diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/aig/cec/cecCore.c | 3 | ||||
-rw-r--r-- | src/aig/gia/gia.h | 7 | ||||
-rw-r--r-- | src/aig/gia/giaCSat0.c | 6 | ||||
-rw-r--r-- | src/aig/gia/giaCSat2.c | 745 | ||||
-rw-r--r-- | src/base/abci/abc.c | 12 | ||||
-rw-r--r-- | src/base/abci/abcLut.c | 2 | ||||
-rw-r--r-- | src/base/abci/abcLutmin.c | 644 | ||||
-rw-r--r-- | src/misc/extra/extra.h | 2 | ||||
-rw-r--r-- | src/misc/extra/extraBddMisc.c | 1 | ||||
-rw-r--r-- | src/opt/mfs/mfsSat.c | 5 |
10 files changed, 1336 insertions, 91 deletions
diff --git a/src/aig/cec/cecCore.c b/src/aig/cec/cecCore.c index 8e66179f..9274dcb8 100644 --- a/src/aig/cec/cecCore.c +++ b/src/aig/cec/cecCore.c @@ -282,6 +282,9 @@ p->timeSim += clock() - clk; // Gia_ManEquivTransform( p->pAig, 1 ); } pSrm = Cec_ManFraSpecReduction( p ); + +// Gia_WriteAiger( pSrm, "gia_srm.aig", 0, 0 ); + if ( pPars->fVeryVerbose ) Gia_ManPrintStats( pSrm ); if ( Gia_ManCoNum(pSrm) == 0 ) diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index 1c3529ba..e3b3f014 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -435,14 +435,15 @@ static inline int * Gia_ObjGateFanins( Gia_Man_t * p, int Id ) { re /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -/*=== giaAig.c ============================================================*/ +/*=== giaAig.c =============================================================*/ extern Gia_Man_t * Gia_ManFromAig( Aig_Man_t * p ); extern Gia_Man_t * Gia_ManFromAigSwitch( Aig_Man_t * p ); extern Aig_Man_t * Gia_ManToAig( Gia_Man_t * p ); -/*=== giaAiger.c ==========================================================*/ +/*=== giaAiger.c ===========================================================*/ extern Gia_Man_t * Gia_ReadAiger( char * pFileName, int fCheck ); extern void Gia_WriteAiger( Gia_Man_t * p, char * pFileName, int fWriteSymbols, int fCompact ); -/*=== giaCof.c ============================================================*/ +/*=== giaCsat.c ============================================================*/ +/*=== giaCof.c =============================================================*/ extern void Gia_ManPrintFanio( Gia_Man_t * pGia, int nNodes ); extern Gia_Man_t * Gia_ManDupCof( Gia_Man_t * p, int iVar ); extern Gia_Man_t * Gia_ManDupCofAllInt( Gia_Man_t * p, Vec_Int_t * vSigs, int fVerbose ); diff --git a/src/aig/gia/giaCSat0.c b/src/aig/gia/giaCSat0.c index 599ad43c..a0d567a2 100644 --- a/src/aig/gia/giaCSat0.c +++ b/src/aig/gia/giaCSat0.c @@ -122,8 +122,10 @@ void Gia_SatVerifyPattern( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vCex, V } Value = Gia_XsimNotCond( Value, Gia_ObjFaninC0(pRoot) ); if ( Value != GIA_ONE ) - printf( "Gia_SatVerifyPattern(): Verification failed.\n" ); - assert( Value == GIA_ONE ); + printf( "Gia_SatVerifyPattern(): Verification FAILED.\n" ); +// else +// printf( "Gia_SatVerifyPattern(): Verification succeeded.\n" ); +// assert( Value == GIA_ONE ); // clean the nodes Gia_ManForEachObjVec( vVisit, p, pObj, i ) Sat_ObjSetXValue( pObj, 0 ); diff --git a/src/aig/gia/giaCSat2.c b/src/aig/gia/giaCSat2.c new file mode 100644 index 00000000..1e7cc949 --- /dev/null +++ b/src/aig/gia/giaCSat2.c @@ -0,0 +1,745 @@ +/**CFile**************************************************************** + + FileName [giaCSat2.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [A simple circuit-based solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaCSat2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Cbs_Par_t_ Cbs_Par_t; +struct Cbs_Par_t_ +{ + // conflict limits + int nBTLimit; // limit on the number of conflicts + int nJustLimit; // limit on the size of justification queue + // current parameters + int nBTThis; // number of conflicts + int nJustThis; // max size of the frontier + int nBTTotal; // total number of conflicts + int nJustTotal; // total size of the frontier + // decision heuristics + int fUseHighest; // use node with the highest ID + int fUseLowest; // use node with the highest ID + int fUseMaxFF; // use node with the largest fanin fanout + // other + int fVerbose; +}; + +typedef struct Cbs_Que_t_ Cbs_Que_t; +struct Cbs_Que_t_ +{ + int iHead; // beginning of the queue + int iTail; // end of the queue + int nSize; // allocated size + Gia_Obj_t ** pData; // nodes stored in the queue +}; + +typedef struct Cbs_Man_t_ Cbs_Man_t; +struct Cbs_Man_t_ +{ + Cbs_Par_t Pars; // parameters + Gia_Man_t * pAig; // AIG manager + Cbs_Que_t pProp; // propagation queue + Cbs_Que_t pJust; // justification queue + Vec_Int_t * vModel; // satisfying assignment +}; + +static inline int Cbs_VarIsAssigned( Gia_Obj_t * pVar ) { return pVar->fMark0; } +static inline void Cbs_VarAssign( Gia_Obj_t * pVar ) { assert(!pVar->fMark0); pVar->fMark0 = 1; } +static inline void Cbs_VarUnassign( Gia_Obj_t * pVar ) { assert(pVar->fMark0); pVar->fMark0 = 0; pVar->fMark1 = 0; } +static inline int Cbs_VarValue( Gia_Obj_t * pVar ) { assert(pVar->fMark0); return pVar->fMark1; } +static inline void Cbs_VarSetValue( Gia_Obj_t * pVar, int v ) { assert(pVar->fMark0); pVar->fMark1 = v; } +static inline int Cbs_VarIsJust( Gia_Obj_t * pVar ) { return Gia_ObjIsAnd(pVar) && !Cbs_VarIsAssigned(Gia_ObjFanin0(pVar)) && !Cbs_VarIsAssigned(Gia_ObjFanin1(pVar)); } +static inline int Cbs_VarFanin0Value( Gia_Obj_t * pVar ) { return !Cbs_VarIsAssigned(Gia_ObjFanin0(pVar)) ? 2 : (Cbs_VarValue(Gia_ObjFanin0(pVar)) ^ Gia_ObjFaninC0(pVar)); } +static inline int Cbs_VarFanin1Value( Gia_Obj_t * pVar ) { return !Cbs_VarIsAssigned(Gia_ObjFanin1(pVar)) ? 2 : (Cbs_VarValue(Gia_ObjFanin1(pVar)) ^ Gia_ObjFaninC1(pVar)); } + +#define Cbs_QueForEachEntry( Que, pObj, i ) \ + for ( i = (Que).iHead; (i < (Que).iTail) && ((pObj) = (Que).pData[i]); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sets default values of the parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs_SetDefaultParams( Cbs_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Cbs_Par_t) ); + pPars->nBTLimit = 1000; // limit on the number of conflicts + pPars->nJustLimit = 100; // limit on the size of justification queue + pPars->fUseHighest = 1; // use node with the highest ID + pPars->fUseLowest = 0; // use node with the highest ID + pPars->fUseMaxFF = 0; // use node with the largest fanin fanout + pPars->fVerbose = 1; // print detailed statistics +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cbs_Man_t * Cbs_ManAlloc() +{ + Cbs_Man_t * p; + p = ABC_CALLOC( Cbs_Man_t, 1 ); + p->pProp.nSize = p->pJust.nSize = 10000; + p->pProp.pData = ABC_ALLOC( Gia_Obj_t *, p->pProp.nSize ); + p->pJust.pData = ABC_ALLOC( Gia_Obj_t *, p->pJust.nSize ); + p->vModel = Vec_IntAlloc( 1000 ); + Cbs_SetDefaultParams( &p->Pars ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs_ManStop( Cbs_Man_t * p ) +{ + Vec_IntFree( p->vModel ); + ABC_FREE( p->pProp.pData ); + ABC_FREE( p->pJust.pData ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Returns satisfying assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cbs_ReadModel( Cbs_Man_t * p ) +{ + return p->vModel; +} + + + + +/**Function************************************************************* + + Synopsis [Returns 1 if the solver is out of limits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs_ManCheckLimits( Cbs_Man_t * p ) +{ + return p->Pars.nJustThis > p->Pars.nJustLimit || p->Pars.nBTThis > p->Pars.nBTLimit; +} + +/**Function************************************************************* + + Synopsis [Saves the satisfying assignment as an array of literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs_ManSaveModel( Cbs_Man_t * p, Vec_Int_t * vCex ) +{ + Gia_Obj_t * pVar; + int i; + Vec_IntClear( vCex ); + p->pProp.iHead = 0; + Cbs_QueForEachEntry( p->pProp, pVar, i ) + if ( Gia_ObjIsCi(pVar) ) + Vec_IntPush( vCex, Gia_Var2Lit(Gia_ObjId(p->pAig,pVar), !Cbs_VarValue(pVar)) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs_QueIsEmpty( Cbs_Que_t * p ) +{ + return p->iHead == p->iTail; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs_QuePush( Cbs_Que_t * p, Gia_Obj_t * pObj ) +{ + if ( p->iTail == p->nSize ) + { + p->nSize *= 2; + p->pData = ABC_REALLOC( Gia_Obj_t *, p->pData, p->nSize ); + } + p->pData[p->iTail++] = pObj; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the object in the queue.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs_QueHasNode( Cbs_Que_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pTemp; + int i; + Cbs_QueForEachEntry( *p, pTemp, i ) + if ( pTemp == pObj ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs_QueStore( Cbs_Que_t * p, int * piHeadOld, int * piTailOld ) +{ + int i; + *piHeadOld = p->iHead; + *piTailOld = p->iTail; + for ( i = *piHeadOld; i < *piTailOld; i++ ) + Cbs_QuePush( p, p->pData[i] ); + p->iHead = *piTailOld; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs_QueRestore( Cbs_Que_t * p, int iHeadOld, int iTailOld ) +{ + p->iHead = iHeadOld; + p->iTail = iTailOld; +} + + +/**Function************************************************************* + + Synopsis [Max number of fanins fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs_VarFaninFanoutMax( Cbs_Man_t * p, Gia_Obj_t * pObj ) +{ + int Count0, Count1; + assert( !Gia_IsComplement(pObj) ); + assert( Gia_ObjIsAnd(pObj) ); + Count0 = Gia_ObjRefs( p->pAig, Gia_ObjFanin0(pObj) ); + Count1 = Gia_ObjRefs( p->pAig, Gia_ObjFanin1(pObj) ); + return ABC_MAX( Count0, Count1 ); +} + +/**Function************************************************************* + + Synopsis [Find variable with the highest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Cbs_ManDecideHighest( Cbs_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMax = NULL; + int i; + Cbs_QueForEachEntry( p->pJust, pObj, i ) + if ( pObjMax == NULL || pObjMax < pObj ) + pObjMax = pObj; + return pObjMax; +} + +/**Function************************************************************* + + Synopsis [Find variable with the lowest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Cbs_ManDecideLowest( Cbs_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMin = NULL; + int i; + Cbs_QueForEachEntry( p->pJust, pObj, i ) + if ( pObjMin == NULL || pObjMin > pObj ) + pObjMin = pObj; + return pObjMin; +} + +/**Function************************************************************* + + Synopsis [Find variable with the maximum number of fanin fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Cbs_ManDecideMaxFF( Cbs_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMax = NULL; + int i, iMaxFF = 0, iCurFF; + assert( p->pAig->pRefs != NULL ); + Cbs_QueForEachEntry( p->pJust, pObj, i ) + { + iCurFF = Cbs_VarFaninFanoutMax( p, pObj ); + assert( iCurFF > 0 ); + if ( iMaxFF < iCurFF ) + { + iMaxFF = iCurFF; + pObjMax = pObj; + } + } + return pObjMax; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs_ManCancelUntil( Cbs_Man_t * p, int iBound ) +{ + Gia_Obj_t * pVar; + int i; + assert( iBound <= p->pProp.iTail ); + p->pProp.iHead = iBound; + Cbs_QueForEachEntry( p->pProp, pVar, i ) + Cbs_VarUnassign( pVar ); + p->pProp.iTail = iBound; +} + +/**Function************************************************************* + + Synopsis [Assigns the variables a value.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs_ManAssign( Cbs_Man_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pObjR = Gia_Regular(pObj); + assert( Gia_ObjIsCand(pObjR) ); + assert( !Cbs_VarIsAssigned(pObjR) ); + Cbs_VarAssign( pObjR ); + Cbs_VarSetValue( pObjR, !Gia_IsComplement(pObj) ); + Cbs_QuePush( &p->pProp, pObjR ); +} + +/**Function************************************************************* + + Synopsis [Propagates a variable.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs_ManPropagateOne( Cbs_Man_t * p, Gia_Obj_t * pVar ) +{ + int Value0, Value1; + assert( !Gia_IsComplement(pVar) ); + assert( Cbs_VarIsAssigned(pVar) ); + if ( Gia_ObjIsCi(pVar) ) + return 0; + assert( Gia_ObjIsAnd(pVar) ); + Value0 = Cbs_VarFanin0Value(pVar); + Value1 = Cbs_VarFanin1Value(pVar); + if ( Cbs_VarValue(pVar) ) + { // value is 1 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + return 1; + if ( Value0 == 2 ) // first is unassigned + Cbs_ManAssign( p, Gia_ObjChild0(pVar) ); + if ( Value1 == 2 ) // first is unassigned + Cbs_ManAssign( p, Gia_ObjChild1(pVar) ); + return 0; + } + // value is 0 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + return 0; + if ( Value0 == 1 && Value1 == 1 ) // both are 1 + return 1; + if ( Value0 == 1 || Value1 == 1 ) // one is 1 + { + if ( Value0 == 2 ) // first is unassigned + Cbs_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)) ); + if ( Value1 == 2 ) // first is unassigned + Cbs_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)) ); + return 0; + } + assert( Cbs_VarIsJust(pVar) ); + assert( !Cbs_QueHasNode( &p->pJust, pVar ) ); + Cbs_QuePush( &p->pJust, pVar ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Propagates a variable.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs_ManPropagateTwo( Cbs_Man_t * p, Gia_Obj_t * pVar ) +{ + int Value0, Value1; + assert( !Gia_IsComplement(pVar) ); + assert( Gia_ObjIsAnd(pVar) ); + assert( Cbs_VarIsAssigned(pVar) ); + assert( !Cbs_VarValue(pVar) ); + Value0 = Cbs_VarFanin0Value(pVar); + Value1 = Cbs_VarFanin1Value(pVar); + // value is 0 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + return 0; + if ( Value0 == 1 && Value1 == 1 ) // both are 1 + return 1; + assert( Value0 == 1 || Value1 == 1 ); + if ( Value0 == 2 ) // first is unassigned + Cbs_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)) ); + if ( Value1 == 2 ) // first is unassigned + Cbs_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)) ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Propagates all variables.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cbs_ManPropagate( Cbs_Man_t * p ) +{ + Gia_Obj_t * pVar; + int i, k; + while ( 1 ) + { + Cbs_QueForEachEntry( p->pProp, pVar, i ) + { + if ( Cbs_ManPropagateOne( p, pVar ) ) + return 1; + } + p->pProp.iHead = p->pProp.iTail; + k = p->pJust.iHead; + Cbs_QueForEachEntry( p->pJust, pVar, i ) + { + if ( Cbs_VarIsJust( pVar ) ) + p->pJust.pData[k++] = pVar; + else if ( Cbs_ManPropagateTwo( p, pVar ) ) + return 1; + } + if ( k == p->pJust.iTail ) + break; + p->pJust.iTail = k; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Solve the problem recursively.] + + Description [Returns 1 if unsat or undecided; 0 if satisfiable.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cbs_ManSolve_rec( Cbs_Man_t * p ) +{ + Gia_Obj_t * pVar; + int iPropHead, iJustHead, iJustTail; + // propagate assignments + assert( !Cbs_QueIsEmpty(&p->pProp) ); + if ( Cbs_ManPropagate( p ) ) + return 1; + // check for satisfying assignment + assert( Cbs_QueIsEmpty(&p->pProp) ); + if ( Cbs_QueIsEmpty(&p->pJust) ) + return 0; + // quit using resource limits + p->Pars.nBTThis++; + p->Pars.nJustThis = ABC_MAX( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); + if ( Cbs_ManCheckLimits( p ) ) + return 1; + // remember the state before branching + iPropHead = p->pProp.iHead; + Cbs_QueStore( &p->pJust, &iJustHead, &iJustTail ); + // find the decision variable + if ( p->Pars.fUseHighest ) + pVar = Cbs_ManDecideHighest( p ); + else if ( p->Pars.fUseLowest ) + pVar = Cbs_ManDecideLowest( p ); + else if ( p->Pars.fUseMaxFF ) + pVar = Cbs_ManDecideMaxFF( p ); + else assert( 0 ); + assert( Cbs_VarIsJust( pVar ) ); + // decide using fanout count! + if ( Gia_ObjRefs(p->pAig, Gia_ObjFanin0(pVar)) < Gia_ObjRefs(p->pAig, Gia_ObjFanin1(pVar)) ) + { + // decide on first fanin + Cbs_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)) ); + if ( !Cbs_ManSolve_rec( p ) ) + return 0; + if ( Cbs_ManCheckLimits( p ) ) + return 1; + Cbs_ManCancelUntil( p, iPropHead ); + Cbs_QueRestore( &p->pJust, iJustHead, iJustTail ); + // decide on second fanin + Cbs_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)) ); + } + else + { + // decide on first fanin + Cbs_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)) ); + if ( !Cbs_ManSolve_rec( p ) ) + return 0; + if ( Cbs_ManCheckLimits( p ) ) + return 1; + Cbs_ManCancelUntil( p, iPropHead ); + Cbs_QueRestore( &p->pJust, iJustHead, iJustTail ); + // decide on second fanin + Cbs_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)) ); + } + if ( !Cbs_ManSolve_rec( p ) ) + return 0; + if ( Cbs_ManCheckLimits( p ) ) + return 1; + return 1; +} + +/**Function************************************************************* + + Synopsis [Looking for a satisfying assignment of the node.] + + Description [Assumes that each node has flag pObj->fMark0 set to 0. + Returns 1 if unsatisfiable, 0 if satisfiable, and -1 if undecided. + The node may be complemented. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cbs_ManSolve( Cbs_Man_t * p, Gia_Obj_t * pObj ) +{ +// Gia_Obj_t * pTemp; +// int i; + int RetValue; +// Gia_ManForEachObj( p->pAig, pTemp, i ) +// assert( pTemp->fMark0 == 0 ); + assert( !p->pProp.iHead && !p->pProp.iTail ); + assert( !p->pJust.iHead && !p->pJust.iTail ); + p->Pars.nBTThis = p->Pars.nJustThis = 0; + Cbs_ManAssign( p, pObj ); + RetValue = Cbs_ManSolve_rec( p ); + if ( RetValue == 0 ) + Cbs_ManSaveModel( p, p->vModel ); + Cbs_ManCancelUntil( p, 0 ); + p->pJust.iHead = p->pJust.iTail = 0; + p->Pars.nBTTotal += p->Pars.nBTThis; + p->Pars.nJustTotal = ABC_MAX( p->Pars.nJustTotal, p->Pars.nJustThis ); + if ( Cbs_ManCheckLimits( p ) ) + return -1; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Procedure to test the new SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs_ManSolveTest( Gia_Man_t * pGia ) +{ + extern void Gia_SatVerifyPattern( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vCex, Vec_Int_t * vVisit ); + int nConfsMax = 1000; + int CountUnsat, CountSat, CountUndec; + Cbs_Man_t * p; + Vec_Int_t * vCex; + Vec_Int_t * vVisit; + Gia_Obj_t * pRoot; + int i, RetValue, clk = clock(); + Gia_ManCreateRefs( pGia ); + // create logic network + p = Cbs_ManAlloc(); + p->pAig = pGia; + // prepare AIG + Gia_ManCleanValue( pGia ); + Gia_ManCleanMark0( pGia ); + Gia_ManCleanMark1( pGia ); +// vCex = Vec_IntAlloc( 100 ); + vVisit = Vec_IntAlloc( 100 ); + // solve for each output + CountUnsat = CountSat = CountUndec = 0; + Gia_ManForEachCo( pGia, pRoot, i ) + { + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) ) + continue; + +// Gia_ManIncrementTravId( pGia ); + +//printf( "Output %6d : ", i ); +// iLit = Gia_Var2Lit( Gia_ObjHandle(Gia_ObjFanin0(pRoot)), Gia_ObjFaninC0(pRoot) ); +// RetValue = Cbs_ManSolve( p, &iLit, 1, nConfsMax, vCex ); + RetValue = Cbs_ManSolve( p, Gia_ObjChild0(pRoot) ); + if ( RetValue == 1 ) + CountUnsat++; + else if ( RetValue == -1 ) + CountUndec++; + else + { + int iLit, k; + vCex = Cbs_ReadModel( p ); + +// printf( "complemented = %d. ", Gia_ObjFaninC0(pRoot) ); +//printf( "conflicts = %6d max-frontier = %6d \n", p->Pars.nBTThis, p->Pars.nJustThis ); +// Vec_IntForEachEntry( vCex, iLit, k ) +// printf( "%s%d ", Gia_LitIsCompl(iLit)? "!": "", Gia_ObjCioId(Gia_ManObj(pGia,Gia_Lit2Var(iLit))) ); +// printf( "\n" ); + + Gia_SatVerifyPattern( pGia, pRoot, vCex, vVisit ); + assert( RetValue == 0 ); + CountSat++; + } +// Gia_ManCheckMark0( p ); +// Gia_ManCheckMark1( p ); + } + Cbs_ManStop( p ); +// Vec_IntFree( vCex ); + Vec_IntFree( vVisit ); + printf( "Unsat = %d. Sat = %d. Undec = %d. ", CountUnsat, CountSat, CountUndec ); + ABC_PRT( "Time", clock() - clk ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index b5e23856..556828cb 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -3729,8 +3729,8 @@ int Abc_CommandLutmin( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - nLutSize = 6; - fVerbose = 1; + nLutSize = 4; + fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Kvh" ) ) != EOF ) { @@ -3744,8 +3744,6 @@ int Abc_CommandLutmin( Abc_Frame_t * pAbc, int argc, char ** argv ) } nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( nLutSize > 1 ) - goto usage; break; case 'v': fVerbose ^= 1; @@ -23956,6 +23954,7 @@ int Abc_CommandAbc9Test( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_Man_t * pTemp = NULL; int c, fVerbose = 0; extern void Gia_SatSolveTest( Gia_Man_t * p ); + extern void Cbs_ManSolveTest( Gia_Man_t * pGia ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) @@ -23983,8 +23982,9 @@ int Abc_CommandAbc9Test( Abc_Frame_t * pAbc, int argc, char ** argv ) // Gia_SatSolveTest( pAbc->pAig ); // For_ManExperiment( pAbc->pAig, 20, 1, 1 ); // Gia_ManUnrollSpecial( pAbc->pAig, 5, 100, 1 ); - pAbc->pAig = Gia_ManDupSelf( pTemp = pAbc->pAig ); - Gia_ManStop( pTemp ); +// pAbc->pAig = Gia_ManDupSelf( pTemp = pAbc->pAig ); +// Gia_ManStop( pTemp ); +// Cbs_ManSolveTest( pAbc->pAig ); return 0; usage: diff --git a/src/base/abci/abcLut.c b/src/base/abci/abcLut.c index bb45f6c4..089f4107 100644 --- a/src/base/abci/abcLut.c +++ b/src/base/abci/abcLut.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "abc.h" -#include "cut.h" +#include "cut.h" #define LARGE_LEVEL 1000000 diff --git a/src/base/abci/abcLutmin.c b/src/base/abci/abcLutmin.c index 6906e2c4..41ee25fe 100644 --- a/src/base/abci/abcLutmin.c +++ b/src/base/abci/abcLutmin.c @@ -20,6 +20,12 @@ #include "abc.h" +/* + Implememented here is the algorithm for minimal-LUT decomposition + described in the paper: T. Sasao et al. "On the number of LUTs + to implement logic functions", To appear in Proc. IWLS'09. +*/ + //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// @@ -30,6 +36,254 @@ /**Function************************************************************* + Synopsis [Implements 2:1 MUX using one 3-LUT.] + + Description [The fanins are (c, d0, d1).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkBddMux21( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] ) +{ + DdManager * dd = pNtkNew->pManFunc; + Abc_Obj_t * pNode; + DdNode * bSpin, * bCof0, * bCof1; + pNode = Abc_NtkCreateNode( pNtkNew ); + Abc_ObjAddFanin( pNode, pFanins[0] ); + Abc_ObjAddFanin( pNode, pFanins[1] ); + Abc_ObjAddFanin( pNode, pFanins[2] ); + bSpin = Cudd_bddIthVar(dd, 0); + bCof0 = Cudd_bddIthVar(dd, 1); + bCof1 = Cudd_bddIthVar(dd, 2); + pNode->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 ); Cudd_Ref( pNode->pData ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Implements 4:1 MUX using one 6-LUT.] + + Description [The fanins are (c0, c1, d00, d01, d10, d11).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkBddMux411( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] ) +{ + DdManager * dd = pNtkNew->pManFunc; + Abc_Obj_t * pNode; + DdNode * bSpin, * bCof0, * bCof1; + pNode = Abc_NtkCreateNode( pNtkNew ); + Abc_ObjAddFanin( pNode, pFanins[0] ); + Abc_ObjAddFanin( pNode, pFanins[1] ); + Abc_ObjAddFanin( pNode, pFanins[2] ); + Abc_ObjAddFanin( pNode, pFanins[3] ); + Abc_ObjAddFanin( pNode, pFanins[4] ); + Abc_ObjAddFanin( pNode, pFanins[5] ); + bSpin = Cudd_bddIthVar(dd, 1); + bCof0 = Cudd_bddIte( dd, bSpin, Cudd_bddIthVar(dd, 3), Cudd_bddIthVar(dd, 2) ); Cudd_Ref( bCof0 ); + bCof1 = Cudd_bddIte( dd, bSpin, Cudd_bddIthVar(dd, 5), Cudd_bddIthVar(dd, 4) ); Cudd_Ref( bCof1 ); + bSpin = Cudd_bddIthVar(dd, 0); + pNode->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 ); Cudd_Ref( pNode->pData ); + Cudd_RecursiveDeref( dd, bCof0 ); + Cudd_RecursiveDeref( dd, bCof1 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Implementes 4:1 MUX using two 4-LUTs.] + + Description [The fanins are (c0, c1, d00, d01, d10, d11).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkBddMux412( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] ) +{ + DdManager * dd = pNtkNew->pManFunc; + Abc_Obj_t * pNodeBot, * pNodeTop; + DdNode * bSpin, * bCof0, * bCof1; + // bottom node + pNodeBot = Abc_NtkCreateNode( pNtkNew ); + Abc_ObjAddFanin( pNodeBot, pFanins[0] ); + Abc_ObjAddFanin( pNodeBot, pFanins[1] ); + Abc_ObjAddFanin( pNodeBot, pFanins[2] ); + Abc_ObjAddFanin( pNodeBot, pFanins[3] ); + bSpin = Cudd_bddIthVar(dd, 0); + bCof0 = Cudd_bddIte( dd, Cudd_bddIthVar(dd, 1), Cudd_bddIthVar(dd, 3), Cudd_bddIthVar(dd, 2) ); Cudd_Ref( bCof0 ); + bCof1 = Cudd_bddIthVar(dd, 1); + pNodeBot->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 ); Cudd_Ref( pNodeBot->pData ); + Cudd_RecursiveDeref( dd, bCof0 ); + // top node + pNodeTop = Abc_NtkCreateNode( pNtkNew ); + Abc_ObjAddFanin( pNodeTop, pFanins[0] ); + Abc_ObjAddFanin( pNodeTop, pNodeBot ); + Abc_ObjAddFanin( pNodeTop, pFanins[4] ); + Abc_ObjAddFanin( pNodeTop, pFanins[5] ); + bSpin = Cudd_bddIthVar(dd, 0); + bCof0 = Cudd_bddIthVar(dd, 1); + bCof1 = Cudd_bddIte( dd, Cudd_bddIthVar(dd, 1), Cudd_bddIthVar(dd, 3), Cudd_bddIthVar(dd, 2) ); Cudd_Ref( bCof1 ); + pNodeTop->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 ); Cudd_Ref( pNodeTop->pData ); + Cudd_RecursiveDeref( dd, bCof1 ); + return pNodeTop; +} + +/**Function************************************************************* + + Synopsis [Implementes 4:1 MUX using two 4-LUTs.] + + Description [The fanins are (c0, c1, d00, d01, d10, d11).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkBddMux412a( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] ) +{ + DdManager * dd = pNtkNew->pManFunc; + Abc_Obj_t * pNodeBot, * pNodeTop; + DdNode * bSpin, * bCof0, * bCof1; + // bottom node + pNodeBot = Abc_NtkCreateNode( pNtkNew ); + Abc_ObjAddFanin( pNodeBot, pFanins[1] ); + Abc_ObjAddFanin( pNodeBot, pFanins[2] ); + Abc_ObjAddFanin( pNodeBot, pFanins[3] ); + bSpin = Cudd_bddIthVar(dd, 0); + bCof0 = Cudd_bddIthVar(dd, 1); + bCof1 = Cudd_bddIthVar(dd, 2); + pNodeBot->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 ); Cudd_Ref( pNodeBot->pData ); + // top node + pNodeTop = Abc_NtkCreateNode( pNtkNew ); + Abc_ObjAddFanin( pNodeTop, pFanins[0] ); + Abc_ObjAddFanin( pNodeTop, pFanins[1] ); + Abc_ObjAddFanin( pNodeTop, pNodeBot ); + Abc_ObjAddFanin( pNodeTop, pFanins[4] ); + Abc_ObjAddFanin( pNodeTop, pFanins[5] ); + bSpin = Cudd_bddIthVar(dd, 0); + bCof0 = Cudd_bddIthVar(dd, 2); + bCof1 = Cudd_bddIte( dd, Cudd_bddIthVar(dd, 1), Cudd_bddIthVar(dd, 4), Cudd_bddIthVar(dd, 3) ); Cudd_Ref( bCof1 ); + pNodeTop->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 ); Cudd_Ref( pNodeTop->pData ); + Cudd_RecursiveDeref( dd, bCof1 ); + return pNodeTop; +} + +/**Function************************************************************* + + Synopsis [Implements 4:1 MUX using three 2:1 MUXes.] + + Description [The fanins are (c0, c1, d00, d01, d10, d11).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkBddMux413( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] ) +{ + Abc_Obj_t * pNodesBot[3], * pNodesTop[3]; + // left bottom + pNodesBot[0] = pFanins[1]; + pNodesBot[1] = pFanins[2]; + pNodesBot[2] = pFanins[3]; + pNodesTop[1] = Abc_NtkBddMux21( pNtkNew, pNodesBot ); + // right bottom + pNodesBot[0] = pFanins[1]; + pNodesBot[1] = pFanins[4]; + pNodesBot[2] = pFanins[5]; + pNodesTop[2] = Abc_NtkBddMux21( pNtkNew, pNodesBot ); + // top node + pNodesTop[0] = pFanins[0]; + return Abc_NtkBddMux21( pNtkNew, pNodesTop ); +} + +/**Function************************************************************* + + Synopsis [Finds unique cofactors of the function on the given level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_NtkBddCofactors_rec( DdManager * dd, DdNode * bNode, int iCof, int iLevel, int nLevels ) +{ + DdNode * bNode0, * bNode1; + if ( Cudd_IsConstant(bNode) || iLevel == nLevels ) + return bNode; + if ( Cudd_ReadPerm( dd, Cudd_NodeReadIndex(bNode) ) > iLevel ) + { + bNode0 = bNode; + bNode1 = bNode; + } + else if ( Cudd_IsComplement(bNode) ) + { + bNode0 = Cudd_Not(cuddE(Cudd_Regular(bNode))); + bNode1 = Cudd_Not(cuddT(Cudd_Regular(bNode))); + } + else + { + bNode0 = cuddE(bNode); + bNode1 = cuddT(bNode); + } + if ( (iCof >> (nLevels-1-iLevel)) & 1 ) + return Abc_NtkBddCofactors_rec( dd, bNode1, iCof, iLevel + 1, nLevels ); + return Abc_NtkBddCofactors_rec( dd, bNode0, iCof, iLevel + 1, nLevels ); +} + +/**Function************************************************************* + + Synopsis [Finds unique cofactors of the function on the given level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkBddCofactors( DdManager * dd, DdNode * bNode, int Level ) +{ + Vec_Ptr_t * vCofs; + int i, nCofs = (1<<Level); + assert( Level > 0 && Level < 10 ); + vCofs = Vec_PtrAlloc( 8 ); + for ( i = 0; i < nCofs; i++ ) + Vec_PtrPush( vCofs, Abc_NtkBddCofactors_rec( dd, bNode, i, 0, Level ) ); + return vCofs; +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two integers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Vec_PtrSortCompare( void ** pp1, void ** pp2 ) +{ + if ( *pp1 < *pp2 ) + return -1; + if ( *pp1 > *pp2 ) + return 1; + return 0; +} + +/**Function************************************************************* + Synopsis [Converts the node to MUXes.] Description [] @@ -39,27 +293,43 @@ SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NtkCreateNodeLut( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bFunc, Abc_Obj_t * pNode, int nLutSize ) +Abc_Obj_t * Abc_NtkCreateCofLut( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bCof, Abc_Obj_t * pNode, int Level ) { + int fVerbose = 0; DdNode * bFuncNew; Abc_Obj_t * pNodeNew; - int i, nStart = ABC_MIN( 0, Abc_ObjFaninNum(pNode) - nLutSize ); + int i; + assert( Abc_ObjFaninNum(pNode) > Level ); // create a new node pNodeNew = Abc_NtkCreateNode( pNtkNew ); // add the fanins in the order, in which they appear in the reordered manager - for ( i = nStart; i < Abc_ObjFaninNum(pNode); i++ ) + for ( i = Level; i < Abc_ObjFaninNum(pNode); i++ ) Abc_ObjAddFanin( pNodeNew, Abc_ObjFanin(pNode, i)->pCopy ); +if ( fVerbose ) +{ +Extra_bddPrint( dd, bCof ); +printf( "\n" ); +printf( "\n" ); +} // transfer the function - bFuncNew = Extra_bddMove( dd, bFunc, nStart ); Cudd_Ref( bFuncNew ); - assert( Cudd_SupportSize(dd, bFuncNew) <= nLutSize ); + bFuncNew = Extra_bddMove( dd, bCof, -Level ); Cudd_Ref( bFuncNew ); +if ( fVerbose ) +{ +Extra_bddPrint( dd, bFuncNew ); +printf( "\n" ); +printf( "\n" ); +} pNodeNew->pData = Extra_TransferLevelByLevel( dd, pNtkNew->pManFunc, bFuncNew ); Cudd_Ref( pNodeNew->pData ); +//Extra_bddPrint( pNtkNew->pManFunc, pNodeNew->pData ); +//printf( "\n" ); +//printf( "\n" ); Cudd_RecursiveDeref( dd, bFuncNew ); return pNodeNew; } /**Function************************************************************* - Synopsis [Converts the node to MUXes.] + Synopsis [Performs one step of Ashenhurst-Curtis decomposition.] Description [] @@ -68,36 +338,164 @@ Abc_Obj_t * Abc_NtkCreateNodeLut( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NodeBddToMuxesLut_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * pNtkNew, st_table * tBdd2Node, Abc_Obj_t * pNode, int nLutSize ) -{ - Abc_Obj_t * pNodeNew, * pNodeNew0, * pNodeNew1, * pNodeNewC; - assert( !Cudd_IsComplement(bFunc) ); - if ( bFunc == b1 ) - return Abc_NtkCreateNodeConst1(pNtkNew); - if ( st_lookup( tBdd2Node, (char *)bFunc, (char **)&pNodeNew ) ) - return pNodeNew; - if ( dd->perm[bFunc->index] >= Abc_ObjFaninNum(pNode) - nLutSize ) - { - pNodeNew = Abc_NtkCreateNodeLut( pNtkNew, dd, bFunc, pNode, nLutSize ); - st_insert( tBdd2Node, (char *)bFunc, (char *)pNodeNew ); - return pNodeNew; - } - // solve for the children nodes - pNodeNew0 = Abc_NodeBddToMuxesLut_rec( dd, Cudd_Regular(cuddE(bFunc)), pNtkNew, tBdd2Node, pNode, nLutSize ); - if ( Cudd_IsComplement(cuddE(bFunc)) ) - pNodeNew0 = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew0 ); - pNodeNew1 = Abc_NodeBddToMuxesLut_rec( dd, cuddT(bFunc), pNtkNew, tBdd2Node, pNode, nLutSize ); - if ( !st_lookup( tBdd2Node, (char *)Cudd_bddIthVar(dd, bFunc->index), (char **)&pNodeNewC ) ) - assert( 0 ); - // create the MUX node - pNodeNew = Abc_NtkCreateNodeMux( pNtkNew, pNodeNewC, pNodeNew1, pNodeNew0 ); - st_insert( tBdd2Node, (char *)bFunc, (char *)pNodeNew ); +Abc_Obj_t * Abc_NtkBddCurtis( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vCofs, Vec_Ptr_t * vUniq ) +{ + DdManager * ddOld = pNode->pNtk->pManFunc; + DdManager * ddNew = pNtkNew->pManFunc; + DdNode * bCof, * bUniq, * bMint, * bTemp, * bFunc, * bBits[10], ** pbCodeVars; + Abc_Obj_t * pNodeNew = NULL, * pNodeBS[10]; + int nLutSize = Extra_Base2Log( Vec_PtrSize(vCofs) ); + int nBits = Extra_Base2Log( Vec_PtrSize(vUniq) ); + int b, c, u, i; + assert( nBits + 2 <= nLutSize ); + assert( nLutSize < Abc_ObjFaninNum(pNode) ); + // start BDDs for the decompoosed blocks + for ( b = 0; b < nBits; b++ ) + bBits[b] = Cudd_ReadLogicZero(ddNew), Cudd_Ref( bBits[b] ); + // add each bound set minterm to one of the blccks + Vec_PtrForEachEntry( vCofs, bCof, c ) + { + Vec_PtrForEachEntry( vUniq, bUniq, u ) + if ( bUniq == bCof ) + break; + assert( u < Vec_PtrSize(vUniq) ); + for ( b = 0; b < nBits; b++ ) + { + if ( ((u >> b) & 1) == 0 ) + continue; + bMint = Extra_bddBitsToCube( ddNew, c, nLutSize, ddNew->vars, 1 ); Cudd_Ref( bMint ); + bBits[b] = Cudd_bddOr( ddNew, bTemp = bBits[b], bMint ); Cudd_Ref( bBits[b] ); + Cudd_RecursiveDeref( ddNew, bTemp ); + Cudd_RecursiveDeref( ddNew, bMint ); + } + } + // create bound set nodes + for ( b = 0; b < nBits; b++ ) + { + pNodeBS[b] = Abc_NtkCreateNode( pNtkNew ); + for ( i = 0; i < nLutSize; i++ ) + Abc_ObjAddFanin( pNodeBS[b], Abc_ObjFanin(pNode, i)->pCopy ); + pNodeBS[b]->pData = bBits[b]; // takes ref + } + // create composition node + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + // add free set variables first + for ( i = nLutSize; i < Abc_ObjFaninNum(pNode); i++ ) + Abc_ObjAddFanin( pNodeNew, Abc_ObjFanin(pNode, i)->pCopy ); + // add code bit variables next + for ( b = 0; b < nBits; b++ ) + Abc_ObjAddFanin( pNodeNew, pNodeBS[b] ); + // derive function of the composition node + bFunc = Cudd_ReadLogicZero(ddNew); Cudd_Ref( bFunc ); + pbCodeVars = ddNew->vars + Abc_ObjFaninNum(pNode) - nLutSize; + Vec_PtrForEachEntry( vUniq, bUniq, u ) + { + bUniq = Extra_bddMove( ddOld, bUniq, -nLutSize ); Cudd_Ref( bUniq ); + bUniq = Extra_TransferLevelByLevel( ddOld, ddNew, bTemp = bUniq ); Cudd_Ref( bUniq ); + Cudd_RecursiveDeref( ddOld, bTemp ); + + bMint = Extra_bddBitsToCube( ddNew, u, nBits, pbCodeVars, 0 ); Cudd_Ref( bMint ); + bMint = Cudd_bddAnd( ddNew, bTemp = bMint, bUniq ); Cudd_Ref( bMint ); + Cudd_RecursiveDeref( ddNew, bTemp ); + Cudd_RecursiveDeref( ddNew, bUniq ); + + bFunc = Cudd_bddOr( ddNew, bTemp = bFunc, bMint ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( ddNew, bTemp ); + Cudd_RecursiveDeref( ddNew, bMint ); + } + pNodeNew->pData = bFunc; // takes ref return pNodeNew; } /**Function************************************************************* - Synopsis [Converts the node to MUXes.] + Synopsis [Tries to decompose using cofactoring into two LUTs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkBddFindCofactor( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int nLutSize ) +{ + Abc_Obj_t * pNodeBot, * pNodeTop; + DdManager * ddOld = pNode->pNtk->pManFunc; + DdManager * ddNew = pNtkNew->pManFunc; + DdNode * bCof0, * bCof1, * bSupp, * bTemp, * bVar; + DdNode * bCof0n, * bCof1n; + int i, iCof, iFreeVar, fCof1Smaller = -1; + assert( Abc_ObjFaninNum(pNode) == nLutSize + 1 ); + for ( iCof = 0; iCof < Abc_ObjFaninNum(pNode); iCof++ ) + { + bVar = Cudd_bddIthVar( ddOld, iCof ); + bCof0 = Cudd_Cofactor( ddOld, pNode->pData, Cudd_Not(bVar) ); Cudd_Ref( bCof0 ); + bCof1 = Cudd_Cofactor( ddOld, pNode->pData, bVar ); Cudd_Ref( bCof1 ); + if ( Cudd_SupportSize( ddOld, bCof0 ) <= nLutSize - 2 ) + { + fCof1Smaller = 0; + break; + } + if ( Cudd_SupportSize( ddOld, bCof1 ) <= nLutSize - 2 ) + { + fCof1Smaller = 1; + break; + } + Cudd_RecursiveDeref( ddOld, bCof0 ); + Cudd_RecursiveDeref( ddOld, bCof1 ); + } + if ( iCof == Abc_ObjFaninNum(pNode) ) + return NULL; + // find unused variable + bSupp = Cudd_Support( ddOld, fCof1Smaller? bCof1 : bCof0 ); Cudd_Ref( bSupp ); + iFreeVar = -1; + for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) + { + assert( i == Cudd_ReadPerm(ddOld, i) ); + if ( i == iCof ) + continue; + for ( bTemp = bSupp; !Cudd_IsConstant(bTemp); bTemp = cuddT(bTemp) ) + if ( i == (int)Cudd_NodeReadIndex(bTemp) ) + break; + if ( Cudd_IsConstant(bTemp) ) + { + iFreeVar = i; + break; + } + } + assert( iFreeVar != iCof && iFreeVar < Abc_ObjFaninNum(pNode) ); + Cudd_RecursiveDeref( ddOld, bSupp ); + // transfer the cofactors + bCof0n = Extra_TransferLevelByLevel( ddOld, ddNew, bCof0 ); Cudd_Ref( bCof0n ); + bCof1n = Extra_TransferLevelByLevel( ddOld, ddNew, bCof1 ); Cudd_Ref( bCof1n ); + Cudd_RecursiveDeref( ddOld, bCof0 ); + Cudd_RecursiveDeref( ddOld, bCof1 ); + // create bottom node + pNodeBot = Abc_NtkCreateNode( pNtkNew ); + for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) + Abc_ObjAddFanin( pNodeBot, Abc_ObjFanin(pNode, i)->pCopy ); + pNodeBot->pData = fCof1Smaller? bCof0n : bCof1n; + // create top node + pNodeTop = Abc_NtkCreateNode( pNtkNew ); + for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) + if ( i == iFreeVar ) + Abc_ObjAddFanin( pNodeTop, pNodeBot ); + else + Abc_ObjAddFanin( pNodeTop, Abc_ObjFanin(pNode, i)->pCopy ); + // derive the new function + pNodeTop->pData = Cudd_bddIte( ddNew, + Cudd_bddIthVar(ddNew, iCof), + fCof1Smaller? bCof1n : Cudd_bddIthVar(ddNew, iFreeVar), + fCof1Smaller? Cudd_bddIthVar(ddNew, iFreeVar) : bCof0n ); + Cudd_Ref( pNodeTop->pData ); + Cudd_RecursiveDeref( ddNew, fCof1Smaller? bCof1n : bCof0n ); + return pNodeTop; +} + +/**Function************************************************************* + + Synopsis [Decompose the function once.] Description [] @@ -106,23 +504,64 @@ Abc_Obj_t * Abc_NodeBddToMuxesLut_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NodeBddToMuxesLut( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, int nLutSize ) +Abc_Obj_t * Abc_NtkBddDecompose( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int nLutSize, int fVerbose ) { - DdManager * dd = pNodeOld->pNtk->pManFunc; - DdNode * bFunc = pNodeOld->pData; - Abc_Obj_t * pFaninOld, * pNodeNew; - st_table * tBdd2Node; + Vec_Ptr_t * vCofs, * vUniq; + DdManager * dd = pNode->pNtk->pManFunc; + DdNode * bCof; + Abc_Obj_t * pNodeNew = NULL; + Abc_Obj_t * pCofs[20]; int i; - // create the table mapping BDD nodes into the ABC nodes - tBdd2Node = st_init_table( st_ptrcmp, st_ptrhash ); - // add the constant and the elementary vars - Abc_ObjForEachFanin( pNodeOld, pFaninOld, i ) - st_insert( tBdd2Node, (char *)Cudd_bddIthVar(dd, i), (char *)pFaninOld->pCopy ); - // create the new nodes recursively - pNodeNew = Abc_NodeBddToMuxesLut_rec( dd, Cudd_Regular(bFunc), pNtkNew, tBdd2Node, pNodeOld, nLutSize ); - st_free_table( tBdd2Node ); - if ( Cudd_IsComplement(bFunc) ) - pNodeNew = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew ); + assert( Abc_ObjFaninNum(pNode) > nLutSize ); + // try to decompose with two LUTs (the best case for Supp = LutSize + 1) + if ( Abc_ObjFaninNum(pNode) == nLutSize + 1 ) + { + + pNodeNew = Abc_NtkBddFindCofactor( pNtkNew, pNode, nLutSize ); + if ( pNodeNew != NULL ) + { + if ( fVerbose ) + printf( "Decomposing %d-input node %d using MUX.\n", + Abc_ObjFaninNum(pNode), Abc_ObjId(pNode) ); + return pNodeNew; + } + + } + // cofactor w.r.t. the bound set variables + vCofs = Abc_NtkBddCofactors( dd, pNode->pData, nLutSize ); + vUniq = Vec_PtrDup( vCofs ); + Vec_PtrUniqify( vUniq, (int (*)())Vec_PtrSortCompare ); + // only perform decomposition with it is support reduring with two less vars + if( Vec_PtrSize(vUniq) > (1 << (nLutSize-2)) ) + { + Vec_PtrFree( vCofs ); + vCofs = Abc_NtkBddCofactors( dd, pNode->pData, 2 ); + if ( fVerbose ) + printf( "Decomposing %d-input node %d using cofactoring with %d cofactors.\n", + Abc_ObjFaninNum(pNode), Abc_ObjId(pNode), Vec_PtrSize(vCofs) ); + // implement the cofactors + pCofs[0] = Abc_ObjFanin(pNode, 0)->pCopy; + pCofs[1] = Abc_ObjFanin(pNode, 1)->pCopy; + Vec_PtrForEachEntry( vCofs, bCof, i ) + pCofs[2+i] = Abc_NtkCreateCofLut( pNtkNew, dd, bCof, pNode, 2 ); + if ( nLutSize == 4 ) + pNodeNew = Abc_NtkBddMux412( pNtkNew, pCofs ); + else if ( nLutSize == 5 ) + pNodeNew = Abc_NtkBddMux412a( pNtkNew, pCofs ); + else if ( nLutSize == 6 ) + pNodeNew = Abc_NtkBddMux411( pNtkNew, pCofs ); + else assert( 0 ); + } + // alternative decompose using MUX-decomposition + else + { + if ( fVerbose ) + printf( "Decomposing %d-input node %d using Curtis with %d unique columns.\n", + Abc_ObjFaninNum(pNode), Abc_ObjId(pNode), Vec_PtrSize(vUniq) ); + pNodeNew = Abc_NtkBddCurtis( pNtkNew, pNode, vCofs, vUniq ); + } + Vec_PtrFree( vCofs ); + Vec_PtrFree( vUniq ); return pNodeNew; } @@ -137,20 +576,24 @@ Abc_Obj_t * Abc_NodeBddToMuxesLut( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, in SeeAlso [] ***********************************************************************/ -void Abc_NtkLutminConstruct( Abc_Ntk_t * pNtkClp, Abc_Ntk_t * pNtkDec, int nLutSize ) +void Abc_NtkLutminConstruct( Abc_Ntk_t * pNtkClp, Abc_Ntk_t * pNtkDec, int nLutSize, int fVerbose ) { - Abc_Obj_t * pObj, * pDriver; - int i; - Abc_NtkForEachCo( pNtkClp, pObj, i ) + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode, * pFanin; + int i, k; + vNodes = Abc_NtkDfs( pNtkClp, 0 ); + Vec_PtrForEachEntry( vNodes, pNode, i ) { - pDriver = Abc_ObjFanin0( pObj ); - if ( !Abc_ObjIsNode(pDriver) ) - continue; - if ( Abc_ObjFaninNum(pDriver) == 0 ) - pDriver->pCopy = Abc_NtkDupObj( pNtkDec, pDriver, 0 ); + if ( Abc_ObjFaninNum(pNode) <= nLutSize ) + { + pNode->pCopy = Abc_NtkDupObj( pNtkDec, pNode, 0 ); + Abc_ObjForEachFanin( pNode, pFanin, k ) + Abc_ObjAddFanin( pNode->pCopy, pFanin->pCopy ); + } else - pDriver->pCopy = Abc_NodeBddToMuxesLut( pNtkDec, pDriver, nLutSize ); + pNode->pCopy = Abc_NtkBddDecompose( pNtkDec, pNode, nLutSize, fVerbose ); } + Vec_PtrFree( vNodes ); } /**Function************************************************************* @@ -164,42 +607,87 @@ void Abc_NtkLutminConstruct( Abc_Ntk_t * pNtkClp, Abc_Ntk_t * pNtkDec, int nLutS SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ) +Abc_Ntk_t * Abc_NtkLutminInt( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ) { extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ); - Abc_Ntk_t * pNtkDec, * pNtkClp, * pTemp; - // collapse the network and reorder BDDs - if ( Abc_NtkIsStrash(pNtk) ) - pTemp = Abc_NtkDup( pNtk ); - else - pTemp = Abc_NtkStrash( pNtk, 0, 1, 0 ); - pNtkClp = Abc_NtkCollapse( pTemp, 10000, 0, 1, 0 ); - Abc_NtkDelete( pTemp ); - if ( pNtkClp == NULL ) - return NULL; - if ( !Abc_NtkIsBddLogic(pNtkClp) ) - Abc_NtkToBdd( pNtkClp ); - Abc_NtkBddReorder( pNtkClp, fVerbose ); + Abc_Ntk_t * pNtkDec; + // minimize BDDs +// Abc_NtkBddReorder( pNtk, fVerbose ); + Abc_NtkBddReorder( pNtk, 0 ); // decompose one output at a time - pNtkDec = Abc_NtkStartFrom( pNtkClp, ABC_NTK_LOGIC, ABC_FUNC_BDD ); + pNtkDec = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); // make sure the new manager has enough inputs - Cudd_bddIthVar( pNtkDec->pManFunc, nLutSize ); + Cudd_bddIthVar( pNtkDec->pManFunc, Abc_NtkGetFaninMax(pNtk) ); // put the results into the new network (save new CO drivers in old CO drivers) - Abc_NtkLutminConstruct( pNtkClp, pNtkDec, nLutSize ); + Abc_NtkLutminConstruct( pNtk, pNtkDec, nLutSize, fVerbose ); // finalize the new network - Abc_NtkFinalize( pNtkClp, pNtkDec ); - Abc_NtkDelete( pNtkClp ); + Abc_NtkFinalize( pNtk, pNtkDec ); // make the network minimum base Abc_NtkMinimumBase( pNtkDec ); + return pNtkDec; +} + +/**Function************************************************************* + + Synopsis [Performs minimum-LUT decomposition of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtkInit, int nLutSize, int fVerbose ) +{ + extern bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); + Abc_Ntk_t * pNtkNew, * pTemp; + int i; + if ( nLutSize < 4 ) + { + printf( "The LUT count (%d) should be at least 4.\n", nLutSize ); + return NULL; + } + if ( nLutSize > 6 ) + { + printf( "The LUT count (%d) should not exceed 6.\n", nLutSize ); + return NULL; + } + // create internal representation + if ( Abc_NtkIsStrash(pNtkInit) ) + pNtkNew = Abc_NtkDup( pNtkInit ); + else + pNtkNew = Abc_NtkStrash( pNtkInit, 0, 1, 0 ); + // collapse the network + pNtkNew = Abc_NtkCollapse( pTemp = pNtkNew, 10000, 0, 1, 0 ); + Abc_NtkDelete( pTemp ); + if ( pNtkNew == NULL ) + return NULL; + // convert it to BDD + if ( !Abc_NtkIsBddLogic(pNtkNew) ) + Abc_NtkToBdd( pNtkNew ); + // iterate decomposition + for ( i = 0; Abc_NtkGetFaninMax(pNtkNew) > nLutSize; i++ ) + { + if ( fVerbose ) + printf( "*** Iteration %d:\n", i+1 ); + if ( fVerbose ) + printf( "Decomposing network with %d nodes and %d max fanin count for K = %d.\n", + Abc_NtkNodeNum(pNtkNew), Abc_NtkGetFaninMax(pNtkNew), nLutSize ); + pNtkNew = Abc_NtkLutminInt( pTemp = pNtkNew, nLutSize, fVerbose ); + Abc_NtkDelete( pTemp ); + } // fix the problem with complemented and duplicated CO edges - Abc_NtkLogicMakeSimpleCos( pNtkDec, 0 ); + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + // merge functionally equivalent nodes + Abc_NtkFraigSweep( pNtkNew, 1, 0, 0, 0 ); // make sure everything is okay - if ( !Abc_NtkCheck( pNtkDec ) ) + if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkLutmin: The network check has failed.\n" ); return 0; } - return pNtkDec; + return pNtkNew; } //////////////////////////////////////////////////////////////////////// diff --git a/src/misc/extra/extra.h b/src/misc/extra/extra.h index f81479b3..dc2c2b0b 100644 --- a/src/misc/extra/extra.h +++ b/src/misc/extra/extra.h @@ -169,7 +169,7 @@ extern DdNode * Extra_bddImageRead2( Extra_ImageTree2_t * pTree ); extern DdNode * Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ); extern DdNode * Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f ); extern DdNode * Extra_bddRemapUp( DdManager * dd, DdNode * bF ); -extern DdNode * Extra_bddMove( DdManager * dd, DdNode * bF, int fShiftUp ); +extern DdNode * Extra_bddMove( DdManager * dd, DdNode * bF, int nVars ); extern DdNode * extraBddMove( DdManager * dd, DdNode * bF, DdNode * bFlag ); extern void Extra_StopManager( DdManager * dd ); extern void Extra_bddPrint( DdManager * dd, DdNode * F ); diff --git a/src/misc/extra/extraBddMisc.c b/src/misc/extra/extraBddMisc.c index e17d1744..0c285fc7 100644 --- a/src/misc/extra/extraBddMisc.c +++ b/src/misc/extra/extraBddMisc.c @@ -221,6 +221,7 @@ void Extra_StopManager( DdManager * dd ) // check for remaining references in the package RetValue = Cudd_CheckZeroRef( dd ); if ( RetValue > 10 ) +// if ( RetValue ) printf( "\nThe number of referenced nodes = %d\n\n", RetValue ); // Cudd_PrintInfo( dd, stdout ); Cudd_Quit( dd ); diff --git a/src/opt/mfs/mfsSat.c b/src/opt/mfs/mfsSat.c index a35d67e4..eab80c53 100644 --- a/src/opt/mfs/mfsSat.c +++ b/src/opt/mfs/mfsSat.c @@ -43,11 +43,16 @@ int Abc_NtkMfsSolveSat_iter( Mfs_Man_t * p ) { int Lits[MFS_FANIN_MAX]; int RetValue, nBTLimit, iVar, b, Mint; +// int nConfs = p->pSat->stats.conflicts; if ( p->nTotConfLim && p->nTotConfLim <= p->pSat->stats.conflicts ) return -1; nBTLimit = p->nTotConfLim? p->nTotConfLim - p->pSat->stats.conflicts : 0; RetValue = sat_solver_solve( p->pSat, NULL, NULL, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); assert( RetValue == l_Undef || RetValue == l_True || RetValue == l_False ); +//printf( "%c", RetValue==l_Undef ? '?' : (RetValue==l_False ? '-' : '+') ); +//printf( "%d ", p->pSat->stats.conflicts-nConfs ); +//if ( RetValue==l_False ) +//printf( "\n" ); if ( RetValue == l_Undef ) return -1; if ( RetValue == l_False ) |