diff options
| author | Alan Mishchenko <alanmi@berkeley.edu> | 2009-03-15 08:01:00 -0700 | 
|---|---|---|
| committer | Alan Mishchenko <alanmi@berkeley.edu> | 2009-03-15 08:01:00 -0700 | 
| commit | 770bc99e79baa07a9d2cc7a25dc30ee86ed34d91 (patch) | |
| tree | c1240cf561832c51469197f7d01c91844b09c6a7 /src | |
| parent | 81b51657f5c502e45418630614fd56e5e1506230 (diff) | |
| download | abc-770bc99e79baa07a9d2cc7a25dc30ee86ed34d91.tar.gz abc-770bc99e79baa07a9d2cc7a25dc30ee86ed34d91.tar.bz2 abc-770bc99e79baa07a9d2cc7a25dc30ee86ed34d91.zip | |
Version abc90315
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 ) | 
