diff options
58 files changed, 4385 insertions, 622 deletions
| @@ -90,6 +90,10 @@ LINK32=link.exe  SOURCE=.\src\base\main\main.c  # End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswSat.c +# End Source File  # End Group  # Begin Group "Header Files" @@ -263,10 +263,18 @@ SOURCE=.\src\base\abci\abcDress2.c  # End Source File  # Begin Source File +SOURCE=.\src\base\abci\abcDress3.c +# End Source File +# Begin Source File +  SOURCE=.\src\base\abci\abcDsd.c  # End Source File  # Begin Source File +SOURCE=.\src\base\abci\abcExact.c +# End Source File +# Begin Source File +  SOURCE=.\src\base\abci\abcExtract.c  # End Source File  # Begin Source File @@ -5347,6 +5355,10 @@ SOURCE=.\src\proof\acec\acecCore.c  # End Source File  # Begin Source File +SOURCE=.\src\proof\acec\acecCover.c +# End Source File +# Begin Source File +  SOURCE=.\src\proof\acec\acecFadds.c  # End Source File  # Begin Source File diff --git a/src/aig/aig/aigDfs.c b/src/aig/aig/aigDfs.c index 8afec81e..d560fc29 100644 --- a/src/aig/aig/aigDfs.c +++ b/src/aig/aig/aigDfs.c @@ -199,6 +199,20 @@ void Aig_ManDfsAll_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )      Aig_ManDfsAll_rec( p, Aig_ObjFanin1(pObj), vNodes );      Vec_PtrPush( vNodes, pObj );  } +Vec_Ptr_t * Aig_ManDfsArray( Aig_Man_t * p, Aig_Obj_t ** pNodes, int nNodes ) +{ +    Vec_Ptr_t * vNodes; +    int i; +    Aig_ManIncrementTravId( p ); +    vNodes = Vec_PtrAlloc( Aig_ManObjNumMax(p) ); +    // add constant +    Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); +    Vec_PtrPush( vNodes, Aig_ManConst1(p) ); +    // collect nodes reachable in the DFS order +    for ( i = 0; i < nNodes; i++ ) +        Aig_ManDfsAll_rec( p, pNodes[i], vNodes ); +    return vNodes; +}  /**Function************************************************************* diff --git a/src/aig/aig/aigUtil.c b/src/aig/aig/aigUtil.c index 6637e1a4..767015c9 100644 --- a/src/aig/aig/aigUtil.c +++ b/src/aig/aig/aigUtil.c @@ -653,23 +653,36 @@ void Aig_ObjPrintVerilog( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, i  void Aig_ObjPrintVerbose( Aig_Obj_t * pObj, int fHaig )  {      assert( !Aig_IsComplement(pObj) ); -    printf( "Node %p : ", pObj ); +    printf( "Node %d : ", pObj->Id );      if ( Aig_ObjIsConst1(pObj) )          printf( "constant 1" );      else if ( Aig_ObjIsCi(pObj) ) -        printf( "PI" ); +        printf( "CI" );      else if ( Aig_ObjIsCo(pObj) )      { -        printf( "PO" ); -        printf( "%p%s",  -            Aig_ObjFanin0(pObj), (Aig_ObjFaninC0(pObj)? "\'" : " ") ); +        printf( "CO( " ); +        printf( "%d%s )",  +            Aig_ObjFanin0(pObj)->Id, (Aig_ObjFaninC0(pObj)? "\'" : " ") );      }      else -        printf( "AND( %p%s, %p%s )",  -            Aig_ObjFanin0(pObj), (Aig_ObjFaninC0(pObj)? "\'" : " "),  -            Aig_ObjFanin1(pObj), (Aig_ObjFaninC1(pObj)? "\'" : " ") ); +        printf( "AND( %d%s, %d%s )",  +            Aig_ObjFanin0(pObj)->Id, (Aig_ObjFaninC0(pObj)? "\'" : " "),  +            Aig_ObjFanin1(pObj)->Id, (Aig_ObjFaninC1(pObj)? "\'" : " ") );      printf( " (refs = %3d)", Aig_ObjRefs(pObj) );  } +void Aig_ObjPrintVerboseCone( Aig_Man_t * p, Aig_Obj_t * pRoot, int fHaig ) +{ +    extern Vec_Ptr_t * Aig_ManDfsArray( Aig_Man_t * p, Aig_Obj_t ** pNodes, int nNodes ); +    Vec_Ptr_t * vNodes; +    Aig_Obj_t * pObj; +    int i; +    vNodes = Aig_ManDfsArray( p, &pRoot, 1 ); +    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) +        Aig_ObjPrintVerbose( pObj, fHaig ), printf( "\n" ); +    printf( "\n" ); +    Vec_PtrFree( vNodes ); + +}  /**Function************************************************************* diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index f2baf7e0..3d2d84ae 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -175,6 +175,8 @@ struct Gia_Man_t_      Vec_Int_t *    vUserFfIds;    // numbers assigned to FFs by the user      Vec_Int_t *    vCiNumsOrig;   // original CI names      Vec_Int_t *    vCoNumsOrig;   // original CO names +    Vec_Int_t *    vIdsOrig;      // original object IDs +    Vec_Int_t *    vIdsEquiv;     // original object IDs proved equivalent      Vec_Int_t *    vCofVars;      // cofactoring variables      Vec_Vec_t *    vClockDoms;    // clock domains      Vec_Flt_t *    vTiming;       // arrival/required/slack @@ -1241,6 +1243,10 @@ extern void                Gia_ManDetectSeqSignals( Gia_Man_t * p, int fSetReset  extern Gia_Man_t *         Gia_ManUnrollAndCofactor( Gia_Man_t * p, int nFrames, int nFanMax, int fVerbose );  extern Gia_Man_t *         Gia_ManRemoveEnables( Gia_Man_t * p );  /*=== giaEquiv.c ==========================================================*/ +extern void                Gia_ManOrigIdsInit( Gia_Man_t * p ); +extern void                Gia_ManOrigIdsStart( Gia_Man_t * p ); +extern void                Gia_ManOrigIdsRemap( Gia_Man_t * p, Gia_Man_t * pNew ); +extern Gia_Man_t *         Gia_ManOrigIdsReduce( Gia_Man_t * p, Vec_Int_t * vPairs );  extern void                Gia_ManEquivFixOutputPairs( Gia_Man_t * p );  extern int                 Gia_ManCheckTopoOrder( Gia_Man_t * p );  extern int *               Gia_ManDeriveNexts( Gia_Man_t * p ); diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index a2277294..7ced54a4 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -1383,7 +1383,7 @@ Gia_Man_t * Gia_ManDupDfs( Gia_Man_t * p )      Gia_ManForEachCo( p, pObj, i )          Gia_ManDupDfs_rec( pNew, p, Gia_ObjFanin0(pObj) );      Gia_ManForEachCo( p, pObj, i ) -        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); +        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );      Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );      pNew->nConstrs = p->nConstrs;      if ( p->pCexSeq ) @@ -3825,7 +3825,7 @@ Vec_Int_t * Gia_ManCollectTopXors( Gia_Man_t * p )          Gia_ManSetMark0Dfs_rec( p, Gia_ObjId(p, pFan[fFlip]) );          Gia_ManSetMark1Dfs_rec( p, Gia_ObjId(p, pFan[!fFlip]) );      } -    printf( "Detected %d single-output XOR miters and %d other miters.\n", Vec_IntSize(vXors) - Count1, Count1 ); +    //printf( "Detected %d single-output XOR miters and %d other miters.\n", Vec_IntSize(vXors) - Count1, Count1 );      Vec_IntFree( vXors );      Gia_ManCleanMark01(p);      // create new order @@ -3860,9 +3860,18 @@ Gia_Man_t * Gia_ManDemiterToDual( Gia_Man_t * p )          pObj->Value = Gia_ManAppendCi( pNew );      Gia_ManForEachObjVec( vNodes, p, pObj, i )          pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); -    Gia_ManSetPhase( p ); -    Gia_ManForEachObjVec( vOrder, p, pObj, i ) -        Gia_ManAppendCo( pNew, Abc_LitNotCond(pObj->Value, pObj->fPhase) ); +    pObj = Gia_ManCo(p, 0); +    if ( Gia_ObjFanin0(pObj) == Gia_ManConst0(p) ) +    { +        Gia_ManAppendCo( pNew, 0 ); +        Gia_ManAppendCo( pNew, Gia_ObjFaninC0(pObj) ); +    } +    else +    { +        Gia_ManSetPhase( p ); +        Gia_ManForEachObjVec( vOrder, p, pObj, i ) +            Gia_ManAppendCo( pNew, Abc_LitNotCond(pObj->Value, pObj->fPhase) ); +    }      Vec_IntFree( vNodes );      Vec_IntFree( vOrder );      return pNew; diff --git a/src/aig/gia/giaEdge.c b/src/aig/gia/giaEdge.c index 65d9d6ef..5ba8006f 100644 --- a/src/aig/gia/giaEdge.c +++ b/src/aig/gia/giaEdge.c @@ -175,13 +175,14 @@ int Gia_ObjCheckEdge( Gia_Man_t * p, int iObj, int iNext )  }  static inline int Gia_ObjEvalEdgeDelay( Gia_Man_t * p, int iObj, Vec_Int_t * vDelay )  { +    int nEdgeDelay = 2;      int i, iFan, Delay, DelayMax = 0;      if ( Gia_ManHasMapping(p) && Gia_ObjIsLut(p, iObj) )      {          assert( Gia_ObjLutSize(p, iObj) <= 4 );          Gia_LutForEachFanin( p, iObj, iFan, i )          { -            Delay = Vec_IntEntry(vDelay, iFan) + (Gia_ObjHaveEdge(p, iObj, iFan) ? 2 : 10); +            Delay = Vec_IntEntry(vDelay, iFan) + (Gia_ObjHaveEdge(p, iObj, iFan) ? nEdgeDelay : 10);              DelayMax = Abc_MaxInt( DelayMax, Delay );          }      } @@ -190,7 +191,7 @@ static inline int Gia_ObjEvalEdgeDelay( Gia_Man_t * p, int iObj, Vec_Int_t * vDe          assert( Gia_ObjLutSize2(p, iObj) <= 4 );          Gia_LutForEachFanin2( p, iObj, iFan, i )          { -            Delay = Vec_IntEntry(vDelay, iFan) + (Gia_ObjHaveEdge(p, iObj, iFan) ? 2 : 10); +            Delay = Vec_IntEntry(vDelay, iFan) + (Gia_ObjHaveEdge(p, iObj, iFan) ? nEdgeDelay : 10);              DelayMax = Abc_MaxInt( DelayMax, Delay );          }      } diff --git a/src/aig/gia/giaEquiv.c b/src/aig/gia/giaEquiv.c index d383ce41..584be4cd 100644 --- a/src/aig/gia/giaEquiv.c +++ b/src/aig/gia/giaEquiv.c @@ -34,6 +34,143 @@ ABC_NAMESPACE_IMPL_START  /**Function************************************************************* +  Synopsis    [Manipulating original IDs.] + +  Description [] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +void Gia_ManOrigIdsInit( Gia_Man_t * p ) +{ +    Vec_IntFreeP( &p->vIdsOrig ); +    p->vIdsOrig = Vec_IntStartNatural( Gia_ManObjNum(p) ); +} +void Gia_ManOrigIdsStart( Gia_Man_t * p ) +{ +    Vec_IntFreeP( &p->vIdsOrig ); +    p->vIdsOrig = Vec_IntStartFull( Gia_ManObjNum(p) ); +} +void Gia_ManOrigIdsRemap( Gia_Man_t * p, Gia_Man_t * pNew ) +{ +    Gia_Obj_t * pObj; int i; +    if ( p->vIdsOrig == NULL ) +        return; +    Gia_ManOrigIdsStart( pNew ); +    Vec_IntWriteEntry( pNew->vIdsOrig, 0, 0 ); +    Gia_ManForEachObj1( p, pObj, i ) +        if ( ~pObj->Value && Abc_Lit2Var(pObj->Value) && Vec_IntEntry(p->vIdsOrig, i) != -1 && Vec_IntEntry(pNew->vIdsOrig, Abc_Lit2Var(pObj->Value)) == -1 ) +            Vec_IntWriteEntry( pNew->vIdsOrig, Abc_Lit2Var(pObj->Value), Vec_IntEntry(p->vIdsOrig, i) ); +    Gia_ManForEachObj( pNew, pObj, i ) +        assert( Vec_IntEntry(pNew->vIdsOrig, i) >= 0 ); +} +// input is a set of equivalent node pairs in any order +// output is the mapping of each node into the equiv node with the smallest ID +void Gia_ManOrigIdsRemapPairsInsert( Vec_Int_t * vMap, int One, int Two ) +{ +    int Smo = One < Two ? One : Two; +    int Big = One < Two ? Two : One; +    assert( Smo != Big ); +    if ( Vec_IntEntry(vMap, Big) == -1 ) +        Vec_IntWriteEntry( vMap, Big, Smo ); +    else +        Gia_ManOrigIdsRemapPairsInsert( vMap, Smo, Vec_IntEntry(vMap, Big) ); +} +int Gia_ManOrigIdsRemapPairsExtract( Vec_Int_t * vMap, int One ) +{ +    if ( Vec_IntEntry(vMap, One) == -1 ) +        return One; +    return Gia_ManOrigIdsRemapPairsExtract( vMap, Vec_IntEntry(vMap, One) ); +} +Vec_Int_t * Gia_ManOrigIdsRemapPairs( Vec_Int_t * vEquivPairs, int nObjs ) +{ +    Vec_Int_t * vMapResult; +    Vec_Int_t * vMap2Smaller; +    int i, One, Two; +    // map bigger into smaller one +    vMap2Smaller = Vec_IntStartFull( nObjs ); +    Vec_IntForEachEntryDouble( vEquivPairs, One, Two, i ) +        Gia_ManOrigIdsRemapPairsInsert( vMap2Smaller, One, Two ); +    // collect results in the topo order +    vMapResult = Vec_IntStartFull( nObjs ); +    Vec_IntForEachEntry( vMap2Smaller, One, i ) +        if ( One >= 0 ) +            Vec_IntWriteEntry( vMapResult, i, Gia_ManOrigIdsRemapPairsExtract(vMap2Smaller, One) ); +    Vec_IntFree( vMap2Smaller ); +    return vMapResult; +} +// remap the AIG using the equivalent pairs proved +// returns the reduced AIG and the equivalence classes of the original AIG +Gia_Man_t * Gia_ManOrigIdsReduce( Gia_Man_t * p, Vec_Int_t * vPairs ) +{ +    Gia_Man_t * pNew = NULL; +    Gia_Obj_t * pObj, * pRepr; int i; +    Vec_Int_t * vMap = Gia_ManOrigIdsRemapPairs( vPairs, Gia_ManObjNum(p) ); +    Gia_ManSetPhase( p ); +    pNew = Gia_ManStart( Gia_ManObjNum(p) ); +    pNew->pSpec = Abc_UtilStrsav( p->pSpec ); +    pNew->pName = Abc_UtilStrsav( p->pName ); +    Gia_ManFillValue(p); +    Gia_ManConst0(p)->Value = 0; +    Gia_ManForEachCi( p, pObj, i ) +        pObj->Value = Gia_ManAppendCi(pNew); +    Gia_ManHashAlloc( pNew ); +    Gia_ManForEachAnd( p, pObj, i ) +    { +        if ( Vec_IntEntry(vMap, i) == -1 ) +            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +        else +        { +            pRepr = Gia_ManObj( p, Vec_IntEntry(vMap, i) ); +            pObj->Value = Abc_LitNotCond( pRepr->Value, pRepr->fPhase ^ pObj->fPhase ); +        } +    } +    Gia_ManHashStop( pNew ); +    Gia_ManForEachCo( p, pObj, i ) +        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); +    Vec_IntFree( vMap ); +    // compute equivalences +    assert( !p->pReprs && !p->pNexts ); +    p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); +    for ( i = 0; i < Gia_ManObjNum(p); i++ ) +        Gia_ObjSetRepr( p, i, GIA_VOID ); +    Gia_ManFillValue(pNew); +    Gia_ManForEachAnd( p, pObj, i ) +    { +        int iRepr = Abc_Lit2Var(pObj->Value); +        if ( iRepr == 0 ) +        { +            Gia_ObjSetRepr( p, i, 0 ); +            continue; +        } +        pRepr = Gia_ManObj( pNew, iRepr ); +        if ( !~pRepr->Value ) // first time +        { +            pRepr->Value = i; +            continue; +        } +        // add equivalence +        Gia_ObjSetRepr( p, i, pRepr->Value ); +    } +    p->pNexts = Gia_ManDeriveNexts( p ); +    return pNew; +} +Gia_Man_t * Gia_ManOrigIdsReduceTest( Gia_Man_t * p, Vec_Int_t * vPairs ) +{ +    Gia_Man_t * pTemp, * pNew = Gia_ManOrigIdsReduce( p, vPairs ); +    Gia_ManPrintStats( p, NULL ); +    Gia_ManPrintStats( pNew, NULL ); +    //Gia_ManStop( pNew ); +    // cleanup the resulting one +    pNew = Gia_ManCleanup( pTemp = pNew ); +    Gia_ManStop( pTemp ); +    return pNew; +} + +/**Function************************************************************* +    Synopsis    [Returns 1 if AIG is not in the required topo order.]    Description [] @@ -460,7 +597,7 @@ Gia_Man_t * Gia_ManEquivReduce( Gia_Man_t * p, int fUseAll, int fDualOut, int fS      Gia_ManForEachCo( p, pObj, i )          Gia_ManEquivReduce_rec( pNew, p, Gia_ObjFanin0(pObj), fUseAll, fDualOut );      Gia_ManForEachCo( p, pObj, i ) -        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); +        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );      Gia_ManHashStop( pNew );      Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );      return pNew; @@ -641,6 +778,7 @@ Gia_Man_t * Gia_ManEquivReduceAndRemap( Gia_Man_t * p, int fSeq, int fMiterPairs      pNew = Gia_ManEquivReduce( p, 0, 0, 0, 0 );      if ( pNew == NULL )          return NULL; +    Gia_ManOrigIdsRemap( p, pNew );      if ( fMiterPairs )          Gia_ManEquivFixOutputPairs( pNew );      if ( fSeq ) @@ -649,9 +787,11 @@ Gia_Man_t * Gia_ManEquivReduceAndRemap( Gia_Man_t * p, int fSeq, int fMiterPairs          Gia_ManCombMarkUsed( pNew );      Gia_ManEquivUpdatePointers( p, pNew );      pFinal = Gia_ManDupMarked( pNew ); +    Gia_ManOrigIdsRemap( pNew, pFinal );      Gia_ManEquivDeriveReprs( p, pNew, pFinal );      Gia_ManStop( pNew );      pFinal = Gia_ManEquivRemapDfs( pNew = pFinal ); +    Gia_ManOrigIdsRemap( pNew, pFinal );      Gia_ManStop( pNew );      return pFinal;  } diff --git a/src/aig/gia/giaFx.c b/src/aig/gia/giaFx.c index 4fff177c..c6eae6c7 100644 --- a/src/aig/gia/giaFx.c +++ b/src/aig/gia/giaFx.c @@ -455,7 +455,7 @@ Gia_Man_t * Gia_ManFxInsert( Gia_Man_t * p, Vec_Wec_t * vCubes, Vec_Str_t * vCom  ***********************************************************************/  Gia_Man_t * Gia_ManPerformFx( Gia_Man_t * p, int nNewNodesMax, int LitCountMax, int fReverse, int fVerbose, int fVeryVerbose )  { -    extern int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitCountMax, int fVerbose, int fVeryVerbose ); +    extern int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitCountMax, int fCanonDivs, int fVerbose, int fVeryVerbose );      Gia_Man_t * pNew = NULL;      Vec_Wec_t * vCubes;      Vec_Str_t * vCompl; @@ -467,7 +467,7 @@ Gia_Man_t * Gia_ManPerformFx( Gia_Man_t * p, int nNewNodesMax, int LitCountMax,      vCubes = Gia_ManFxRetrieve( p, &vCompl, fReverse );      // call the fast extract procedure  //    clk = Abc_Clock(); -    Fx_FastExtract( vCubes, Vec_StrSize(vCompl), nNewNodesMax, LitCountMax, fVerbose, fVeryVerbose ); +    Fx_FastExtract( vCubes, Vec_StrSize(vCompl), nNewNodesMax, LitCountMax, 0, fVerbose, fVeryVerbose );  //    Abc_PrintTime( 1, "Fx runtime", Abc_Clock() - clk );      // insert information      pNew = Gia_ManFxInsert( p, vCubes, vCompl ); diff --git a/src/aig/gia/giaIf.c b/src/aig/gia/giaIf.c index 9a72f576..26f549d0 100644 --- a/src/aig/gia/giaIf.c +++ b/src/aig/gia/giaIf.c @@ -926,7 +926,7 @@ Gia_Man_t * Gia_ManFromIfAig( If_Man_t * pIfMan )      Vec_Int_t * vAig;      int i, k;      assert( pIfMan->pPars->pLutStruct == NULL ); -    assert( pIfMan->pPars->fDelayOpt || pIfMan->pPars->fDsdBalance || pIfMan->pPars->fUserRecLib ); +    assert( pIfMan->pPars->fDelayOpt || pIfMan->pPars->fDsdBalance || pIfMan->pPars->fUserRecLib || pIfMan->pPars->fUserSesLib );      // create new manager      pNew = Gia_ManStart( If_ManObjNum(pIfMan) );      Gia_ManHashAlloc( pNew ); @@ -1783,8 +1783,8 @@ Gia_Man_t * Gia_ManFromIfLogic( If_Man_t * pIfMan )              pCutBest = If_ObjCutBest( pIfObj );              // perform sorting of cut leaves by delay, so that the slowest pin drives the fastest input of the LUT              if ( !pIfMan->pPars->fUseTtPerm && !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance &&  -                 !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->nGateSize && !pIfMan->pPars->fEnableCheck75 &&  -                 !pIfMan->pPars->fEnableCheck75u && !pIfMan->pPars->fEnableCheck07 && !pIfMan->pPars->fUseDsdTune &&  +                 !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize &&  +                 !pIfMan->pPars->fEnableCheck75 && !pIfMan->pPars->fEnableCheck75u && !pIfMan->pPars->fEnableCheck07 && !pIfMan->pPars->fUseDsdTune &&                    !pIfMan->pPars->fUseCofVars && !pIfMan->pPars->fUseAndVars )                  If_CutRotatePins( pIfMan, pCutBest );              // collect leaves of the best cut @@ -2117,7 +2117,7 @@ Gia_Man_t * Gia_ManPerformMappingInt( Gia_Man_t * p, If_Par_t * pPars )      ABC_FREE( p->pCellStr );      Vec_IntFreeP( &p->vConfigs );      // disable cut minimization when GIA strucure is needed -    if ( !pPars->fDelayOpt && !pPars->fDelayOptLut && !pPars->fDsdBalance && !pPars->fUserRecLib && !pPars->fDeriveLuts && !pPars->fUseDsd && !pPars->fUseTtPerm ) +    if ( !pPars->fDelayOpt && !pPars->fDelayOptLut && !pPars->fDsdBalance && !pPars->fUserRecLib && !pPars->fUserSesLib && !pPars->fDeriveLuts && !pPars->fUseDsd && !pPars->fUseTtPerm )          pPars->fCutMin = 0;      // translate into the mapper      pIfMan = Gia_ManToIf( p, pPars );     @@ -2142,7 +2142,7 @@ Gia_Man_t * Gia_ManPerformMappingInt( Gia_Man_t * p, If_Par_t * pPars )              Abc_Print( 0, "Switching activity computation for designs with boxes is disabled.\n" );      }      if ( p->pManTime ) -        pIfMan->pManTim = Tim_ManDup( (Tim_Man_t *)p->pManTime, pPars->fDelayOpt || pPars->fDelayOptLut || pPars->fDsdBalance || pPars->fUserRecLib ); +        pIfMan->pManTim = Tim_ManDup( (Tim_Man_t *)p->pManTime, pPars->fDelayOpt || pPars->fDelayOptLut || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib );  //    Tim_ManPrint( pIfMan->pManTim );      if ( !If_ManPerformMapping( pIfMan ) )      { @@ -2150,7 +2150,7 @@ Gia_Man_t * Gia_ManPerformMappingInt( Gia_Man_t * p, If_Par_t * pPars )          return NULL;      }      // transform the result of mapping into the new network -    if ( pIfMan->pPars->fDelayOpt || pIfMan->pPars->fDsdBalance || pIfMan->pPars->fUserRecLib ) +    if ( pIfMan->pPars->fDelayOpt || pIfMan->pPars->fDsdBalance || pIfMan->pPars->fUserRecLib || pIfMan->pPars->fUserSesLib )          pNew = Gia_ManFromIfAig( pIfMan );      else          pNew = Gia_ManFromIfLogic( pIfMan ); diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index d9e878a7..9ccab495 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -93,6 +93,8 @@ void Gia_ManStop( Gia_Man_t * p )      Vec_FltFreeP( &p->vTiming );      Vec_VecFreeP( &p->vClockDoms );      Vec_IntFreeP( &p->vCofVars ); +    Vec_IntFreeP( &p->vIdsOrig ); +    Vec_IntFreeP( &p->vIdsEquiv );      Vec_IntFreeP( &p->vLutConfigs );      Vec_IntFreeP( &p->vEdgeDelay );      Vec_IntFreeP( &p->vEdgeDelayR ); diff --git a/src/aig/gia/giaMf.c b/src/aig/gia/giaMf.c index 086da95b..591f5bc5 100644 --- a/src/aig/gia/giaMf.c +++ b/src/aig/gia/giaMf.c @@ -247,6 +247,14 @@ void Mf_ManProfileTruths( Mf_Man_t * p )    SeeAlso     []  ***********************************************************************/ +static inline void Mf_CutPrintOne( int * pCut ) +{ +    int i;  +    printf( "%d {", Mf_CutSize(pCut) ); +    for ( i = 1; i <= Mf_CutSize(pCut); i++ ) +        printf( " %d", pCut[i] ); +    printf( " }\n" ); +}  static inline int Mf_CubeLit( int Cube, int iVar ) { return (Cube >> (iVar << 1)) & 3; }  static inline int Mf_ManCountLits( int * pCnf, int nCubes, int nVars )  { @@ -287,6 +295,7 @@ Vec_Int_t * Mf_ManDeriveCnfs( Mf_Man_t * p, int * pnVars, int * pnClas, int * pn          if ( !Mf_ObjMapRefNum(p, i) )              continue;          pCut = Mf_ObjCutBest( p, i ); +        //Mf_CutPrintOne( pCut );          iFunc = Abc_Lit2Var( Mf_CutFunc(pCut) );          if ( Vec_IntEntry(vCnfs, iFunc) == -1 )          { diff --git a/src/aig/gia/giaMfs.c b/src/aig/gia/giaMfs.c index e5dfb788..c39e102d 100644 --- a/src/aig/gia/giaMfs.c +++ b/src/aig/gia/giaMfs.c @@ -67,7 +67,7 @@ Sfm_Ntk_t * Gia_ManExtractMfs( Gia_Man_t * p )      int i, j, k, curCi, curCo, nBoxIns, nBoxOuts;      int Id, iFan, nMfsVars, nBbIns = 0, nBbOuts = 0, Counter = 0;      assert( !p->pAigExtra || Gia_ManPiNum(p->pAigExtra) <= 6 ); -    Tim_ManBlackBoxIoNum( pManTime, &nBbIns, &nBbOuts ); +    if ( pManTime ) Tim_ManBlackBoxIoNum( pManTime, &nBbIns, &nBbOuts );      // skip PIs due to box outputs      Counter += nBbOuts;      // prepare storage @@ -252,7 +252,7 @@ Gia_Man_t * Gia_ManInsertMfs( Gia_Man_t * p, Sfm_Ntk_t * pNtk )      Vec_Int_t * vArray, * vLeaves;      Vec_Int_t * vMapping, * vMapping2;      int nBbIns = 0, nBbOuts = 0; -    Tim_ManBlackBoxIoNum( pManTime, &nBbIns, &nBbOuts ); +    if ( pManTime ) Tim_ManBlackBoxIoNum( pManTime, &nBbIns, &nBbOuts );      nMfsNodes = 1 + Gia_ManCiNum(p) + Gia_ManLutNum(p) + Gia_ManCoNum(p) + nBbIns + nBbOuts;      vMfs2Gia  = Vec_IntStartFull( nMfsNodes );      vGroupMap = Vec_IntStartFull( nMfsNodes ); diff --git a/src/aig/gia/giaSatLE.c b/src/aig/gia/giaSatLE.c index 549ec4fb..d541804a 100644 --- a/src/aig/gia/giaSatLE.c +++ b/src/aig/gia/giaSatLE.c @@ -31,8 +31,8 @@ ABC_NAMESPACE_IMPL_START  ////////////////////////////////////////////////////////////////////////  static inline int   Sle_CutSize( int * pCut )          { return pCut[0] & 0xF;  }  //  4 bits -static inline int   Sle_CutSign( int * pCut )          { return pCut[0] >> 4;   }  // 28 bits -static inline int   Sle_CutSetSizeSign( int s, int S ) { return (S << 28) | s;  } +static inline int   Sle_CutSign( int * pCut )          { return ((unsigned)pCut[0]) >> 4;   }  // 28 bits +static inline int   Sle_CutSetSizeSign( int s, int S ) { return (S << 4) | s;   }  static inline int * Sle_CutLeaves( int * pCut )        { return pCut + 1;       }   static inline int   Sle_CutIsUsed( int * pCut )        { return pCut[1] != 0;   } @@ -197,7 +197,7 @@ int Sle_ManCutMerge( Gia_Man_t * p, int iObj, Vec_Int_t * vCuts, Vec_Int_t * vTe          nCuts++;      }      // add unit cut -    Vec_IntPush( vCuts, Sle_CutSetSizeSign(1, iObj % 28) ); +    Vec_IntPush( vCuts, Sle_CutSetSizeSign(1, 1<<(iObj % 28)) );      Vec_IntPush( vCuts, iObj );      Vec_IntWriteEntry( vCuts, Vec_IntEntry(vCuts, iObj), nCuts );      return nCuts; @@ -213,7 +213,7 @@ Vec_Int_t * Sle_ManComputeCuts( Gia_Man_t * p, int nLutSize, int fVerbose )      {          Vec_IntWriteEntry( vCuts, iObj, Vec_IntSize(vCuts) );          Vec_IntPush( vCuts, 0 ); -        Vec_IntPush( vCuts, Sle_CutSetSizeSign(1, iObj % 28) ); +        Vec_IntPush( vCuts, Sle_CutSetSizeSign(1, 1<<(iObj % 28)) );          Vec_IntPush( vCuts, iObj );      }      Gia_ManForEachAndId( p, iObj ) @@ -226,6 +226,64 @@ Vec_Int_t * Sle_ManComputeCuts( Gia_Man_t * p, int nLutSize, int fVerbose )      Vec_IntFree( vTemp );      return vCuts;  } + +/**Function************************************************************* + +  Synopsis    [Cut delay computation.] + +  Description [] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +int Sle_ManComputeDelayCut( Gia_Man_t * p, int * pCut, Vec_Int_t * vTime ) +{ +    int nSize   = Sle_CutSize(pCut); +    int k, * pC = Sle_CutLeaves(pCut); +    int DelayMax = 0; +    for ( k = 0; k < nSize; k++ ) +        DelayMax = Abc_MaxInt( DelayMax, Vec_IntEntry(vTime, pC[k]) ); +    return DelayMax + 1; +} +int Sle_ManComputeDelayOne( Gia_Man_t * p, int iObj, Vec_Int_t * vCuts, Vec_Int_t * vTime ) +{ +    int i, * pCut, Delay, DelayMin = ABC_INFINITY; +    int * pList = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, iObj) ); +    Sle_ForEachCut( pList, pCut, i ) +    { +        Delay = Sle_ManComputeDelayCut( p, pCut, vTime ); +        DelayMin = Abc_MinInt( DelayMin, Delay ); +    } +    Vec_IntWriteEntry( vTime, iObj, DelayMin ); +    return DelayMin; +} +int Sle_ManComputeDelay( Gia_Man_t * p, Vec_Int_t * vCuts ) +{ +    int iObj, Delay, DelayMax = 0; +    Vec_Int_t * vTime = Vec_IntStart( Gia_ManObjNum(p) ); +    Gia_ManForEachAndId( p, iObj ) +    { +        Delay = Sle_ManComputeDelayOne( p, iObj, vCuts, vTime ); +        DelayMax = Abc_MaxInt( DelayMax, Delay ); +    } +    Vec_IntFree( vTime ); +    //printf( "Delay = %d.\n", DelayMax ); +    return DelayMax; +} + +/**Function************************************************************* + +  Synopsis    [Cut printing.] + +  Description [] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/  void Sle_ManPrintCut( int * pCut )  {      int nSize   = Sle_CutSize(pCut); @@ -347,6 +405,7 @@ struct Sle_Man_t_      Gia_Man_t *    pGia;         // user's manager (with mapping and edges)      int            nLevels;      // total number of levels      int            fVerbose;     // verbose flag +    int            nSatCalls;    // the number of SAT calls      // SAT variables      int            nNodeVars;    // node variables (Gia_ManAndNum(pGia))      int            nCutVars;     // cut variables (total number of non-trivial cuts) @@ -405,6 +464,7 @@ Sle_Man_t * Sle_ManAlloc( Gia_Man_t * pGia, int nLevels, int fVerbose )      p->vDelayFirst  = Vec_IntStartFull( Gia_ManObjNum(pGia) );      p->vPolars      = Vec_IntAlloc( 100 );      p->vLits        = Vec_IntAlloc( 100 ); +    p->nLevels      = Sle_ManComputeDelay( pGia, p->vCuts );      return p;  }  void Sle_ManStop( Sle_Man_t * p ) @@ -462,8 +522,6 @@ void Sle_ManMarkupVariables( Sle_Man_t * p )      }      p->nDelayVars = Counter - p->nEdgeVars - p->nCutVars - p->nNodeVars;      p->nVarsTotal = Counter; -    printf( "Vars:  Total = %d.  Node = %d. Cut = %d. Edge = %d. Delay = %d.\n",  -        p->nVarsTotal, p->nNodeVars, p->nCutVars, p->nEdgeVars, p->nDelayVars );  } @@ -478,10 +536,25 @@ void Sle_ManMarkupVariables( Sle_Man_t * p )    SeeAlso     []  ***********************************************************************/ +// returns 1 if Cut can represent LUT (Cut is equal or is contained in LUT) +static inline int Sle_ManCheckContained( int * pCutLeaves, int nCutLeaves, int * pLutFanins, int nLutFanins ) +{ +    int i, k; +    if ( nCutLeaves > nLutFanins ) +        return 0; +    for ( i = 0; i < nCutLeaves; i++ ) +    { +        for ( k = 0; k < nLutFanins; k++ ) +            if ( pCutLeaves[i] == pLutFanins[k] ) +                break; +        if ( k == nLutFanins ) // not found +            return 0; +    } +    return 1; +}  void Sle_ManDeriveInit( Sle_Man_t * p )  {      Vec_Int_t * vEdges; -    int pFaninsCopy[16];      int i, iObj, iFanin, iEdge;      if ( !Gia_ManHasMapping(p->pGia) )          return; @@ -495,13 +568,10 @@ void Sle_ManDeriveInit( Sle_Man_t * p )          Vec_IntPush( p->vPolars, iObj ); // node var          nFanins = Gia_ObjLutSize( p->pGia, iObj );          pFanins = Gia_ObjLutFanins( p->pGia, iObj ); -        // duplicate and sort fanins -        memcpy( pFaninsCopy, pFanins, sizeof(int)*nFanins ); -        Vec_IntSelectSort( pFaninsCopy, nFanins );          // find cut          pList = Sle_ManList( p, iObj );          Sle_ForEachCut( pList, pCut, i ) -            if ( nFanins == Sle_CutSize(pCut) && !memcmp(pFaninsCopy, Sle_CutLeaves(pCut), sizeof(int)*Sle_CutSize(pCut)) ) +            if ( Sle_ManCheckContained( Sle_CutLeaves(pCut), Sle_CutSize(pCut), pFanins, nFanins ) )              {                  iFound = i;                  break; @@ -510,7 +580,7 @@ void Sle_ManDeriveInit( Sle_Man_t * p )          {              printf( "Cannot find the following cut at node %d: {", iObj );              for ( i = 0; i < nFanins; i++ ) -                printf( " %d", pFaninsCopy[i] ); +                printf( " %d", pFanins[i] );              printf( " }\n" );              Sle_ManPrintCuts( p->pGia, p->vCuts, iObj );              fflush( stdout ); @@ -535,6 +605,8 @@ void Sle_ManDeriveInit( Sle_Man_t * p )          assert( Gia_ObjIsAnd(Gia_ManObj(p->pGia, iObj)) );          // find edge          iEdge = Vec_IntFind( Vec_WecEntry(p->vCutFanins, iObj), iFanin ); +        if ( iEdge < 0 ) +            continue;          assert( iEdge >= 0 );          Vec_IntPush( p->vPolars, Vec_IntEntry(p->vEdgeFirst, iObj) + iEdge ); // edge      } @@ -552,9 +624,8 @@ void Sle_ManDeriveInit( Sle_Man_t * p )    SeeAlso     []  ***********************************************************************/ -void Sle_ManDeriveCnf( Sle_Man_t * p ) +void Sle_ManDeriveCnf( Sle_Man_t * p, int nBTLimit, int fDynamic )  { -    int nBTLimit = 0;      int nTimeOut = 0;      int i, iObj, value;      Vec_Int_t * vArray; @@ -592,7 +663,15 @@ void Sle_ManDeriveCnf( Sle_Man_t * p )              Vec_IntPush( p->vLits, Abc_Var2Lit(iCutVar0 + i, 0) );          value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits)  );          assert( value ); -        // cut required fanin nodes +        // cuts are mutually exclusive +        for ( i = 0; i < Sle_ListCutNum(pList); i++ ) +            for ( e = i+1; e < Sle_ListCutNum(pList); e++ ) +            { +                Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(iCutVar0 + i, 1), Abc_Var2Lit(iCutVar0 + e, 1) ); +                value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits)  ); +                assert( value ); +            } +        // cut requires fanin nodes          Vec_WecInit( p->vEdgeCuts, Vec_IntSize(vCutFans) );          Sle_ForEachCut( pList, pCut, i )          { @@ -609,11 +688,17 @@ void Sle_ManDeriveCnf( Sle_Man_t * p )                  // find the edge ID between pC[k] and iObj                  iEdge = Vec_IntEntry(p->vObjMap, pC[k]);                  if ( iEdge == -1 ) +                {                      Vec_IntWriteEntry( p->vObjMap, pC[k], (iEdge = nEdges++) ); +                    Vec_WecPush( p->vFanoutEdges, pC[k], iEdgeVar0 + iEdge ); +                }                  Vec_WecPush( p->vEdgeCuts, iEdge, iCutVar0 + i ); -                Vec_WecPush( p->vFanoutEdges, pC[k], iEdgeVar0 + iEdge );                  p->nCutClas++;              } +            // cut requires the node +            Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(iCutVar0 + i, 1), Abc_Var2Lit(iObj, 0) ); +            value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits)  ); +            assert( value );          }          assert( nEdges == Vec_IntSize(vCutFans) ); @@ -644,6 +729,8 @@ void Sle_ManDeriveCnf( Sle_Man_t * p )          for ( i = 0; i < Vec_IntSize(vCutFans); i++ )              Vec_IntPush( vArray, iEdgeVar0 + i );          // generate pairs +        if ( fDynamic ) +            continue;          Vec_IntForEachEntry( vArray, EdgeJ, j )              Vec_IntForEachEntryStart( vArray, EdgeK, k, j+1 )              { @@ -667,6 +754,7 @@ void Sle_ManDeriveCnf( Sle_Man_t * p )              if ( Sle_ManCutHasPisOnly(pCut, p->vMask) )              {                  Vec_IntFill( p->vLits, 1, Abc_Var2Lit(iDelayVar0, 0) ); // pos lit +//                Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(iObj, 1), Abc_Var2Lit(iDelayVar0, 0) );                  value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits)  );                  assert( value );                  break; @@ -680,6 +768,7 @@ void Sle_ManDeriveCnf( Sle_Man_t * p )              for ( d = 0; d < p->nLevels; d++ )              {                  Vec_IntClear( p->vLits ); +                Vec_IntPush( p->vLits, Abc_Var2Lit(iObj, 1) );                  Vec_IntPush( p->vLits, Abc_Var2Lit(iFanin, 1) );                  Vec_IntPush( p->vLits, Abc_Var2Lit(iDelayVarIn + d, 1) );                  Vec_IntPush( p->vLits, Abc_Var2Lit(iEdgeVar0 + e, 0) ); @@ -689,6 +778,7 @@ void Sle_ManDeriveCnf( Sle_Man_t * p )                  assert( value );                  Vec_IntClear( p->vLits ); +                Vec_IntPush( p->vLits, Abc_Var2Lit(iObj, 1) );                  Vec_IntPush( p->vLits, Abc_Var2Lit(iFanin, 1) );                  Vec_IntPush( p->vLits, Abc_Var2Lit(iDelayVarIn + d, 1) );                  if ( d < p->nLevels-1 ) @@ -700,8 +790,68 @@ void Sle_ManDeriveCnf( Sle_Man_t * p )              p->nDelayClas += 2*p->nLevels;          }      } -    printf( "Clas:  Total = %d.  Cut = %d. Edge = %d. EdgeEx = %d. Delay = %d.\n",  -        sat_solver_nclauses(p->pSat), p->nCutClas, p->nEdgeClas, p->nEdgeClas2, p->nDelayClas ); +} + +/**Function************************************************************* + +  Synopsis    [Add edge compatibility constraints.] + +  Description [Returns 1 if constraints have been added.] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +int Sle_ManAddEdgeConstraints( Sle_Man_t * p, int nEdges ) +{ +    Vec_Int_t * vArray; +    Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); +    int value, iObj, nAdded = 0; +    assert( nEdges == 1 || nEdges == 2 ); +    Vec_WecForEachLevel( p->vFanoutEdges, vArray, iObj ) +    { +        int j, k, EdgeJ, EdgeK; +        // check if they are incompatible +        Vec_IntClear( vTemp ); +        Vec_IntForEachEntry( vArray, EdgeJ, j ) +            if ( sat_solver_var_value(p->pSat, EdgeJ) ) +                Vec_IntPush( vTemp, EdgeJ ); +        if ( Vec_IntSize(vTemp) <= nEdges ) +            continue; +        nAdded++; +        if ( nEdges == 1 ) +        { +            // generate pairs +            Vec_IntForEachEntry( vTemp, EdgeJ, j ) +                Vec_IntForEachEntryStart( vTemp, EdgeK, k, j+1 ) +                { +                    Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(EdgeJ, 1), Abc_Var2Lit(EdgeK, 1) ); +                    value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits)  ); +                    assert( value ); +                } +            p->nEdgeClas2 += Vec_IntSize(vTemp) * (Vec_IntSize(vTemp) - 1) / 2; +        } +        else if ( nEdges == 2 ) +        { +            int m, EdgeM; +            // generate triples +            Vec_IntForEachEntry( vTemp, EdgeJ, j ) +                Vec_IntForEachEntryStart( vTemp, EdgeK, k, j+1 ) +                    Vec_IntForEachEntryStart( vTemp, EdgeM, m, k+1 ) +                    { +                        Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(EdgeJ, 1), Abc_Var2Lit(EdgeK, 1) ); +                        Vec_IntPush( p->vLits, Abc_Var2Lit(EdgeM, 1) ); +                        value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits)  ); +                        assert( value ); +                    } +            p->nEdgeClas2 += Vec_IntSize(vTemp) * (Vec_IntSize(vTemp) - 1) * (Vec_IntSize(vTemp) - 2) / 6; +        } +        else assert( 0 ); +    } +    Vec_IntFree( vTemp ); +    //printf( "Added clauses to %d nodes.\n", nAdded ); +    return nAdded;  }  /**Function************************************************************* @@ -742,11 +892,31 @@ void Sle_ManDeriveResult( Sle_Man_t * p, Vec_Int_t * vEdge2, Vec_Int_t * vMappin      {          int i, iFanin, iEdgeVar0 = Vec_IntEntry( p->vEdgeFirst, iObj );          Vec_Int_t * vCutFans = Vec_WecEntry( p->vCutFanins, iObj ); +        //int * pCut, * pList  = Sle_ManList( p, iObj ); +        // int iCutVar0  = Vec_IntEntry( p->vCutFirst, iObj );          if ( !sat_solver_var_value(p->pSat, iObj) )              continue; +        //for ( i = 0; i < Sle_ListCutNum(pList); i++ ) +        //    printf( "%d", sat_solver_var_value(p->pSat, iCutVar0 + i) ); +        //printf( "\n" );          Vec_IntForEachEntry( vCutFans, iFanin, i ) -            if ( sat_solver_var_value(p->pSat, iEdgeVar0 + i) ) +            if ( sat_solver_var_value(p->pSat, iFanin) && sat_solver_var_value(p->pSat, iEdgeVar0 + i) ) +            { +                // verify edge +                int * pFanins = Gia_ObjLutFanins( p->pGia, iObj ); +                int k, nFanins = Gia_ObjLutSize( p->pGia, iObj ); +                for ( k = 0; k < nFanins; k++ ) +                { +                    //printf( "%d ", pFanins[k] ); +                    if ( pFanins[k] == iFanin ) +                        break; +                } +                //printf( "\n" ); +                if ( k == nFanins ) +//                    printf( "Cannot find LUT with input %d at node %d.\n", iFanin, iObj ); +                    continue;                  Vec_IntPushTwo( vEdge2, iFanin, iObj ); +            }      }  } @@ -761,23 +931,31 @@ void Sle_ManDeriveResult( Sle_Man_t * p, Vec_Int_t * vEdge2, Vec_Int_t * vMappin    SeeAlso     []  ***********************************************************************/ -void Sle_ManExplore( Gia_Man_t * pGia, int DelayInit, int fVerbose ) +void Sle_ManExplore( Gia_Man_t * pGia, int nBTLimit, int DelayInit, int fDynamic, int fTwoEdges, int fVerbose )  {      int fVeryVerbose = 0;      abctime clk = Abc_Clock();      Vec_Int_t * vEdges2  = Vec_IntAlloc(1000);      Vec_Int_t * vMapping = Vec_IntAlloc(1000);      int i, iLut, nConfs, status, Delay, iFirstVar; -    int DelayStart = DelayInit ? DelayInit : Gia_ManLutLevel(pGia, NULL); +    int DelayStart = (DelayInit || !Gia_ManHasMapping(pGia)) ? DelayInit : Gia_ManLutLevel(pGia, NULL);      Sle_Man_t * p = Sle_ManAlloc( pGia, DelayStart, fVerbose ); +    if ( fVerbose ) +        printf( "Running solver with %d conflicts, %d initial delay, and %d edges. Dynamic constraints = %s.\n", nBTLimit, DelayInit, 1+fTwoEdges, fDynamic?"yes":"no" );      Sle_ManMarkupVariables( p ); +    if ( fVerbose ) +        printf( "Vars:  Total = %d.  Node = %d. Cut = %d. Edge = %d. Delay = %d.\n",  +            p->nVarsTotal, p->nNodeVars, p->nCutVars, p->nEdgeVars, p->nDelayVars );      Sle_ManDeriveInit( p ); -    Sle_ManDeriveCnf( p ); +    Sle_ManDeriveCnf( p, nBTLimit, fDynamic || fTwoEdges ); +    if ( fVerbose ) +        printf( "Clas:  Total = %d.  Cut = %d. Edge = %d. EdgeEx = %d. Delay = %d.\n",  +            sat_solver_nclauses(p->pSat), p->nCutClas, p->nEdgeClas, p->nEdgeClas2, p->nDelayClas );      //Sat_SolverWriteDimacs( p->pSat, "temp.cnf", NULL, NULL, 0 ); -    for ( Delay = DelayStart; Delay >= 0; Delay-- ) +    for ( Delay = p->nLevels; Delay >= 0; Delay-- )      {          // we constrain COs, although it would be fine to constrain only POs -        if ( Delay < DelayStart ) +        if ( Delay < p->nLevels )          {              Gia_ManForEachCoDriverId( p->pGia, iLut, i )                  if ( Vec_BitEntry(p->vMask, iLut) ) // internal node @@ -788,15 +966,26 @@ void Sle_ManExplore( Gia_Man_t * pGia, int DelayInit, int fVerbose )                  }              if ( i < Gia_ManCoNum(p->pGia) )              { -                printf( "Proved UNSAT for delay %d.  ", Delay ); -                Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +                if ( fVerbose ) +                { +                    printf( "Proved UNSAT for delay %d.  ", Delay ); +                    Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +                }                  break;              }          }          // solve with assumptions          //clk = Abc_Clock();          nConfs = sat_solver_nconflicts( p->pSat ); -        status = sat_solver_solve_internal( p->pSat ); +        while ( 1 ) +        { +            p->nSatCalls++; +            status = sat_solver_solve_internal( p->pSat ); +            if ( status != l_True ) +                break; +            if ( !Sle_ManAddEdgeConstraints(p, 1+fTwoEdges) ) +                break; +        }          nConfs = sat_solver_nconflicts( p->pSat ) - nConfs;          if ( status == l_True )          { @@ -851,14 +1040,17 @@ void Sle_ManExplore( Gia_Man_t * pGia, int DelayInit, int fVerbose )              if ( fVerbose )              {                  if ( status == l_False ) -                    printf( "Proved UNSAT for delay %d.  ", Delay ); +                    printf( "Proved UNSAT for delay %d. Conf = %8d.  ", Delay, nConfs );                  else -                    printf( "Resource limit reached for delay %d.  ", Delay ); +                    printf( "Resource limit reached for delay %d. Conf = %8d.  ", Delay, nConfs );                  Abc_PrintTime( 1, "Time", Abc_Clock() - clk );              }              break;          }      } +    if ( fVerbose ) +        printf( "Clas:  Total = %d.  Cut = %d. Edge = %d. EdgeEx = %d. Delay = %d.  Calls = %d.\n",  +            sat_solver_nclauses(p->pSat), p->nCutClas, p->nEdgeClas, p->nEdgeClas2, p->nDelayClas, p->nSatCalls );      if ( Vec_IntSize(vMapping) > 0 )      {          Gia_ManEdgeFromArray( p->pGia, vEdges2 ); @@ -871,6 +1063,7 @@ void Sle_ManExplore( Gia_Man_t * pGia, int DelayInit, int fVerbose )          Vec_IntFree( vEdges2 );          Vec_IntFree( vMapping );      } +    Vec_IntFreeP( &p->pGia->vPacking );      Sle_ManStop( p );  } diff --git a/src/aig/gia/giaShow.c b/src/aig/gia/giaShow.c index 039931b2..872ba6ec 100644 --- a/src/aig/gia/giaShow.c +++ b/src/aig/gia/giaShow.c @@ -114,11 +114,12 @@ int Gia_WriteDotAigLevel( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vHadds,      return Level;  }  */ -int Gia_WriteDotAigLevel( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vHadds, Vec_Int_t * vRecord, Vec_Int_t ** pvLevel, Vec_Int_t ** pvMarks, Vec_Int_t ** pvRemap ) +int Gia_WriteDotAigLevel( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vHadds, Vec_Int_t * vRecord, Vec_Int_t ** pvLevel, Vec_Int_t ** pvMarks, Vec_Int_t ** pvRemap, Vec_Int_t ** pvRemap2 )  {      Vec_Int_t * vLevel = Vec_IntStart( Gia_ManObjNum(p) );      Vec_Int_t * vMarks = Vec_IntStart( Gia_ManObjNum(p) );      Vec_Int_t * vRemap = Vec_IntStartNatural( Gia_ManObjNum(p) ); +    Vec_Int_t * vRemap2 = Vec_IntStartNatural( Gia_ManObjNum(p) );      int i, k, Id, Entry, LevelMax = 0;      Vec_IntWriteEntry( vMarks, 0, -1 ); @@ -141,6 +142,7 @@ int Gia_WriteDotAigLevel( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vHadds,              Vec_IntWriteEntry( vLevel, pFanins[4], Level+1 );              Vec_IntWriteEntry( vMarks, pFanins[4], Entry );              Vec_IntWriteEntry( vRemap, pFanins[3], pFanins[4] ); +            Vec_IntWriteEntry( vRemap2, pFanins[4], pFanins[3] );              //printf( "Making FA output %d.\n", pFanins[4] );          }          else if ( Attr == 1 ) @@ -154,7 +156,8 @@ int Gia_WriteDotAigLevel( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vHadds,              Vec_IntWriteEntry( vLevel, pFanins[1], Level+1 );              Vec_IntWriteEntry( vMarks, pFanins[1], Entry );              Vec_IntWriteEntry( vRemap, pFanins[0], pFanins[1] ); -            //printf( "Making HA output %d.\n", pFanins[1] ); +            Vec_IntWriteEntry( vRemap2, pFanins[1], pFanins[0] ); +            //printf( "Making HA output %d %d.\n", pFanins[0], pFanins[1] );          }          else // if ( Attr == 3 || Attr == 0 )          { @@ -171,6 +174,7 @@ int Gia_WriteDotAigLevel( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vHadds,      *pvLevel = vLevel;      *pvMarks = vMarks;      *pvRemap = vRemap; +    *pvRemap2 = vRemap2;      return LevelMax;  } @@ -188,7 +192,7 @@ int Gia_WriteDotAigLevel( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vHadds,  ***********************************************************************/  void Gia_WriteDotAig( Gia_Man_t * pMan, char * pFileName, Vec_Int_t * vBold, int fAdders )  { -    Vec_Int_t * vFadds = NULL, * vHadds = NULL, * vRecord = NULL, * vMarks = NULL, * vRemap = NULL; +    Vec_Int_t * vFadds = NULL, * vHadds = NULL, * vRecord = NULL, * vMarks = NULL, * vRemap = NULL, * vRemap2 = NULL;      FILE * pFile;      Gia_Obj_t * pNode;//, * pTemp, * pPrev;      int LevelMax, Prev, Level, i; @@ -218,10 +222,10 @@ void Gia_WriteDotAig( Gia_Man_t * pMan, char * pFileName, Vec_Int_t * vBold, int      if ( fAdders )      {          Vec_IntFreeP( &pMan->vLevels ); -        vFadds   = Gia_ManDetectFullAdders( pMan, 0 ); +        vFadds   = Gia_ManDetectFullAdders( pMan, 0, NULL );          vHadds   = Gia_ManDetectHalfAdders( pMan, 0 );          vRecord  = Gia_PolynFindOrder( pMan, vFadds, vHadds, 0, 0 ); -        LevelMax = 1 + Gia_WriteDotAigLevel( pMan, vFadds, vHadds, vRecord, &pMan->vLevels, &vMarks, &vRemap ); +        LevelMax = 1 + Gia_WriteDotAigLevel( pMan, vFadds, vHadds, vRecord, &pMan->vLevels, &vMarks, &vRemap, &vRemap2 );      }      else          LevelMax = 1 + Gia_ManLevelNum( pMan ); @@ -364,7 +368,7 @@ void Gia_WriteDotAig( Gia_Man_t * pMan, char * pFileName, Vec_Int_t * vBold, int  */              if ( vMarks && Vec_IntEntry(vMarks, i) > 0 )              { -                fprintf( pFile, "  Node%d [label = \"%d_%d\"", i, Vec_IntFind(vRemap, i), i );  +                fprintf( pFile, "  Node%d [label = \"%d_%d\"", i, Vec_IntEntry(vRemap2, i), i );                   if ( Abc_Lit2Att2(Vec_IntEntry(vMarks, i)) == 2 )                      fprintf( pFile, ", shape = doubleoctagon" );                  else  diff --git a/src/aig/gia/giaStr.c b/src/aig/gia/giaStr.c index bf89b547..68d478b8 100644 --- a/src/aig/gia/giaStr.c +++ b/src/aig/gia/giaStr.c @@ -30,6 +30,7 @@ ABC_NAMESPACE_IMPL_START  ////////////////////////////////////////////////////////////////////////  #define STR_SUPER  100 +#define MAX_TREE 10000  enum {       STR_NONE   =  0, @@ -1301,7 +1302,7 @@ Gia_Man_t * Str_NtkBalance( Gia_Man_t * pGia, Str_Ntk_t * p, int nLutSize, int f          pNew->vSuper = Vec_IntAlloc( 1000 );      if ( pNew->vStore == NULL )          pNew->vStore = Vec_IntAlloc( 1000 ); -    vDelay = Vec_IntStart( pNew->nObjsAlloc ); +    vDelay = Vec_IntStart( 2*pNew->nObjsAlloc );      Gia_ManHashStart( pNew );      if ( pGia->pManTime != NULL ) // Tim_Man with unit delay 16      { @@ -1646,7 +1647,7 @@ Str_Mux_t * Str_MuxFindBranching( Str_Mux_t * pRoot, int i )  }  int Str_MuxTryOnce( Gia_Man_t * pNew, Str_Ntk_t * pNtk, Str_Mux_t * pTree, Str_Mux_t * pRoot, int Edge, Vec_Int_t * vDelay, int fVerbose )  { -    int pPath[500]; +    int pPath[MAX_TREE];      Str_Mux_t pBackup[3];      int Delay, DelayBest = Str_MuxDelayEdge_rec( pRoot, Edge ), DelayInit = DelayBest;      int i, k, nLength = 0, ForkBest = -1, nChecks = 0; @@ -1696,8 +1697,8 @@ int Str_MuxRestruct_rec( Gia_Man_t * pNew, Str_Ntk_t * pNtk, Str_Mux_t * pTree,  }  int Str_MuxRestructure2( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fVerbose )  { -    int Limit = 500; -    Str_Mux_t pTree[500]; +    int Limit = MAX_TREE; +    Str_Mux_t pTree[MAX_TREE];      int Delay, Delay2, fChanges = 0;      if ( nMuxes >= Limit )          return -1; @@ -1719,8 +1720,8 @@ int Str_MuxRestructure2( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxe  }  int Str_MuxRestructure1( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fVerbose )  { -    int Limit = 500; -    Str_Mux_t pTree[500]; +    int Limit = MAX_TREE; +    Str_Mux_t pTree[MAX_TREE];      int Delay, Delay2, fChanges = 0;      if ( nMuxes >= Limit )          return -1; @@ -1843,8 +1844,8 @@ int Str_MuxRestructArea_rec( Gia_Man_t * pNew, Str_Mux_t * pTree, Str_Mux_t * pR  }  int Str_MuxRestructureArea( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fVerbose )  { -    int Limit = 500; -    Str_Mux_t pTree[500]; +    int Limit = MAX_TREE; +    Str_Mux_t pTree[MAX_TREE];      int Result;      if ( nMuxes >= Limit )          return -1; diff --git a/src/aig/gia/giaSweep.c b/src/aig/gia/giaSweep.c index 3bb6487b..2d8e705b 100644 --- a/src/aig/gia/giaSweep.c +++ b/src/aig/gia/giaSweep.c @@ -665,6 +665,8 @@ Gia_Man_t * Gia_ManSweepWithBoxesAndDomains( Gia_Man_t * p, void * pParsS, int f              continue;          // find global equivalences          pClp = Gia_ManDupCollapse( pNew, pNew->pAigExtra, NULL, 1 ); +        //Gia_DumpAiger( pClp, p->pSpec, iDom, 2 ); +        //Gia_ManPrintStats( pClp, NULL );          // compute equivalences          Gia_ManSweepComputeOneDomainEquivs( pClp, pNew->vRegClasses, iDom, pParsS, fConst, fEquiv, fVerbose );          // transfer equivalences @@ -728,6 +730,7 @@ Gia_Man_t * Gia_ManSweepWithBoxes( Gia_Man_t * p, void * pParsC, void * pParsS,      nFlops = Vec_IntCountEntry(pNew->vRegClasses, 1);      // find global equivalences      pClp = Gia_ManDupCollapse( pNew, pNew->pAigExtra, NULL, pParsC ? 0 : 1 ); +    //Gia_DumpAiger( pClp, p->pSpec, 1, 1 );      // compute equivalences      if ( pParsC )          Gia_ManFraigSweepPerform( pClp, pParsC ); diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index 971f29bb..35b20dbe 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -642,6 +642,11 @@ extern ABC_DLL int                Abc_NtkLevelReverse( Abc_Ntk_t * pNtk );  extern ABC_DLL int                Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk );  extern ABC_DLL int                Abc_NtkIsAcyclicWithBoxes( Abc_Ntk_t * pNtk );  extern ABC_DLL Vec_Ptr_t *        Abc_AigGetLevelizedOrder( Abc_Ntk_t * pNtk, int fCollectCis ); +/*=== abcExact.c ==========================================================*/ +extern ABC_DLL int                Abc_ExactInputNum(); +extern ABC_DLL int                Abc_ExactIsRunning(); +extern ABC_DLL Abc_Obj_t *        Abc_ExactBuildNode( word * pTruth, int nVars, int * pArrTimeProfile, Abc_Obj_t ** pFanins, Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t *        Abc_NtkFindExact( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrivalTimes, int fVerbose );  /*=== abcFanio.c ==========================================================*/  extern ABC_DLL void               Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin );  extern ABC_DLL void               Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ); @@ -820,7 +825,7 @@ extern ABC_DLL void               Abc_NtkDontCareFree( Odc_Man_t * p );  extern ABC_DLL int                Abc_NtkDontCareCompute( Odc_Man_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth );  /*=== abcPrint.c ==========================================================*/  extern ABC_DLL float              Abc_NtkMfsTotalSwitching( Abc_Ntk_t * pNtk ); -extern ABC_DLL void               Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower, int fGlitch, int fSkipBuf, int fPrintMem ); +extern ABC_DLL void               Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower, int fGlitch, int fSkipBuf, int fSkipSmall, int fPrintMem );  extern ABC_DLL void               Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintFlops );  extern ABC_DLL void               Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk );  extern ABC_DLL void               Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk, int fUseFanio, int fUsePio, int fUseSupp, int fUseCone ); @@ -986,6 +991,7 @@ extern ABC_DLL double             Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk );  extern ABC_DLL int                Abc_NtkGetExorNum( Abc_Ntk_t * pNtk );  extern ABC_DLL int                Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk );  extern ABC_DLL int                Abc_NtkGetBufNum( Abc_Ntk_t * pNtk ); +extern ABC_DLL int                Abc_NtkGetLargeNodeNum( Abc_Ntk_t * pNtk );  extern ABC_DLL int                Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk );  extern ABC_DLL int                Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk );  extern ABC_DLL int                Abc_NtkGetFanoutMax( Abc_Ntk_t * pNtk ); diff --git a/src/base/abc/abcFunc.c b/src/base/abc/abcFunc.c index 94706504..5d0261d7 100644 --- a/src/base/abc/abcFunc.c +++ b/src/base/abc/abcFunc.c @@ -810,7 +810,7 @@ int Abc_NtkSopToAig( Abc_Ntk_t * pNtk )  {      Abc_Obj_t * pNode;      Hop_Man_t * pMan; -    int i; +    int i, Max;      assert( Abc_NtkHasSop(pNtk) );  @@ -819,7 +819,8 @@ int Abc_NtkSopToAig( Abc_Ntk_t * pNtk )      // start the functionality manager      pMan = Hop_ManStart(); -    Hop_IthVar( pMan, Abc_NtkGetFaninMax(pNtk)-1 ); +    Max = Abc_NtkGetFaninMax(pNtk); +    if ( Max ) Hop_IthVar( pMan, Max-1 );      // convert each node from SOP to BDD      Abc_NtkForEachNode( pNtk, pNode, i ) @@ -979,7 +980,7 @@ Gia_Man_t * Abc_NtkAigToGia( Abc_Ntk_t * p, int fGiaSimple )      Vec_Int_t * vMapping = NULL;      Vec_Ptr_t * vNodes;      Abc_Obj_t * pNode, * pFanin; -    int i, k, nObjs; +    int i, k, nObjs, iGiaObj;      assert( Abc_NtkIsAigLogic(p) );      pHopMan = (Hop_Man_t *)p->pManFunc;      // create new manager @@ -1015,15 +1016,14 @@ Gia_Man_t * Abc_NtkAigToGia( Abc_Ntk_t * p, int fGiaSimple )          {              assert( Abc_ObjFaninNum(pNode) <= Hop_ManPiNum(pHopMan) );              Abc_ConvertAigToGia( pNew, pHopObj ); -            if ( !Gia_ObjIsAnd(Gia_ManObj(pNew, Abc_Lit2Var(pHopObj->iData))) ) -                continue; -            if ( vMapping && !Vec_IntEntry(vMapping, Abc_Lit2Var(pHopObj->iData)) ) +            iGiaObj = Abc_Lit2Var( pHopObj->iData ); +            if ( vMapping && Gia_ObjIsAnd(Gia_ManObj(pNew, iGiaObj)) && !Vec_IntEntry(vMapping, iGiaObj) )              { -                Vec_IntWriteEntry( vMapping, Abc_Lit2Var(pHopObj->iData), Vec_IntSize(vMapping) ); +                Vec_IntWriteEntry( vMapping, iGiaObj, Vec_IntSize(vMapping) );                  Vec_IntPush( vMapping, Abc_ObjFaninNum(pNode) );                  Abc_ObjForEachFanin( pNode, pFanin, k )                      Vec_IntPush( vMapping, Abc_Lit2Var(pFanin->iTemp)  ); -                Vec_IntPush( vMapping, Abc_Lit2Var(pHopObj->iData) ); +                Vec_IntPush( vMapping, iGiaObj );              }          }          pNode->iTemp = Abc_LitNotCond( pHopObj->iData, Hop_IsComplement( (Hop_Obj_t *)pNode->pData ) ); diff --git a/src/base/abc/abcUtil.c b/src/base/abc/abcUtil.c index 59993614..f01ef07a 100644 --- a/src/base/abc/abcUtil.c +++ b/src/base/abc/abcUtil.c @@ -429,6 +429,26 @@ int Abc_NtkGetBufNum( Abc_Ntk_t * pNtk )  /**Function************************************************************* +  Synopsis    [Counts the number of exors.] + +  Description [] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +int Abc_NtkGetLargeNodeNum( Abc_Ntk_t * pNtk ) +{ +    Abc_Obj_t * pNode; +    int i, Counter = 0; +    Abc_NtkForEachNode( pNtk, pNode, i ) +        Counter += (Abc_ObjFaninNum(pNode) > 1); +    return Counter; +} + +/**Function************************************************************* +    Synopsis    [Returns 1 if it is an AIG with choice nodes.]    Description [] diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 699b5ec1..31f3a275 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -135,6 +135,10 @@ static int Abc_CommandCascade                ( Abc_Frame_t * pAbc, int argc, cha  static int Abc_CommandExtract                ( Abc_Frame_t * pAbc, int argc, char ** argv );  static int Abc_CommandVarMin                 ( Abc_Frame_t * pAbc, int argc, char ** argv );  static int Abc_CommandDetect                 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExact                  ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBmsStart               ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBmsStop                ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBmsPs                  ( Abc_Frame_t * pAbc, int argc, char ** argv );  static int Abc_CommandLogic                  ( Abc_Frame_t * pAbc, int argc, char ** argv );  static int Abc_CommandComb                   ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -232,6 +236,7 @@ static int Abc_CommandFraigRestore           ( Abc_Frame_t * pAbc, int argc, cha  static int Abc_CommandFraigClean             ( Abc_Frame_t * pAbc, int argc, char ** argv );  static int Abc_CommandFraigSweep             ( Abc_Frame_t * pAbc, int argc, char ** argv );  static int Abc_CommandFraigDress             ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDumpEquiv              ( Abc_Frame_t * pAbc, int argc, char ** argv );  static int Abc_CommandRecStart3              ( Abc_Frame_t * pAbc, int argc, char ** argv );  static int Abc_CommandRecStop3               ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -773,6 +778,11 @@ void Abc_Init( Abc_Frame_t * pAbc )      Cmd_CommandAdd( pAbc, "Synthesis",    "extract",       Abc_CommandExtract,          1 );      Cmd_CommandAdd( pAbc, "Synthesis",    "varmin",        Abc_CommandVarMin,           0 );      Cmd_CommandAdd( pAbc, "Synthesis",    "detect",        Abc_CommandDetect,           0 ); +    Cmd_CommandAdd( pAbc, "Synthesis",    "exact",         Abc_CommandExact,            1 ); + +    Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_start",  Abc_CommandBmsStart,         0 ); +    Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_stop",   Abc_CommandBmsStop,          0 ); +    Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_ps",     Abc_CommandBmsPs,            0 );      Cmd_CommandAdd( pAbc, "Various",      "logic",         Abc_CommandLogic,            1 );      Cmd_CommandAdd( pAbc, "Various",      "comb",          Abc_CommandComb,             1 ); @@ -867,6 +877,7 @@ void Abc_Init( Abc_Frame_t * pAbc )      Cmd_CommandAdd( pAbc, "Fraiging",     "fraig_clean",   Abc_CommandFraigClean,       0 );      Cmd_CommandAdd( pAbc, "Fraiging",     "fraig_sweep",   Abc_CommandFraigSweep,       1 );      Cmd_CommandAdd( pAbc, "Fraiging",     "dress",         Abc_CommandFraigDress,       1 ); +    Cmd_CommandAdd( pAbc, "Fraiging",     "dump_equiv",    Abc_CommandDumpEquiv,        0 );      Cmd_CommandAdd( pAbc, "Choicing",     "rec_start3",    Abc_CommandRecStart3,        0 );      Cmd_CommandAdd( pAbc, "Choicing",     "rec_stop3",     Abc_CommandRecStop3,         0 ); @@ -1223,6 +1234,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )      int fPower;      int fGlitch;      int fSkipBuf; +    int fSkipSmall;      int fPrintMem;      int c; @@ -1238,9 +1250,10 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )      fPower = 0;      fGlitch = 0;      fSkipBuf = 0; +    fSkipSmall = 0;      fPrintMem = 0;      Extra_UtilGetoptReset(); -    while ( ( c = Extra_UtilGetopt( argc, argv, "fbdltmpgsuh" ) ) != EOF ) +    while ( ( c = Extra_UtilGetopt( argc, argv, "fbdltmpgscuh" ) ) != EOF )      {          switch ( c )          { @@ -1271,6 +1284,9 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )          case 's':              fSkipBuf ^= 1;              break; +        case 'c': +            fSkipSmall ^= 1; +            break;          case 'u':              fPrintMem ^= 1;              break; @@ -1291,7 +1307,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )          Abc_Print( -1, "Cannot print LUT delay for a non-logic network.\n" );          return 1;      } -    Abc_NtkPrintStats( pNtk, fFactor, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf, fPrintMem ); +    Abc_NtkPrintStats( pNtk, fFactor, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf, fSkipSmall, fPrintMem );      if ( fPrintTime )      {          pAbc->TimeTotal += pAbc->TimeCommand; @@ -1301,7 +1317,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )      return 0;  usage: -    Abc_Print( -2, "usage: print_stats [-fbdltmpgsuh]\n" ); +    Abc_Print( -2, "usage: print_stats [-fbdltmpgscuh]\n" );      Abc_Print( -2, "\t        prints the network statistics\n" );      Abc_Print( -2, "\t-f    : toggles printing the literal count in the factored forms [default = %s]\n", fFactor? "yes": "no" );      Abc_Print( -2, "\t-b    : toggles saving the best logic network in \"best.blif\" [default = %s]\n", fSaveBest? "yes": "no" ); @@ -1312,6 +1328,7 @@ usage:      Abc_Print( -2, "\t-p    : toggles printing power dissipation due to switching [default = %s]\n", fPower? "yes": "no" );      Abc_Print( -2, "\t-g    : toggles printing percentage of increased power due to glitching [default = %s]\n", fGlitch? "yes": "no" );      Abc_Print( -2, "\t-s    : toggles not counting single-output nodes as nodes [default = %s]\n", fSkipBuf? "yes": "no" ); +    Abc_Print( -2, "\t-c    : toggles not counting constants and single-output nodes as nodes [default = %s]\n", fSkipSmall? "yes": "no" );      Abc_Print( -2, "\t-u    : toggles printing memory usage [default = %s]\n", fPrintMem? "yes": "no" );      Abc_Print( -2, "\t-h    : print the command usage\n");      return 1; @@ -1393,7 +1410,7 @@ int Abc_CommandPrintExdc( Abc_Frame_t * pAbc, int argc, char ** argv )      }      else          Abc_Print( 1, "EXDC network statistics: \n" ); -    Abc_NtkPrintStats( pNtk->pExdc, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); +    Abc_NtkPrintStats( pNtk->pExdc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );      return 0;  usage: @@ -7218,15 +7235,18 @@ usage:  ***********************************************************************/  int Abc_CommandDetect( Abc_Frame_t * pAbc, int argc, char ** argv )  { -    extern void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fVerbose ); +    extern void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fSeq, int fVerbose );      Abc_Ntk_t * pNtk; -    int c, fVerbose = 0; +    int c, fSeq = 0, fVerbose = 0;      pNtk = Abc_FrameReadNtk(pAbc);      Extra_UtilGetoptReset(); -    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) +    while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF )      {          switch ( c )          { +        case 's': +            fSeq ^= 1; +            break;          case 'v':              fVerbose ^= 1;              break; @@ -7246,12 +7266,13 @@ int Abc_CommandDetect( Abc_Frame_t * pAbc, int argc, char ** argv )          Abc_Print( -1, "Only applicable to a logic network.\n" );          return 1;      } -    Abc_NtkDetectClassesTest( pNtk, fVerbose ); +    Abc_NtkDetectClassesTest( pNtk, fSeq, fVerbose );      return 0;  usage: -    Abc_Print( -2, "usage: detect [-vh]\n" ); +    Abc_Print( -2, "usage: detect [-svh]\n" );      Abc_Print( -2, "\t           detects properties of internal nodes\n" ); +    Abc_Print( -2, "\t-s       : toggle using sequential circuit information [default = %s]\n", fSeq? "yes": "no" );      Abc_Print( -2, "\t-v       : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );      Abc_Print( -2, "\t-h       : print the command usage\n");      return 1; @@ -7268,6 +7289,310 @@ usage:    SeeAlso     []  ***********************************************************************/ +int Abc_CommandExact( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ +    extern Gia_Man_t * Gia_ManFindExact( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrivalTimes, int fVerbose ); + +    int c, nMaxDepth = -1, fMakeAIG = 0, fTest = 0, fVerbose = 0, nVars = 0, nVarsTmp, nFunc = 0; +    word pTruth[64]; +    Abc_Ntk_t * pNtkRes; +    Gia_Man_t * pGiaRes; + +    Extra_UtilGetoptReset(); +    while ( ( c = Extra_UtilGetopt( argc, argv, "Datvh" ) ) != EOF ) +    { +        switch ( c ) +        { +        case 'D': +            if ( globalUtilOptind >= argc ) +            { +                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); +                goto usage; +            } +            nMaxDepth = atoi(argv[globalUtilOptind]); +            globalUtilOptind++; +            if ( nMaxDepth < 0 ) +                goto usage; +            break; +        case 'a': +            fMakeAIG ^= 1; +            break; +        case 't': +            fTest ^= 1; +            break; +        case 'v': +            fVerbose ^= 1; +            break; +        case 'h': +            goto usage; +        default: +            goto usage; +        } +    } + +    if ( fTest ) +    { +        extern void Abc_ExactTest( int fVerbose ); +        extern void Abc_ExactStoreTest( int fVerbose ); + +        printf( "run test suite, ignore all other settings\n" ); +        Abc_ExactTest( fVerbose ); +        Abc_ExactStoreTest( fVerbose ); +        return 0; +    } + +    if ( argc == globalUtilOptind ) +        goto usage; + +    memset( pTruth, 0, 64 ); +    while ( globalUtilOptind < argc ) +    { +        if ( nFunc == 16 ) +        { +            Abc_Print( -1, "Too many functions (at most 16 supported).\n" ); +            goto usage; +        } +        nVarsTmp = Abc_TtReadHex( &pTruth[nFunc << 2], argv[globalUtilOptind++] ); +        nFunc++; +        if ( nVars == 0 ) +            nVars = nVarsTmp; +        else if ( nVars > 8 ) +        { +            Abc_Print( -1, "Only 8-variable functions are supported.\n" ); +            goto usage; +        } +        else if ( nVars != nVarsTmp ) +        { +            Abc_Print( -1, "All functions need to have the same size.\n" ); +            goto usage; +        } +    } + +    if ( fMakeAIG ) +    { +        pGiaRes = Gia_ManFindExact( pTruth, nVars, nFunc, nMaxDepth, NULL, fVerbose ); +        if ( pGiaRes ) +            Abc_FrameUpdateGia( pAbc, pGiaRes ); +        else +            Abc_Print( 0, "Could not find AIG within given resource constraints.\n" ); +    } +    else +    { +        pNtkRes = Abc_NtkFindExact( pTruth, nVars, nFunc, nMaxDepth, NULL, fVerbose ); +        if ( pNtkRes ) +        { +            Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); +            Abc_FrameClearVerifStatus( pAbc ); +        } +        else +            Abc_Print( 0, "Could not find network within given resource constraints.\n" ); +    } +    return 0; + +usage: +    Abc_Print( -2, "usage: exact [-D <num>] [-atvh] <truth1> <truth2> ...\n" ); +    Abc_Print( -2, "\t           finds optimum networks using SAT-based exact synthesis for hex truth tables <truth1> <truth2> ...\n" ); +    Abc_Print( -2, "\t-D <num> : constrain maximum depth (if too low, algorithm may not terminate)\n" ); +    Abc_Print( -2, "\t-a       : toggle create AIG [default = %s]\n", fMakeAIG ? "yes" : "no" ); +    Abc_Print( -2, "\t-t       : run test suite\n" ); +    Abc_Print( -2, "\t-v       : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no" ); +    Abc_Print( -2, "\t-h       : print the command usage\n" ); +    Abc_Print( -2, "\t\n" ); +    Abc_Print( -2, "\t           This command was contributed by Mathias Soeken from EPFL in July 2016.\n" ); +    Abc_Print( -2, "\t           The author can be contacted as mathias.soeken at epfl.ch\n" ); +    return 1; +} + +/**Function************************************************************* + +  Synopsis    [] + +  Description [] + +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +int Abc_CommandBmsStart( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ +    extern int Abc_ExactIsRunning(); +    extern void Abc_ExactStart( int nBTLimit, int fMakeAIG, int fVerbose, const char *pFilename ); + +    int c, fMakeAIG = 0, fVerbose = 0, nBTLimit = 10000; +    char * pFilename = NULL; + +    Extra_UtilGetoptReset(); +    while ( ( c = Extra_UtilGetopt( argc, argv, "Cavh" ) ) != EOF ) +    { +        switch ( c ) +        { +        case 'C': +            if ( globalUtilOptind >= argc ) +            { +                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); +                goto usage; +            } +            nBTLimit = atoi(argv[globalUtilOptind]); +            globalUtilOptind++; +            break; +        case 'a': +            fMakeAIG ^= 1; +            break; +        case 'v': +            fVerbose ^= 1; +            break; +        case 'h': +            goto usage; +        default: +            goto usage; +        } +    } + +    if ( argc > globalUtilOptind ) +    { +        pFilename = argv[globalUtilOptind++]; +    } + +    if ( Abc_ExactIsRunning() ) +    { +        Abc_Print( -1, "BMS manager is already started." ); +        return 1; +    } + +    Abc_ExactStart( nBTLimit, fMakeAIG, fVerbose, pFilename ); +    return 0; + +usage: +    Abc_Print( -2, "usage: bms_start [-C <num>] [-avh] [<file>]\n" ); +    Abc_Print( -2, "\t           starts BMS manager for recording optimum networks\n" ); +    Abc_Print( -2, "\t           if <file> is specified, store entries are read from that file\n" ); +    Abc_Print( -2, "\t-C <num> : the limit on the number of conflicts [default = %d]\n", nBTLimit ); +    Abc_Print( -2, "\t-a       : toggle create AIG [default = %s]\n", fMakeAIG ? "yes" : "no" ); +    Abc_Print( -2, "\t-v       : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no" ); +    Abc_Print( -2, "\t-h       : print the command usage\n" ); +    Abc_Print( -2, "\t\n" ); +    Abc_Print( -2, "\t           This command was contributed by Mathias Soeken from EPFL in July 2016.\n" ); +    Abc_Print( -2, "\t           The author can be contacted as mathias.soeken at epfl.ch\n" ); +    return 1; +} + +/**Function************************************************************* + +  Synopsis    [] + +  Description [] + +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +int Abc_CommandBmsStop( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ +    extern int Abc_ExactIsRunning(); +    extern void Abc_ExactStop( const char *pFilename ); + +    int c; +    char * pFilename = NULL; + +    Extra_UtilGetoptReset(); +    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) +    { +        switch ( c ) +        { +        case 'h': +            goto usage; +        default: +            goto usage; +        } +    } + +    if ( argc > globalUtilOptind ) +    { +        pFilename = argv[globalUtilOptind++]; +    } + +    if ( !Abc_ExactIsRunning() ) +    { +        Abc_Print( -1, "BMS manager is not started." ); +        return 1; +    } + +    Abc_ExactStop( pFilename ); +    return 0; + +usage: +    Abc_Print( -2, "usage: bms_stop [-C <num>] [-vh] [<file>]\n" ); +    Abc_Print( -2, "\t           stops BMS manager for recording optimum networks\n" ); +    Abc_Print( -2, "\t           if <file> is specified, store entries are written to that file\n" ); +    Abc_Print( -2, "\t-h       : print the command usage\n" ); +    Abc_Print( -2, "\t\n" ); +    Abc_Print( -2, "\t           This command was contributed by Mathias Soeken from EPFL in July 2016.\n" ); +    Abc_Print( -2, "\t           The author can be contacted as mathias.soeken at epfl.ch\n" ); +    return 1; +} + +/**Function************************************************************* + +  Synopsis    [] + +  Description [] + +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +int Abc_CommandBmsPs( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ +    extern int Abc_ExactIsRunning(); +    extern void Abc_ExactStats(); + +    int c; + +    Extra_UtilGetoptReset(); +    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) +    { +        switch ( c ) +        { +        case 'h': +            goto usage; +        default: +            goto usage; +        } +    } + +    if ( !Abc_ExactIsRunning() ) +    { +        Abc_Print( -1, "BMS manager is not started." ); +        return 1; +    } + +    Abc_ExactStats(); +    return 0; + +usage: +    Abc_Print( -2, "usage: bms_ps [-h]\n" ); +    Abc_Print( -2, "\t           shows statistics about BMS manager\n" ); +    Abc_Print( -2, "\t-h       : print the command usage\n" ); +    Abc_Print( -2, "\t\n" ); +    Abc_Print( -2, "\t           This command was contributed by Mathias Soeken from EPFL in July 2016.\n" ); +    Abc_Print( -2, "\t           The author can be contacted as mathias.soeken at epfl.ch\n" ); +    return 1; +} + +/**Function************************************************************* + +  Synopsis    [] + +  Description [] + +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/  int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv )  {      Abc_Ntk_t * pNtk, * pNtkRes; @@ -14745,6 +15070,93 @@ usage:    SeeAlso     []  ***********************************************************************/ +int Abc_CommandDumpEquiv( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ +    extern void Abc_NtkDumpEquiv( Abc_Ntk_t * pNtks[2], char * pFileName, int nConfs, int fByName, int fVerbose ); +    Abc_Ntk_t * pNtks[2] = {NULL}; +    char * pFileName[2], * pFileNameOut; +    int c, nConfs = 1000, fByName = 1, fVerbose = 0; +    Extra_UtilGetoptReset(); +    while ( ( c = Extra_UtilGetopt( argc, argv, "Cnvh" ) ) != EOF ) +    { +        switch ( c ) +        { +        case 'C': +            if ( globalUtilOptind >= argc ) +            { +                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); +                goto usage; +            } +            nConfs = atoi(argv[globalUtilOptind]); +            globalUtilOptind++; +            if ( nConfs < 0 ) +                goto usage; +            break; +        case 'n': +            fByName ^= 1; +            break; +        case 'v': +            fVerbose ^= 1; +            break; +        case 'h': +            goto usage; +        default: +            goto usage; +        } +    } +    if ( argc != globalUtilOptind + 3 ) +    { +        Abc_Print( -1, "Expecting three file names on the command line.\n" ); +        goto usage; +    } +    pFileName[0] = argv[globalUtilOptind]; +    pFileName[1] = argv[globalUtilOptind+1]; +    pFileNameOut = argv[globalUtilOptind+2]; +    for ( c = 0; c < 2; c++ ) +    { +        pNtks[c] = Io_Read( pFileName[c], Io_ReadFileType(pFileName[c]), 1, 0 ); +        if ( pNtks[c] == NULL ) +            goto usage; +        Abc_NtkToAig( pNtks[c] ); +    } +//    if ( Abc_NtkCiNum(pNtks[0]) != Abc_NtkCiNum(pNtks[1]) ) +//        Abc_Print( -1, "The number of primary inputs of networks \"%s\" and \"%s\" does not match.\n", Abc_NtkName(pNtks[0]), Abc_NtkName(pNtks[1]) ); +//    else if ( Abc_NtkCoNum(pNtks[0]) != Abc_NtkCoNum(pNtks[1]) ) +//        Abc_Print( -1, "The number of primary outputs of networks \"%s\" and \"%s\" does not match.\n", Abc_NtkName(pNtks[0]), Abc_NtkName(pNtks[1]) ); +//    else +        Abc_NtkDumpEquiv( pNtks, pFileNameOut, nConfs, fByName, fVerbose ); +    Abc_NtkDelete( pNtks[0] ); +    Abc_NtkDelete( pNtks[1] ); +    return 0; + +usage: +    Abc_Print( -2, "usage: dump_equiv [-C num] [-nvh] <file1.blif> <file2.blif> <file_dump_equiv.txt>\n" ); +    Abc_Print( -2, "\t          computes equivalence classes of nodes in <file1> and <file2>\n" ); +    Abc_Print( -2, "\t          By default this procedure performs matching of primary inputs by name.\n" ); +    Abc_Print( -2, "\t          Those inputs that cannot be matched are treated as free variables.\n" ); +    Abc_Print( -2, "\t          There is no effort to match primary outputs. Indeed, if two outputs\n" ); +    Abc_Print( -2, "\t          are equivalent, they will belong to the same equivalence class in the end.\n" ); +    Abc_Print( -2, "\t-C num  : the maximum number of conflicts at each node [default = %d]\n", nConfs ); +    Abc_Print( -2, "\t-n      : enable matching of primary inputs by name [default = %s]\n", fByName? "yes": "no" ); +    Abc_Print( -2, "\t-v      : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); +    Abc_Print( -2, "\t-h      : print the command usage\n"); +    Abc_Print( -2, "\t<file1> : first network whose nodes are considered\n" ); +    Abc_Print( -2, "\t<file2> : second network whose nodes are considered\n" ); +    Abc_Print( -2, "\t<file_dump_equiv> : text file with node equivalence classes\n" ); +    return 1; +} + +/**Function************************************************************* + +  Synopsis    [] + +  Description [] + +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/  int Abc_CommandRecStart3( Abc_Frame_t * pAbc, int argc, char ** argv )  {      char * FileName, * pTemp; @@ -16277,7 +16689,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )      If_ManSetDefaultPars( pPars );      pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut();      Extra_UtilGetoptReset(); -    while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYDEWSqaflepmrsdbgxyojiktncvh" ) ) != EOF ) +    while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYDEWSqaflepmrsdbgxyuojiktncvh" ) ) != EOF )      {          switch ( c )          { @@ -16482,6 +16894,9 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )          case 'y':              pPars->fUserRecLib ^= 1;              break; +        case 'u': +            pPars->fUserSesLib ^= 1; +            break;          case 'o':              pPars->fUseBuffs ^= 1;              break; @@ -16625,7 +17040,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )          pPars->fExpRed = 0;      }      // modify the subgraph recording -    if ( pPars->fUserRecLib ) +    if ( pPars->fUserRecLib || pPars->fUserSesLib )      {          pPars->fTruth      =  1;          pPars->fCutMin     =  1; @@ -16699,7 +17114,21 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )          }          if ( Abc_NtkRecInputNum3() != pPars->nLutSize )          { -            printf( "The number of library inputs (%d) different from the K parameters (%d).\n", Abc_NtkRecInputNum3(), pPars->nLutSize ); +            printf( "The number of library inputs (%d) is different from the K parameters (%d).\n", Abc_NtkRecInputNum3(), pPars->nLutSize ); +            return 0; +        } +    } + +    if ( pPars->fUserSesLib ) +    { +        if ( !Abc_ExactIsRunning() ) +        { +            printf( "BMS manager is not running (use \"bms_start\").\n" ); +            return 0; +        } +        if ( Abc_ExactInputNum() < pPars->nLutSize ) +        { +            printf( "The number of library inputs (%d) is smaller than the K parameters (%d).\n", Abc_ExactInputNum(), pPars->nLutSize );              return 0;          }      } @@ -16766,7 +17195,7 @@ usage:          sprintf(LutSize, "library" );      else          sprintf(LutSize, "%d", pPars->nLutSize ); -    Abc_Print( -2, "usage: if [-KCFAGRNTXY num] [-DEW float] [-S str] [-qarlepmsdbgxyojiktncvh]\n" ); +    Abc_Print( -2, "usage: if [-KCFAGRNTXY num] [-DEW float] [-S str] [-qarlepmsdbgxyuojiktncvh]\n" );      Abc_Print( -2, "\t           performs FPGA technology mapping of the network\n" );      Abc_Print( -2, "\t-K num   : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize );      Abc_Print( -2, "\t-C num   : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); @@ -16795,6 +17224,7 @@ usage:      Abc_Print( -2, "\t-g       : toggles delay optimization by SOP balancing [default = %s]\n", pPars->fDelayOpt? "yes": "no" );      Abc_Print( -2, "\t-x       : toggles delay optimization by DSD balancing [default = %s]\n", pPars->fDsdBalance? "yes": "no" );      Abc_Print( -2, "\t-y       : toggles delay optimization with recorded library [default = %s]\n", pPars->fUserRecLib? "yes": "no" ); +    Abc_Print( -2, "\t-u       : toggles delay optimization with SAT-based library [default = %s]\n", pPars->fUserSesLib? "yes": "no" );      Abc_Print( -2, "\t-o       : toggles using buffers to decouple combinational outputs [default = %s]\n", pPars->fUseBuffs? "yes": "no" );      Abc_Print( -2, "\t-j       : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck07? "yes": "no" );      Abc_Print( -2, "\t-i       : toggles using cofactoring variables [default = %s]\n", pPars->fUseCofVars? "yes": "no" ); @@ -26955,7 +27385,7 @@ usage:      Abc_Print( -2, "\t         converts the current network into GIA and moves it to the &-space\n" );      Abc_Print( -2, "\t         (if the network is a sequential logic network, normalizes the flops\n" );      Abc_Print( -2, "\t         to have const-0 initial values, equivalent to \"undc; st; zero\")\n" ); -    Abc_Print( -2, "\t-c     : toggles allowing simple GIA to be improved [default = %s]\n", fGiaSimple? "yes": "no" ); +    Abc_Print( -2, "\t-c     : toggles allowing simple GIA to be imported [default = %s]\n", fGiaSimple? "yes": "no" );      Abc_Print( -2, "\t-m     : toggles preserving the current mapping [default = %s]\n", fMapped? "yes": "no" );      Abc_Print( -2, "\t-n     : toggles saving CI/CO names of the AIG [default = %s]\n", fNames? "yes": "no" );      Abc_Print( -2, "\t-v     : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); @@ -27110,7 +27540,7 @@ usage:    SeeAlso     []  ***********************************************************************/ -static inline int Gia_ManCompareWithBest( Gia_Man_t * pBest, Gia_Man_t * p, int * pnBestLuts, int * pnBestEdges, int * pnBestLevels ) +static inline int Gia_ManCompareWithBest( Gia_Man_t * pBest, Gia_Man_t * p, int * pnBestLuts, int * pnBestEdges, int * pnBestLevels, int fArea )  {      int nCurLuts, nCurEdges, nCurLevels;      Gia_ManLutParams( p, &nCurLuts, &nCurEdges, &nCurLevels ); @@ -27119,8 +27549,9 @@ static inline int Gia_ManCompareWithBest( Gia_Man_t * pBest, Gia_Man_t * p, int           Gia_ManPoNum(pBest) != Gia_ManPoNum(p) ||            Gia_ManRegNum(pBest) != Gia_ManRegNum(p) ||           strcmp(Gia_ManName(pBest), Gia_ManName(p)) || -        (*pnBestLevels > nCurLevels) || -        (*pnBestLevels == nCurLevels && 2*(*pnBestLuts) + *pnBestEdges > 2*nCurLuts + nCurEdges) ) +         (!fArea && (*pnBestLevels > nCurLevels || (*pnBestLevels == nCurLevels && 2*(*pnBestLuts) + *pnBestEdges > 2*nCurLuts + nCurEdges))) ||  +         ( fArea && (*pnBestLuts   > nCurLuts   || (*pnBestLuts   == nCurLuts   && *pnBestLevels > nCurLevels))) +       )      {          *pnBestLuts = nCurLuts;          *pnBestEdges = nCurEdges; @@ -27143,12 +27574,15 @@ static inline int Gia_ManCompareWithBest( Gia_Man_t * pBest, Gia_Man_t * p, int  ***********************************************************************/  int Abc_CommandAbc9Save( Abc_Frame_t * pAbc, int argc, char ** argv )  { -    int c; +    int c, fArea = 0;      Extra_UtilGetoptReset(); -    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) +    while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF )      {          switch ( c )          { +        case 'a': +            fArea ^= 1; +            break;          case 'h':              goto usage;          default: @@ -27165,7 +27599,7 @@ int Abc_CommandAbc9Save( Abc_Frame_t * pAbc, int argc, char ** argv )          Abc_Print( -1, "GIA has no mapping.\n" );          return 1;      } -    if ( !Gia_ManCompareWithBest( pAbc->pGiaBest, pAbc->pGia, &pAbc->nBestLuts, &pAbc->nBestEdges, &pAbc->nBestLevels ) ) +    if ( !Gia_ManCompareWithBest( pAbc->pGiaBest, pAbc->pGia, &pAbc->nBestLuts, &pAbc->nBestEdges, &pAbc->nBestLevels, fArea ) )          return 0;      // save the design as best      Gia_ManStopP( &pAbc->pGiaBest ); @@ -27173,8 +27607,9 @@ int Abc_CommandAbc9Save( Abc_Frame_t * pAbc, int argc, char ** argv )      return 0;   usage: -    Abc_Print( -2, "usage: &save [-h]\n" ); +    Abc_Print( -2, "usage: &save [-ah]\n" );      Abc_Print( -2, "\t        compares and possibly saves AIG with mapping\n" ); +    Abc_Print( -2, "\t-a    : toggle using area as the primary metric [default = %s]\n", fArea? "yes": "no" );      Abc_Print( -2, "\t-h    : print the command usage\n");      return 1;  } @@ -33363,7 +33798,7 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv )      {          if ( !Abc_FrameReadFlag("silentmode") )          Abc_Print( -1, "Empty GIA network.\n" ); -        return 1; +        return 0;      }      if ( Gia_ManBufNum(pAbc->pGia) )      { @@ -35224,14 +35659,23 @@ int Abc_CommandAbc9Edge( Abc_Frame_t * pAbc, int argc, char ** argv )  {      extern int Edg_ManAssignEdgeNew( Gia_Man_t * p, int nEdges, int fVerbose );      extern void Seg_ManComputeDelay( Gia_Man_t * pGia, int Delay, int nFanouts, int fTwo, int fVerbose ); -    extern void Sle_ManExplore( Gia_Man_t * pGia, int DelayInit, int fVerbose ); +    extern void Sle_ManExplore( Gia_Man_t * pGia, int nBTLimit, int DelayInit, int fDynamic, int fTwoEdges, int fVerbose ); -    int c, DelayMax = 0, nFanouts = 0, nEdges = 1, fReverse = 0, fUsePack = 0, fUseOld = 0, fMapping = 0, fVerbose = 0; +    int c, nBTLimit = 0, DelayMax = 0, nFanouts = 0, nEdges = 1, fReverse = 0, fUsePack = 0, fUseOld = 0, fMapping = 0, fDynamic = 1, fVerbose = 0;      Extra_UtilGetoptReset(); -    while ( ( c = Extra_UtilGetopt( argc, argv, "DFErpomvh" ) ) != EOF ) +    while ( ( c = Extra_UtilGetopt( argc, argv, "CDFErpomdvh" ) ) != EOF )      {          switch ( c )          { +            case 'C': +                if ( globalUtilOptind >= argc ) +                { +                    Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" ); +                    goto usage; +                } +                nBTLimit = atoi(argv[globalUtilOptind]); +                globalUtilOptind++; +                break;              case 'D':                  if ( globalUtilOptind >= argc )                  { @@ -35276,6 +35720,9 @@ int Abc_CommandAbc9Edge( Abc_Frame_t * pAbc, int argc, char ** argv )              case 'm':                  fMapping ^= 1;                  break; +            case 'd': +                fDynamic ^= 1; +                break;              case 'v':                  fVerbose ^= 1;                  break; @@ -35289,16 +35736,16 @@ int Abc_CommandAbc9Edge( Abc_Frame_t * pAbc, int argc, char ** argv )          Abc_Print( -1, "Empty GIA network.\n" );          return 1;      } +    if ( fMapping ) +    { +        Sle_ManExplore( pAbc->pGia, nBTLimit, DelayMax, fDynamic, nEdges==2, fVerbose ); +        return 0; +    }      if ( !Gia_ManHasMapping(pAbc->pGia) )      {          Abc_Print( -1, "Current AIG has no mapping. Run \"&if\".\n" );          return 1;      } -    if ( fMapping ) -    { -        Sle_ManExplore( pAbc->pGia, DelayMax, fVerbose ); -        return 0; -    }      if ( Gia_ManLutSizeMax(pAbc->pGia) > 6 )      {          Abc_Print( 0, "Current AIG has mapping into %d-LUTs.\n", Gia_ManLutSizeMax(pAbc->pGia) ); @@ -35333,8 +35780,9 @@ int Abc_CommandAbc9Edge( Abc_Frame_t * pAbc, int argc, char ** argv )      return 0;  usage: -    Abc_Print( -2, "usage: &edge [-DFE num] [-rpomvh]\n" ); +    Abc_Print( -2, "usage: &edge [-CDFE num] [-rpomdvh]\n" );      Abc_Print( -2, "\t           find edge assignment of the LUT-mapped network\n" ); +    Abc_Print( -2, "\t-C num   : the SAT solver conflict limit (0 = unused) [default = %d]\n", nBTLimit );      Abc_Print( -2, "\t-D num   : the upper bound on delay [default = %d]\n", DelayMax );      Abc_Print( -2, "\t-F num   : skip using edge if fanout higher than this [default = %d]\n", nFanouts );      Abc_Print( -2, "\t-E num   : the limit on the number of edges (1 <= num <= 2) [default = %d]\n", nEdges ); @@ -35342,6 +35790,7 @@ usage:      Abc_Print( -2, "\t-p       : toggles deriving edges from packing [default = %s]\n", fUsePack? "yes": "no" );      Abc_Print( -2, "\t-o       : toggles using old algorithm [default = %s]\n", fUseOld? "yes": "no" );      Abc_Print( -2, "\t-m       : toggles combining edge assignment with mapping [default = %s]\n", fMapping? "yes": "no" ); +    Abc_Print( -2, "\t-d       : toggles dynamic addition of clauses [default = %s]\n", fDynamic? "yes": "no" );      Abc_Print( -2, "\t-v       : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );      Abc_Print( -2, "\t-h       : prints the command usage\n");      return 1; @@ -35505,6 +35954,8 @@ int Abc_CommandAbc9Unmap( Abc_Frame_t * pAbc, int argc, char ** argv )      Vec_IntFreeP( &pAbc->pGia->vMapping );      Vec_IntFreeP( &pAbc->pGia->vPacking );      Vec_IntFreeP( &pAbc->pGia->vCellMapping ); +    Vec_IntFreeP( &pAbc->pGia->vEdge1 ); +    Vec_IntFreeP( &pAbc->pGia->vEdge2 );      return 0;  usage: @@ -39675,7 +40126,7 @@ usage:  int Abc_CommandAbc9Polyn( Abc_Frame_t * pAbc, int argc, char ** argv )  {      Vec_Int_t * vOrder = NULL; -    int c, fSimple = 0, fSigned = 0, fVerbose = 0, fVeryVerbose = 0; +    int c, fSimple = 1, fSigned = 0, fVerbose = 0, fVeryVerbose = 0;      Extra_UtilGetoptReset();      while ( ( c = Extra_UtilGetopt( argc, argv, "asvwh" ) ) != EOF )      { diff --git a/src/base/abci/abcDetect.c b/src/base/abci/abcDetect.c index 8fa395e8..c87169b5 100644 --- a/src/base/abci/abcDetect.c +++ b/src/base/abci/abcDetect.c @@ -193,7 +193,7 @@ finish:    SeeAlso     []  ***********************************************************************/ -void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fVerbose ) +void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fSeq, int fVerbose )  {      printf( "This procedure is currently not used.\n" );  } diff --git a/src/base/abci/abcDress3.c b/src/base/abci/abcDress3.c new file mode 100644 index 00000000..33545f0a --- /dev/null +++ b/src/base/abci/abcDress3.c @@ -0,0 +1,344 @@ +/**CFile**************************************************************** + +  FileName    [abcDress3.c] + +  SystemName  [ABC: Logic synthesis and verification system.] + +  PackageName [Network and node package.] + +  Synopsis    [Transfers names from one netlist to the other.] + +  Author      [Alan Mishchenko] +   +  Affiliation [UC Berkeley] + +  Date        [Ver. 1.0. Started - June 20, 2005.] + +  Revision    [$Id: abcDress3.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "base/abc/abc.h" +#include "base/io/ioAbc.h" +#include "proof/cec/cec.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +///                        DECLARATIONS                              /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +///                     FUNCTION DEFINITIONS                         /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + +  Synopsis    [Compute equivalence classes of nodes.] + +  Description [] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +void Abc_NtkComputeGiaEquivs( Gia_Man_t * pGia, int nConfs, int fVerbose ) +{ +    Gia_Man_t * pTemp; +    Cec_ParFra_t ParsFra, * pPars = &ParsFra; +    Cec_ManFraSetDefaultParams( pPars ); +    pPars->fUseOrigIds = 1; +    pPars->fSatSweeping = 1; +    pPars->nBTLimit = nConfs; +    pPars->fVerbose = fVerbose; +    pTemp = Cec_ManSatSweeping( pGia, pPars, 0 ); +    Gia_ManStop( pTemp ); +    pTemp = Gia_ManOrigIdsReduce( pGia, pGia->vIdsEquiv ); +    Gia_ManStop( pTemp ); +} + +/**Function************************************************************* + +  Synopsis    [Converts AIG from HOP to GIA.] + +  Description [] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +void Abc_ConvertHopToGia_rec1( Gia_Man_t * p, Hop_Obj_t * pObj ) +{ +    assert( !Hop_IsComplement(pObj) ); +    if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) +        return; +    Abc_ConvertHopToGia_rec1( p, Hop_ObjFanin0(pObj) );  +    Abc_ConvertHopToGia_rec1( p, Hop_ObjFanin1(pObj) ); +    pObj->iData = Gia_ManHashAnd( p, Hop_ObjChild0CopyI(pObj), Hop_ObjChild1CopyI(pObj) ); +    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection +    Hop_ObjSetMarkA( pObj ); +} +void Abc_ConvertHopToGia_rec2( Hop_Obj_t * pObj ) +{ +    assert( !Hop_IsComplement(pObj) ); +    if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) +        return; +    Abc_ConvertHopToGia_rec2( Hop_ObjFanin0(pObj) );  +    Abc_ConvertHopToGia_rec2( Hop_ObjFanin1(pObj) ); +    assert( Hop_ObjIsMarkA(pObj) ); // loop detection +    Hop_ObjClearMarkA( pObj ); +} +int Abc_ConvertHopToGia( Gia_Man_t * p, Hop_Obj_t * pRoot ) +{ +    assert( !Hop_IsComplement(pRoot) ); +    if ( Hop_ObjIsConst1( pRoot ) ) +        return 1; +    Abc_ConvertHopToGia_rec1( p, pRoot ); +    Abc_ConvertHopToGia_rec2( pRoot ); +    return pRoot->iData; +} + +/**Function************************************************************* + +  Synopsis    [Add logic from pNtk to the AIG manager p.] + +  Description [] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +void Abc_NtkAigToGiaOne( Gia_Man_t * p, Abc_Ntk_t * pNtk, Vec_Int_t * vMap ) +{ +    Hop_Man_t * pHopMan; +    Hop_Obj_t * pHopObj; +    Vec_Ptr_t * vNodes; +    Abc_Obj_t * pNode, * pFanin; +    int i, k; +    assert( Abc_NtkIsAigLogic(pNtk) ); +    pHopMan = (Hop_Man_t *)pNtk->pManFunc; +    Hop_ManConst1(pHopMan)->iData = 1; +    // image primary inputs +    Abc_NtkCleanCopy( pNtk ); +    Abc_NtkForEachCi( pNtk, pNode, i ) +        pNode->iTemp = Gia_ManCiLit(p, Vec_IntEntry(vMap, i)); +    // iterate through nodes used in the mapping +    vNodes = Abc_NtkDfs( pNtk, 1 ); +    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) +    { +        Abc_ObjForEachFanin( pNode, pFanin, k ) +            Hop_ManPi(pHopMan, k)->iData = pFanin->iTemp; +        pHopObj = Hop_Regular( (Hop_Obj_t *)pNode->pData ); +        assert( Abc_ObjFaninNum(pNode) <= Hop_ManPiNum(pHopMan) ); +        if ( Hop_DagSize(pHopObj) > 0 ) +            Abc_ConvertHopToGia( p, pHopObj ); +        pNode->iTemp = Abc_LitNotCond( pHopObj->iData, Hop_IsComplement( (Hop_Obj_t *)pNode->pData ) ); +    } +    Vec_PtrFree( vNodes ); +    // create primary outputs +    Abc_NtkForEachCo( pNtk, pNode, i ) +        Gia_ManAppendCo( p, Abc_ObjFanin0(pNode)->iTemp ); +} +Gia_Man_t * Abc_NtkAigToGiaTwo( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fByName ) +{ +    Gia_Man_t * p; +    Gia_Obj_t * pObj; +    Abc_Obj_t * pNode; +    Vec_Int_t * vMap1, * vMap2; +    int i, Index = 0; +    assert( Abc_NtkIsAigLogic(pNtk1) ); +    assert( Abc_NtkIsAigLogic(pNtk2) ); +    // find common variables +    if ( fByName ) +    { +        int nCommon = 0; +        vMap1 = Vec_IntStartNatural( Abc_NtkCiNum(pNtk1) ); +        vMap2 = Vec_IntAlloc( Abc_NtkCiNum(pNtk2) ); +        Abc_NtkForEachCi( pNtk1, pNode, i ) +            pNode->iTemp = Index++; +        assert( Index == Abc_NtkCiNum(pNtk1) ); +        Abc_NtkForEachCi( pNtk2, pNode, i ) +        { +            int Num = Nm_ManFindIdByName( pNtk1->pManName, Abc_ObjName(pNode), ABC_OBJ_PI ); +            if ( Num < 0 ) +                Num = Nm_ManFindIdByName( pNtk1->pManName, Abc_ObjName(pNode), ABC_OBJ_BO ); +            assert( Num < 0 || Abc_ObjIsCi(Abc_NtkObj(pNtk1, Num)) ); +            if ( Num >= 0 ) +                Vec_IntPush( vMap2, Abc_NtkObj(pNtk1, Num)->iTemp ), nCommon++; +            else +                Vec_IntPush( vMap2, Index++ ); +        } +        // report +        printf( "Matched %d vars by name.", nCommon ); +        if ( nCommon != Abc_NtkCiNum(pNtk1) ) +            printf( " Netlist1 has %d unmatched vars.", Abc_NtkCiNum(pNtk1) - nCommon ); +        if ( nCommon != Abc_NtkCiNum(pNtk2) ) +            printf( " Netlist2 has %d unmatched vars.", Abc_NtkCiNum(pNtk2) - nCommon ); +        printf( "\n" ); +    } +    else +    { +        vMap1 = Vec_IntStartNatural( Abc_NtkCiNum(pNtk1) ); +        vMap2 = Vec_IntStartNatural( Abc_NtkCiNum(pNtk2) ); +        Index = Abc_MaxInt( Vec_IntSize(vMap1), Vec_IntSize(vMap2) ); +        // report +        printf( "Matched %d vars by order.", Abc_MinInt(Abc_NtkCiNum(pNtk1), Abc_NtkCiNum(pNtk2)) ); +        if ( Abc_NtkCiNum(pNtk1) < Abc_NtkCiNum(pNtk2) ) +            printf( " The last %d vars of Netlist2 are unmatched vars.", Abc_NtkCiNum(pNtk2) - Abc_NtkCiNum(pNtk1) ); +        if ( Abc_NtkCiNum(pNtk1) > Abc_NtkCiNum(pNtk2) ) +            printf( " The last %d vars of Netlist1 are unmatched vars.", Abc_NtkCiNum(pNtk1) - Abc_NtkCiNum(pNtk2) ); +        printf( "\n" ); +    } +    // create new manager +    p = Gia_ManStart( 10000 ); +    p->pName = Abc_UtilStrsav( Abc_NtkName(pNtk1) ); +    p->pSpec = Abc_UtilStrsav( Abc_NtkSpec(pNtk1) ); +    for ( i = 0; i < Index; i++ ) +        Gia_ManAppendCi(p); +    // add logic +    Gia_ManHashAlloc( p ); +    Abc_NtkAigToGiaOne( p, pNtk1, vMap1 ); +    Abc_NtkAigToGiaOne( p, pNtk2, vMap2 ); +    Gia_ManHashStop( p ); +    Vec_IntFree( vMap1 ); +    Vec_IntFree( vMap2 ); +    // add extra POs to dangling nodes +    Gia_ManCreateValueRefs( p ); +    Gia_ManForEachAnd( p, pObj, i ) +        if ( pObj->Value == 0 ) +            Gia_ManAppendCo( p, Abc_Var2Lit(i, 0) ); +    return p; +} + +/**Function************************************************************* + +  Synopsis    [Collect equivalence class information.] + +  Description [Each class is represented as follows:  +      <num_entries><entry1><entry2>...<entryN>  +  where <entry> is nodeId with 1-bit for complement and 1-bit for network.] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +static inline void Abc_NtkCollectAddOne( int iNtk, int iObj, int iGiaLit, Gia_Man_t * pGia, Vec_Int_t * vGia2Cla, Vec_Int_t * vNexts[2] ) +{ +    int iRepr = Gia_ObjReprSelf( pGia, Abc_Lit2Var(iGiaLit) ); +    int Compl = Abc_LitIsCompl(iGiaLit) ^ Gia_ObjPhase(Gia_ManObj(pGia, iRepr)) ^ Gia_ObjPhase(Gia_ManObj(pGia, Abc_Lit2Var(iGiaLit))); +    int Added = Abc_Var2Lit( Abc_Var2Lit(iObj, Compl), iNtk ); +    int Entry = Vec_IntEntry( vGia2Cla, iRepr ); +    Vec_IntWriteEntry( vNexts[iNtk], iObj, Entry ); +    Vec_IntWriteEntry( vGia2Cla, iRepr, Added ); +} +Vec_Int_t * Abc_NtkCollectEquivClasses( Abc_Ntk_t * pNtks[2], Gia_Man_t * pGia ) +{ +    Vec_Int_t * vClass = Vec_IntAlloc( 100 ); +    Vec_Int_t * vClasses = Vec_IntAlloc( 1000 ); +    Vec_Int_t * vGia2Cla = Vec_IntStartFull( Gia_ManObjNum(pGia) ); // mapping objId into classId +    Vec_Int_t * vNexts[2] = { Vec_IntStartFull(Abc_NtkObjNumMax(pNtks[0])), Vec_IntStartFull(Abc_NtkObjNumMax(pNtks[1])) }; +    Abc_Obj_t * pObj; +    int n, i, k, Entry, fCompl; +    Abc_NtkForEachCi( pNtks[0], pObj, i ) +        Abc_NtkCollectAddOne( 0, Abc_ObjId(pObj), pObj->iTemp, pGia, vGia2Cla, vNexts ); +    for ( n = 0; n < 2; n++ ) +        Abc_NtkForEachNode( pNtks[n], pObj, i ) +            Abc_NtkCollectAddOne( n, Abc_ObjId(pObj), pObj->iTemp, pGia, vGia2Cla, vNexts ); +    Vec_IntForEachEntry( vGia2Cla, Entry, i ) +    { +        Vec_IntClear( vClass ); +        for ( ; Entry >= 0; Entry = Vec_IntEntry(vNexts[Entry&1], Entry>>2) ) +            Vec_IntPush( vClass, Entry ); +        if ( Vec_IntSize(vClass) < 2 ) +            continue; +        Vec_IntReverseOrder( vClass ); +        fCompl = 2 & Vec_IntEntry( vClass, 0 ); +        Vec_IntForEachEntry( vClass, Entry, k ) +            Vec_IntWriteEntry( vClass, k, Entry ^ fCompl );         +        Vec_IntPush( vClasses, Vec_IntSize(vClass) ); +        Vec_IntAppend( vClasses, vClass ); +    } +    Vec_IntFree( vGia2Cla ); +    Vec_IntFree( vNexts[0] ); +    Vec_IntFree( vNexts[1] ); +    Vec_IntFree( vClass ); +    return vClasses; +} + +/**Function************************************************************* + +  Synopsis    [Write the output file.] + +  Description [] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +void Abc_NtkDumpEquivFile( char * pFileName, Vec_Int_t * vClasses, Abc_Ntk_t * pNtks[2] ) +{ +    int i, c, k, Entry; +    FILE * pFile = fopen( pFileName, "wb" ); +    if ( pFile == NULL ) { printf( "Cannot open file %s for writing.\n", pFileName ); return; } +    fprintf( pFile, "# Node equivalences computed by ABC for networks \"%s\" and \"%s\" on %s\n\n", Abc_NtkName(pNtks[0]), Abc_NtkName(pNtks[1]), Extra_TimeStamp() ); +    for ( i = c = 0; i < Vec_IntSize(vClasses); c++, i += 1 + Vec_IntEntry(vClasses, i) ) +    { +        Vec_IntForEachEntryStartStop( vClasses, Entry, k, i + 1, i + 1 + Vec_IntEntry(vClasses, i) ) +        { +            Abc_Ntk_t * pNtk = pNtks[Entry & 1]; +            char * pObjName = Abc_ObjName( Abc_NtkObj(pNtk, Entry>>2) ); +            fprintf( pFile, "%d:%s:%s%s\n", c+1, Abc_NtkName(pNtk), (Entry&2) ? "NOT:":"", pObjName ); +        } +        fprintf( pFile, "\n" ); +    } +    fclose( pFile ); +} + + +/**Function************************************************************* + +  Synopsis    [Compute and dump equivalent name classes.] + +  Description [] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +void Abc_NtkDumpEquiv( Abc_Ntk_t * pNtks[2], char * pFileName, int nConfs, int fByName, int fVerbose ) +{ +    //abctime clk = Abc_Clock(); +    Vec_Int_t * vClasses; +    // derive shared AIG for the two networks +    Gia_Man_t * pGia = Abc_NtkAigToGiaTwo( pNtks[0], pNtks[1], fByName ); +    if ( fVerbose ) +        printf( "Computing equivalences for networks \"%s\" and \"%s\" with conflict limit %d.\n", Abc_NtkName(pNtks[0]), Abc_NtkName(pNtks[1]), nConfs ); +    // compute equivalences in this AIG +    Abc_NtkComputeGiaEquivs( pGia, nConfs, fVerbose ); +    //if ( fVerbose ) +    //    Abc_PrintTime( 1, "Equivalence computation time", Abc_Clock() - clk ); +    if ( fVerbose ) +        Gia_ManPrintStats( pGia, NULL ); +    // collect equivalence class information +    vClasses = Abc_NtkCollectEquivClasses( pNtks, pGia ); +    Gia_ManStop( pGia ); +    // dump information into the output file +    Abc_NtkDumpEquivFile( pFileName, vClasses, pNtks ); +    Vec_IntFree( vClasses ); +} + + +//////////////////////////////////////////////////////////////////////// +///                       END OF FILE                                /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/base/abci/abcExact.c b/src/base/abci/abcExact.c new file mode 100644 index 00000000..8c508b63 --- /dev/null +++ b/src/base/abci/abcExact.c @@ -0,0 +1,1696 @@ +/**CFile**************************************************************** + +  FileName    [abcExact.c] + +  SystemName  [ABC: Logic synthesis and verification system.] + +  PackageName [Network and node package.] + +  Synopsis    [Find minimum size networks with a SAT solver.] + +  Author      [Mathias Soeken] + +  Affiliation [EPFL] + +  Date        [Ver. 1.0. Started - July 15, 2016.] + +  Revision    [$Id: abcFanio.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +/* This implementation is based on Exercises 477 and 478 in + * Donald E. Knuth TAOCP Fascicle 6 (Satisfiability) Section 7.2.2.2 + */ + +#include "base/abc/abc.h" + +#include "aig/gia/gia.h" +#include "bool/kit/kit.h" +#include "misc/util/utilTruth.h" +#include "misc/vec/vecInt.h" +#include "misc/vec/vecPtr.h" +#include "proof/cec/cec.h" +#include "sat/bsat/satSolver.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +///                        DECLARATIONS                              /// +//////////////////////////////////////////////////////////////////////// + +static word s_Truths8[32] = { +    ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xAAAAAAAAAAAAAAAA), +    ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xCCCCCCCCCCCCCCCC), +    ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xF0F0F0F0F0F0F0F0), +    ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFF00FF00FF00FF00), +    ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFF0000FFFF0000), +    ABC_CONST(0xFFFFFFFF00000000), ABC_CONST(0xFFFFFFFF00000000), ABC_CONST(0xFFFFFFFF00000000), ABC_CONST(0xFFFFFFFF00000000), +    ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFFFFFFFFFF), ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFFFFFFFFFF), +    ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFFFFFFFFFF), ABC_CONST(0xFFFFFFFFFFFFFFFF) +}; + +#define ABC_EXACT_SOL_NVARS  0 +#define ABC_EXACT_SOL_NFUNC  1 +#define ABC_EXACT_SOL_NGATES 2 + +typedef struct Ses_Man_t_ Ses_Man_t; +struct Ses_Man_t_ +{ +    sat_solver * pSat;            /* SAT solver */ + +    word *       pSpec;           /* specification */ +    int          bSpecInv;        /* remembers whether spec was inverted for normalization */ +    int          nSpecVars;       /* number of variables in specification */ +    int          nSpecFunc;       /* number of functions to synthesize */ +    int          nRows;           /* number of rows in the specification (without 0) */ +    int          nMaxDepth;       /* maximum depth (-1 if depth is not constrained) */ +    int *        pArrTimeProfile; /* arrival times of inputs (NULL if arrival times are ignored) */ +    int          nArrTimeDelta;   /* delta to the original arrival times (arrival times are normalized to have 0 as minimum element) */ +    int          nArrTimeMax;     /* maximum normalized arrival time */ +    int          nBTLimit;        /* conflict limit */ +    int          fMakeAIG;        /* create AIG instead of general network */ +    int          fVerbose;        /* be verbose */ +    int          fVeryVerbose;    /* be very verbose */ + +    int          nGates;          /* number of gates */ + +    int          nSimVars;        /* number of simulation vars x(i, t) */ +    int          nOutputVars;     /* number of output variables g(h, i) */ +    int          nGateVars;       /* number of gate variables f(i, p, q) */ +    int          nSelectVars;     /* number of select variables s(i, j, k) */ +    int          nDepthVars;      /* number of depth variables d(i, j) */ + +    int          nOutputOffset;   /* offset where output variables start */ +    int          nGateOffset;     /* offset where gate variables start */ +    int          nSelectOffset;   /* offset where select variables start */ +    int          nDepthOffset;    /* offset where depth variables start */ + +    abctime      timeSat;         /* SAT runtime */ +    abctime      timeSatSat;      /* SAT runtime (sat instance) */ +    abctime      timeSatUnsat;    /* SAT runtime (unsat instance) */ +    abctime      timeTotal;       /* all runtime */ +}; + +/*********************************************************************** + +  Synopsis    [Store truth tables based on normalized arrival times.] + +***********************************************************************/ + +// The hash table is a list of pointers to Ses_TruthEntry_t elements, which +// are arranged in a linked list, each of which pointing to a linked list +// of Ses_TimesEntry_t elements which contain the char* representation of the +// optimum netlist according to then normalized arrival times: + +typedef struct Ses_TimesEntry_t_ Ses_TimesEntry_t; +struct Ses_TimesEntry_t_ +{ +    int                pArrTimeProfile[8]; /* normalized arrival time profile */ +    Ses_TimesEntry_t * next;               /* linked list pointer */ +    char *             pNetwork;           /* pointer to char array representation of optimum network */ +}; + +typedef struct Ses_TruthEntry_t_ Ses_TruthEntry_t; +struct Ses_TruthEntry_t_ +{ +    word               pTruth[4]; /* truth table for comparison */ +    int                nVars;     /* number of variables */ +    Ses_TruthEntry_t * next;      /* linked list pointer */ +    Ses_TimesEntry_t * head;      /* pointer to head of sub list with arrival times */ +}; + +#define SES_STORE_TABLE_SIZE 1024 +typedef struct Ses_Store_t_ Ses_Store_t; +struct Ses_Store_t_ +{ +    int                fMakeAIG;                       /* create AIG instead of general network */ +    int                fVerbose;                       /* be verbose */ +    int                nBTLimit;                       /* conflict limit */ +    int                nEntriesCount;                  /* number of entries */ +    Ses_TruthEntry_t * pEntries[SES_STORE_TABLE_SIZE]; /* hash table for truth table entries */ + +    unsigned long      nCutCount; +    unsigned long      pCutCount[9]; +    unsigned long      nCacheHit; +}; + +static Ses_Store_t * s_pSesStore = NULL; + +//////////////////////////////////////////////////////////////////////// +///                     FUNCTION DEFINITIONS                         /// +//////////////////////////////////////////////////////////////////////// + +static int Abc_NormalizeArrivalTimes( int * pArrTimeProfile, int nVars, int * maxNormalized ) +{ +    int * p = pArrTimeProfile, * pEnd = pArrTimeProfile + nVars; +    int delta = *p; + +    while ( ++p < pEnd ) +        if ( *p < delta ) +            delta = *p; + +    *maxNormalized = 0; +    p = pArrTimeProfile; +    while ( p < pEnd ) +    { +        *p -= delta; +        if ( *p > *maxNormalized ) +            *maxNormalized = *p; +        ++p; +    } + +    *maxNormalized += 1; + +    return delta; +} + +static inline Ses_Store_t * Ses_StoreAlloc( int nBTLimit, int fMakeAIG, int fVerbose ) +{ +    Ses_Store_t * pStore = ABC_CALLOC( Ses_Store_t, 1 ); +    pStore->fMakeAIG      = fMakeAIG; +    pStore->fVerbose      = fVerbose; +    pStore->nBTLimit      = nBTLimit; +    pStore->nEntriesCount = 0; +    memset( pStore->pEntries, 0, SES_STORE_TABLE_SIZE ); + +    pStore->nCutCount = 0; +    memset( pStore->pCutCount, 0, 9 ); +    pStore->nCacheHit = 0; + +    return pStore; +} + +static inline void Ses_StoreClean( Ses_Store_t * pStore ) +{ +    int i; +    Ses_TruthEntry_t * pTEntry, * pTEntry2; +    Ses_TimesEntry_t * pTiEntry, * pTiEntry2; + +    for ( i = 0; i < SES_STORE_TABLE_SIZE; ++i ) +        if ( pStore->pEntries[i] ) +        { +            pTEntry = pStore->pEntries[i]; + +            while ( pTEntry ) +            { +                pTiEntry = pTEntry->head; +                while ( pTiEntry ) +                { +                    ABC_FREE( pTiEntry->pNetwork ); +                    pTiEntry2 = pTiEntry; +                    pTiEntry = pTiEntry->next; +                    ABC_FREE( pTiEntry2 ); +                } +                pTEntry2 = pTEntry; +                pTEntry = pTEntry->next; +                ABC_FREE( pTEntry2 ); +            } +        } + +    ABC_FREE( pStore ); +} + +static inline int Ses_StoreTableHash( word * pTruth, int nVars ) +{ +    static int s_Primes[4] = { 1291, 1699, 1999, 2357 }; +    int i; +    unsigned uHash = 0; +    for ( i = 0; i < Kit_TruthWordNum( nVars ); ++i ) +        uHash ^= pTruth[i] * s_Primes[i & 0xf]; +    return (int)(uHash % SES_STORE_TABLE_SIZE ); +} + +static inline int Ses_StoreTruthEqual( Ses_TruthEntry_t * pEntry, word * pTruth, int nVars ) +{ +    int i; + +    if ( pEntry->nVars != nVars ) +        return 0; + +    for ( i = 0; i < Kit_TruthWordNum( nVars ); ++i ) +        if ( pEntry->pTruth[i] != pTruth[i] ) +            return 0; +    return 1; +} + +static inline void Ses_StoreTruthCopy( Ses_TruthEntry_t * pEntry, word * pTruthSrc, int nVars ) +{ +    int i; +    pEntry->nVars = nVars; +    for ( i = 0; i < Kit_TruthWordNum( nVars ); ++i ) +        pEntry->pTruth[i] = pTruthSrc[i]; +} + +static inline int Ses_StoreTimesEqual( int * pTimes1, int * pTimes2, int nVars ) +{ +    int i; +    for ( i = 0; i < nVars; ++i ) +        if ( pTimes1[i] != pTimes2[i] ) +            return 0; +    return 1; +} + +static inline void Ses_StoreTimesCopy( int * pTimesDest, int * pTimesSrc, int nVars ) +{ +    int i; +    for ( i = 0; i < nVars; ++i ) +        pTimesDest[i] = pTimesSrc[i]; +} + +// pArrTimeProfile is not normalized +// returns 1 if and only if a new TimesEntry has been created +int Ses_StoreAddEntry( Ses_Store_t * pStore, word * pTruth, int nVars, int * pArrTimeProfile, char * pSol ) +{ +    int i, nDelta, maxNormalized, key, fAdded; +    Ses_TruthEntry_t * pTEntry; +    Ses_TimesEntry_t * pTiEntry; + +    nDelta = Abc_NormalizeArrivalTimes( pArrTimeProfile, nVars, &maxNormalized ); + +    key = Ses_StoreTableHash( pTruth, nVars ); +    pTEntry = pStore->pEntries[key]; + +    /* does truth table already exist? */ +    while ( pTEntry ) +    { +        if ( Ses_StoreTruthEqual( pTEntry, pTruth, nVars ) ) +            break; +        else +            pTEntry = pTEntry->next; +    } + +    /* entry does not yet exist, so create new one and enqueue */ +    if ( !pTEntry ) +    { +        pTEntry = ABC_CALLOC( Ses_TruthEntry_t, 1 ); +        Ses_StoreTruthCopy( pTEntry, pTruth, nVars ); +        pTEntry->next = pStore->pEntries[key]; +        pStore->pEntries[key] = pTEntry; +    } + +    /* does arrival time already exist? */ +    pTiEntry = pTEntry->head; +    while ( pTiEntry ) +    { +        if ( Ses_StoreTimesEqual( pArrTimeProfile, pTiEntry->pArrTimeProfile, nVars ) ) +            break; +        else +            pTiEntry = pTiEntry->next; +    } + +    /* entry does not yet exist, so create new one and enqueue */ +    if ( !pTiEntry ) +    { +        pTiEntry = ABC_CALLOC( Ses_TimesEntry_t, 1 ); +        Ses_StoreTimesCopy( pTiEntry->pArrTimeProfile, pArrTimeProfile, nVars ); +        pTiEntry->pNetwork = pSol; +        pTiEntry->next = pTEntry->head; +        pTEntry->head = pTiEntry; + +        /* item has been added */ +        fAdded = 1; +        pStore->nEntriesCount++; +    } +    else +        /* item was already present */ +        fAdded = 0; + +    for ( i = 0; i < nVars; ++i ) +        pArrTimeProfile[i] += nDelta; +    return fAdded; +} + +// pArrTimeProfile is not normalized +// returns 0 if no solution was found +char * Ses_StoreGetEntry( Ses_Store_t * pStore, word * pTruth, int nVars, int * pArrTimeProfile ) +{ +    int i, nDelta, maxNormalized, key; +    Ses_TruthEntry_t * pTEntry; +    Ses_TimesEntry_t * pTiEntry; + +    key = Ses_StoreTableHash( pTruth, nVars ); +    pTEntry = pStore->pEntries[key]; + +    /* find truth table entry */ +    while ( pTEntry ) +    { +        if ( Ses_StoreTruthEqual( pTEntry, pTruth, nVars ) ) +            break; +        else +            pTEntry = pTEntry->next; +    } + +    /* no entry found? */ +    if ( !pTEntry ) +        return 0; + +    nDelta = Abc_NormalizeArrivalTimes( pArrTimeProfile, nVars, &maxNormalized ); + +    /* find times entry */ +    pTiEntry = pTEntry->head; +    while ( pTiEntry ) +    { +        if ( Ses_StoreTimesEqual( pArrTimeProfile, pTiEntry->pArrTimeProfile, nVars ) ) +            break; +        else +            pTiEntry = pTiEntry->next; +    } + +    for ( i = 0; i < nVars; ++i ) +        pArrTimeProfile[i] += nDelta; + +    /* no entry found? */ +    if ( !pTiEntry ) +        return 0; + +    return pTiEntry->pNetwork; +} + +static void Ses_StoreWrite( Ses_Store_t * pStore, const char * pFilename ) +{ +    int i; +    Ses_TruthEntry_t * pTEntry; +    Ses_TimesEntry_t * pTiEntry; +    FILE * pFile; + +    pFile = fopen( pFilename, "wb" ); +    if (pFile == NULL) +    { +        printf( "cannot open file \"%s\" for writing\n", pFilename ); +        return; +    } + +    fwrite( &pStore->nEntriesCount, sizeof( int ), 1, pFile ); + +    for ( i = 0; i < SES_STORE_TABLE_SIZE; ++i ) +        if ( pStore->pEntries[i] ) +        { +            pTEntry = pStore->pEntries[i]; + +            while ( pTEntry ) +            { +                pTiEntry = pTEntry->head; +                while ( pTiEntry ) +                { +                    fwrite( pTEntry->pTruth, sizeof( word ), 4, pFile ); +                    fwrite( &pTEntry->nVars, sizeof( int ), 1, pFile ); +                    fwrite( pTiEntry->pArrTimeProfile, sizeof( int ), 8, pFile ); +                    fwrite( pTiEntry->pNetwork, sizeof( char ), 3 + 4 * pTiEntry->pNetwork[ABC_EXACT_SOL_NGATES] + 2 + pTiEntry->pNetwork[ABC_EXACT_SOL_NVARS], pFile ); +                    pTiEntry = pTiEntry->next; +                } +                pTEntry = pTEntry->next; +            } +        } + + +    fclose( pFile ); +} + +static void Ses_StoreRead( Ses_Store_t * pStore, const char * pFilename ) +{ +    int i, nEntries; +    word pTruth[4]; +    int nVars; +    int pArrTimeProfile[8]; +    char pHeader[3]; +    char * pNetwork; +    FILE * pFile; +    int value; + +    pFile = fopen( pFilename, "rb" ); +    if (pFile == NULL) +    { +        printf( "cannot open file \"%s\" for reading\n", pFilename ); +        return; +    } + +    value = fread( &nEntries, sizeof( int ), 1, pFile ); + +    for ( i = 0; i < nEntries; ++i ) +    { +        value = fread( pTruth, sizeof( word ), 4, pFile ); +        value = fread( &nVars, sizeof( int ), 1, pFile ); +        value = fread( pArrTimeProfile, sizeof( int ), 8, pFile ); +        value = fread( pHeader, sizeof( char ), 3, pFile ); + +        pNetwork = ABC_CALLOC( char, 3 + 4 * pHeader[ABC_EXACT_SOL_NGATES] + 2 + pHeader[ABC_EXACT_SOL_NVARS] ); +        pNetwork[0] = pHeader[0]; +        pNetwork[1] = pHeader[1]; +        pNetwork[2] = pHeader[2]; + +        value = fread( pNetwork + 3, sizeof( char ), 4 * pHeader[ABC_EXACT_SOL_NGATES] + 2 + pHeader[ABC_EXACT_SOL_NVARS], pFile ); + +        Ses_StoreAddEntry( pStore, pTruth, nVars, pArrTimeProfile, pNetwork ); +    } + +    fclose( pFile ); +} + +static inline Ses_Man_t * Ses_ManAlloc( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrTimeProfile, int fMakeAIG, int fVerbose ) +{ +    int h, i; + +    Ses_Man_t * p = ABC_CALLOC( Ses_Man_t, 1 ); +    p->pSat       = NULL; +    p->bSpecInv   = 0; +    for ( h = 0; h < nFunc; ++h ) +        if ( pTruth[h << 2] & 1 ) +        { +            for ( i = 0; i < 4; ++i ) +                pTruth[(h << 2) + i] = ~pTruth[(h << 2) + i]; +            p->bSpecInv |= ( 1 << h ); +        } +    p->pSpec         = pTruth; +    p->nSpecVars     = nVars; +    p->nSpecFunc     = nFunc; +    p->nRows         = ( 1 << nVars ) - 1; +    p->nMaxDepth     = nMaxDepth; +    p->pArrTimeProfile = nMaxDepth >= 0 ? pArrTimeProfile : NULL; +    if ( p->pArrTimeProfile ) +        p->nArrTimeDelta = Abc_NormalizeArrivalTimes( p->pArrTimeProfile, nVars, &p->nArrTimeMax ); +    else +        p->nArrTimeDelta = p->nArrTimeMax = 0; +    p->fMakeAIG      = fMakeAIG; +    p->nBTLimit      = nMaxDepth >= 0 ? 50000 : 0; +    p->fVerbose      = fVerbose; +    p->fVeryVerbose  = 0; + +    return p; +} + +static inline void Ses_ManClean( Ses_Man_t * pSes ) +{ +    int h, i; +    for ( h = 0; h < pSes->nSpecFunc; ++h ) +        if ( ( pSes->bSpecInv >> h ) & 1 ) +            for ( i = 0; i < 4; ++i ) +                pSes->pSpec[(h << 2) + i] = ~( pSes->pSpec[(h << 2) + i] ); + +    if ( pSes->pArrTimeProfile ) +        for ( i = 0; i < pSes->nSpecVars; ++i ) +            pSes->pArrTimeProfile[i] += pSes->nArrTimeDelta; + +    if ( pSes->pSat ) +        sat_solver_delete( pSes->pSat ); + +    ABC_FREE( pSes ); +} + +/**Function************************************************************* + +  Synopsis    [Access variables based on indexes.] + +***********************************************************************/ +static inline int Ses_ManSimVar( Ses_Man_t * pSes, int i, int t ) +{ +    assert( i < pSes->nGates ); +    assert( t < pSes->nRows ); + +    return pSes->nRows * i + t; +} + +static inline int Ses_ManOutputVar( Ses_Man_t * pSes, int h, int i ) +{ +    assert( h < pSes->nSpecFunc ); +    assert( i < pSes->nGates ); + +    return pSes->nOutputOffset + pSes->nGates * h + i; +} + +static inline int Ses_ManGateVar( Ses_Man_t * pSes, int i, int p, int q ) +{ +    assert( i < pSes->nGates ); +    assert( p < 2 ); +    assert( q < 2 ); +    assert( p > 0 || q > 0 ); + +    return pSes->nGateOffset + i * 3 + ( p << 1 ) + q - 1; +} + +static inline int Ses_ManSelectVar( Ses_Man_t * pSes, int i, int j, int k ) +{ +    int a; +    int offset; + +    assert( i < pSes->nGates ); +    assert( k < pSes->nSpecVars + i ); +    assert( j < k ); + +    offset = pSes->nSelectOffset; +    for ( a = pSes->nSpecVars; a < pSes->nSpecVars + i; ++a ) +        offset += a * ( a - 1 ) / 2; + +    return offset + ( -j * ( 1 + j - 2 * ( pSes->nSpecVars + i ) ) ) / 2 + ( k - j - 1 ); +} + +static inline int Ses_ManDepthVar( Ses_Man_t * pSes, int i, int j ) +{ +    assert( i < pSes->nGates ); +    assert( j <= pSes->nArrTimeMax + i ); + +    return pSes->nDepthOffset + i * pSes->nArrTimeMax + ( ( i * ( i + 1 ) ) / 2 ) + j; +} + +/**Function************************************************************* + +  Synopsis    [Setup variables to find network with nGates gates.] + +***********************************************************************/ +static void Ses_ManCreateVars( Ses_Man_t * pSes, int nGates ) +{ +    int i; + +    if ( pSes->fVerbose ) +    { +        printf( "create variables for network with %d functions over %d variables and %d gates\n", pSes->nSpecFunc, pSes->nSpecVars, nGates ); +    } + +    pSes->nGates      = nGates; +    pSes->nSimVars    = nGates * pSes->nRows; +    pSes->nOutputVars = pSes->nSpecFunc * nGates; +    pSes->nGateVars   = nGates * 3; +    pSes->nSelectVars = 0; +    for ( i = pSes->nSpecVars; i < pSes->nSpecVars + nGates; ++i ) +        pSes->nSelectVars += ( i * ( i - 1 ) ) / 2; +    pSes->nDepthVars = pSes->nMaxDepth > 0 ? nGates * pSes->nArrTimeMax + ( nGates * ( nGates + 1 ) ) / 2 : 0; + +    pSes->nOutputOffset = pSes->nSimVars; +    pSes->nGateOffset   = pSes->nSimVars + pSes->nOutputVars; +    pSes->nSelectOffset = pSes->nSimVars + pSes->nOutputVars + pSes->nGateVars; +    pSes->nDepthOffset  = pSes->nSimVars + pSes->nOutputVars + pSes->nGateVars + pSes->nSelectVars; + +    if ( pSes->pSat ) +        sat_solver_delete( pSes->pSat ); +    pSes->pSat = sat_solver_new(); +    sat_solver_setnvars( pSes->pSat, pSes->nSimVars + pSes->nOutputVars + pSes->nGateVars + pSes->nSelectVars + pSes->nDepthVars ); +} + +/**Function************************************************************* + +  Synopsis    [Create clauses.] + +***********************************************************************/ +static inline void Ses_ManCreateMainClause( Ses_Man_t * pSes, int t, int i, int j, int k, int a, int b, int c ) +{ +    int pLits[5], ctr = 0, value; + +    pLits[ctr++] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 1 ); +    pLits[ctr++] = Abc_Var2Lit( Ses_ManSimVar( pSes, i, t ), a ); + +    if ( j < pSes->nSpecVars ) +    { +        if ( Abc_TtGetBit( s_Truths8 + ( j << 2 ), t + 1 ) != b ) /* 1 in clause, we can omit the clause */ +            return; +    } +    else +        pLits[ctr++] = Abc_Var2Lit( Ses_ManSimVar( pSes, j - pSes->nSpecVars, t ), b ); + +    if ( k < pSes->nSpecVars ) +    { +        if ( Abc_TtGetBit( s_Truths8 + ( k << 2 ), t + 1 ) != c ) /* 1 in clause, we can omit the clause */ +            return; +    } +    else +        pLits[ctr++] = Abc_Var2Lit( Ses_ManSimVar( pSes, k - pSes->nSpecVars, t ), c ); + +    if ( b > 0 || c > 0 ) +        pLits[ctr++] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, b, c ), 1 - a ); + +    value = sat_solver_addclause( pSes->pSat, pLits, pLits + ctr ); +    assert( value ); +} + +static int Ses_ManCreateClauses( Ses_Man_t * pSes ) +{ +    extern int Extra_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 ); + +    int h, i, j, k, t, ii, jj, kk, p, q, d; +    int pLits[3]; +    Vec_Int_t * vLits; + +    for ( t = 0; t < pSes->nRows; ++t ) +        for ( i = 0; i < pSes->nGates; ++i ) +        { +            /* main clauses */ +            for ( j = 0; j < pSes->nSpecVars + i; ++j ) +                for ( k = j + 1; k < pSes->nSpecVars + i; ++k ) +                { +                    Ses_ManCreateMainClause( pSes, t, i, j, k, 0, 0, 1 ); +                    Ses_ManCreateMainClause( pSes, t, i, j, k, 0, 1, 0 ); +                    Ses_ManCreateMainClause( pSes, t, i, j, k, 0, 1, 1 ); +                    Ses_ManCreateMainClause( pSes, t, i, j, k, 1, 0, 0 ); +                    Ses_ManCreateMainClause( pSes, t, i, j, k, 1, 0, 1 ); +                    Ses_ManCreateMainClause( pSes, t, i, j, k, 1, 1, 0 ); +                    Ses_ManCreateMainClause( pSes, t, i, j, k, 1, 1, 1 ); +                } + +            /* output clauses */ +            for ( h = 0; h < pSes->nSpecFunc; ++h ) +            { +                pLits[0] = Abc_Var2Lit( Ses_ManOutputVar( pSes, h, i ), 1 ); +                pLits[1] = Abc_Var2Lit( Ses_ManSimVar( pSes, i, t ), 1 - Abc_TtGetBit( &pSes->pSpec[h << 2], t + 1 ) ); +                assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 2 ) ); +            } +        } + +    /* some output is selected */ +    for ( h = 0; h < pSes->nSpecFunc; ++h ) +    { +        vLits = Vec_IntAlloc( pSes->nGates ); +        for ( i = 0; i < pSes->nGates; ++i ) +            Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManOutputVar( pSes, h, i ), 0 ) ); +        assert( sat_solver_addclause( pSes->pSat, Vec_IntArray( vLits ), Vec_IntLimit( vLits ) ) ); +        Vec_IntFree( vLits ); +    } + +    /* each gate has two operands */ +    for ( i = 0; i < pSes->nGates; ++i ) +    { +        vLits = Vec_IntAlloc( ( ( pSes->nSpecVars + i ) * ( pSes->nSpecVars + i - 1 ) ) / 2 ); +        for ( j = 0; j < pSes->nSpecVars + i; ++j ) +            for ( k = j + 1; k < pSes->nSpecVars + i; ++k ) +                Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 0 ) ); +        assert( sat_solver_addclause( pSes->pSat, Vec_IntArray( vLits ), Vec_IntLimit( vLits ) ) ); +        Vec_IntFree( vLits ); +    } + +    /* only AIG */ +    if ( pSes->fMakeAIG ) +    { +        for ( i = 0; i < pSes->nGates; ++i ) +        { +            /* not 2 ones */ +            pLits[0] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 0, 1 ), 1 ); +            pLits[1] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 0 ), 1 ); +            pLits[2] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 1 ), 0 ); +            assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ) ); + +            pLits[0] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 0, 1 ), 1 ); +            pLits[1] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 0 ), 0 ); +            pLits[2] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 1 ), 1 ); +            assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ) ); + +            pLits[0] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 0, 1 ), 0 ); +            pLits[1] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 0 ), 1 ); +            pLits[2] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 1 ), 1 ); +            assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ) ); +        } +    } + +    /* EXTRA clauses: use gate i at least once */ +    for ( i = 0; i < pSes->nGates; ++i ) +    { +        vLits = Vec_IntAlloc( 0 ); +        for ( h = 0; h < pSes->nSpecFunc; ++h ) +            Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManOutputVar( pSes, h, i ), 0 ) ); +        for ( ii = i + 1; ii < pSes->nGates; ++ii ) +        { +            for ( j = 0; j < pSes->nSpecVars + i; ++j ) +                Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManSelectVar( pSes, ii, j, pSes->nSpecVars + i ), 0 ) ); +            for ( j = pSes->nSpecVars + i + 1; j < pSes->nSpecVars + ii; ++j ) +                Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManSelectVar( pSes, ii, pSes->nSpecVars + i, j ), 0 ) ); +        } +        assert( sat_solver_addclause( pSes->pSat, Vec_IntArray( vLits ), Vec_IntLimit( vLits ) ) ); +        Vec_IntFree( vLits ); +    } + +    /* EXTRA clauses: co-lexicographic order */ +    for ( i = 0; i < pSes->nGates - 1; ++i ) +    { +        for ( k = 2; k < pSes->nSpecVars + i; ++k ) +        { +            for ( j = 1; j < k; ++j ) +                for ( jj = 0; jj < j; ++jj ) +                { +                    pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 1 ); +                    pLits[1] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i + 1, jj, k ), 1 ); +                } + +            for ( j = 0; j < k; ++j ) +                for ( kk = 1; kk < k; ++kk ) +                    for ( jj = 0; jj < kk; ++jj ) +                    { +                        pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 1 ); +                        pLits[1] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i + 1, jj, kk ), 1 ); +                    } +        } +    } + +    /* EXTRA clauses: symmetric variables */ +    if ( pSes->nSpecFunc == 1 ) /* only check if there is one output function */ +        for ( q = 1; q < pSes->nSpecVars; ++q ) +            for ( p = 0; p < q; ++p ) +                if ( Extra_TruthVarsSymm( (unsigned*)( &pSes->pSpec[h << 2] ), pSes->nSpecVars, p, q ) ) +                { +                    if ( pSes->fVeryVerbose ) +                        printf( "variables %d and %d are symmetric\n", p, q ); +                    for ( i = 0; i < pSes->nGates; ++i ) +                        for ( j = 0; j < q; ++j ) +                        { +                            if ( j == p ) continue; + +                            vLits = Vec_IntAlloc( 0 ); +                            Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, q ), 1 ) ); +                            for ( ii = 0; ii < i; ++ii ) +                                for ( kk = 1; kk < pSes->nSpecVars + ii; ++kk ) +                                    for ( jj = 0; jj < kk; ++jj ) +                                        if ( jj == p || kk == p ) +                                            Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManSelectVar( pSes, ii, jj, kk ), 0 ) ); +                            assert( sat_solver_addclause( pSes->pSat, Vec_IntArray( vLits ), Vec_IntLimit( vLits ) ) ); +                            Vec_IntFree( vLits ); +                        } +                } + +    /* DEPTH clauses */ +    if ( pSes->nMaxDepth > 0 ) +    { +        for ( i = 0; i < pSes->nGates; ++i ) +        { +            /* propagate depths from children */ +            for ( k = 1; k < i; ++k ) +                for ( j = 0; j < k; ++j ) +                { +                    pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, pSes->nSpecVars + j, pSes->nSpecVars + k ), 1 ); +                    for ( jj = 0; jj <= pSes->nArrTimeMax + j; ++jj ) +                    { +                        pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, j, jj ), 1 ); +                        pLits[2] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, jj + 1 ), 0 ); +                        assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ) ); +                    } +                } + +            for ( k = 0; k < i; ++k ) +                for ( j = 0; j < pSes->nSpecVars + k; ++j ) +                { +                    pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, pSes->nSpecVars + k ), 1 ); +                    for ( kk = 0; kk <= pSes->nArrTimeMax + k; ++kk ) +                    { +                        pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, k, kk ), 1 ); +                        pLits[2] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, kk + 1 ), 0 ); +                        assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ) ); +                    } +                } + +            /* propagate depths from arrival times at PIs */ +            if ( pSes->pArrTimeProfile ) +            { +                for ( k = 1; k < pSes->nSpecVars + i; ++k ) +                    for ( j = 0; j < ( ( k < pSes->nSpecVars ) ? k : pSes->nSpecVars ); ++j ) +                    { +                        d = pSes->pArrTimeProfile[j]; +                        if ( k < pSes->nSpecVars && pSes->pArrTimeProfile[k] > d ) +                            d = pSes->pArrTimeProfile[k]; + +                        pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 1 ); +                        pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, d + 1 ), 0 ); +                        assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 2 ) ); +                    } +            } +            else +            { +                /* arrival times are 0 */ +                pLits[0] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, 0 ), 0 ); +                assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 1 ) ); +            } + +            /* reverse order encoding of depth variables */ +            for ( j = 1; j <= pSes->nArrTimeMax + i; ++j ) +            { +                pLits[0] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, j ), 1 ); +                pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, j - 1 ), 0 ); +                assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 2 ) ); +            } + +            /* constrain maximum depth */ +            if ( pSes->nMaxDepth < pSes->nArrTimeMax + i ) +                for ( h = 0; h < pSes->nSpecFunc; ++h ) +                { +                    pLits[0] = Abc_Var2Lit( Ses_ManOutputVar( pSes, h, i ), 1 ); +                    pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, pSes->nMaxDepth ), 1 ); +                    if ( !sat_solver_addclause( pSes->pSat, pLits, pLits + 2 ) ) +                        return 0; +                } +        } +    } + +    return 1; +} + +/**Function************************************************************* + +  Synopsis    [Solve.] + +***********************************************************************/ +static inline int Ses_ManSolve( Ses_Man_t * pSes ) +{ +    int status; +    abctime timeStart, timeDelta; + +    if ( pSes->fVeryVerbose ) +    { +        printf( "solve SAT instance with %d clauses and %d variables\n", sat_solver_nclauses( pSes->pSat ), sat_solver_nvars( pSes->pSat ) ); +    } + +    timeStart = Abc_Clock(); +    status = sat_solver_solve( pSes->pSat, NULL, NULL, pSes->nBTLimit, 0, 0, 0 ); +    timeDelta = Abc_Clock() - timeStart; + +    pSes->timeSat += timeDelta; + +    if ( status == l_True ) +    { +        pSes->timeSatSat += timeDelta; +        return 1; +    } +    else if ( status == l_False ) +    { +        pSes->timeSatUnsat += timeDelta; +        return 0; +    } +    else +    { +        if ( pSes->fVerbose ) +        { +            printf( "resource limit reached\n" ); +        } +        return 2; +    } +} + +/**Function************************************************************* + +  Synopsis    [Extract solution.] + +***********************************************************************/ +// char is an array of short integers that stores the synthesized network +// using the following format +// | nvars | nfunc | ngates | gate[1] | ... | gate[ngates] | func[1] | .. | func[nfunc] | +// nvars:       integer with number of variables +// nfunc:       integer with number of functions +// ngates:      integer with number of gates +// gate[i]:     | op | nfanin | fanin[1] | ... | fanin[nfanin] | +//   op:        integer of gate's truth table (divided by 2, because gate is normal) +//   nfanin[i]: integer with number of fanins +//   fanin:     integer to primary input or other gate +// func[i]:     | fanin | delay | pin[1] | ... | pin[nvars] | +//   fanin:     integer as literal to some gate (not primary input), can be complemented +//   delay:     maximum delay to output (taking arrival times into account, not normalized) or 0 if not specified +//   pin[i]:    pin to pin delay to input i or 0 if not specified or if there is no connection to input i +// NOTE: since outputs can only point to gates, delay and pin-to-pin times cannot be 0 +static char * Ses_ManExtractSolution( Ses_Man_t * pSes ) +{ +    int nSol, h, i, j, k, l, aj, ak, d, nOp; +    char * pSol, * p; +    int * pPerm = NULL; /* will be a 2d array [i][l] where is is gate id and l is PI id */ + +    /* compute length of solution, for now all gates have 2 inputs */ +    nSol = 3 + pSes->nGates * 4 + pSes->nSpecFunc * ( 2 + pSes->nSpecVars ); + +    p = pSol = ABC_CALLOC( char, nSol ); + +    /* header */ +    *p++ = pSes->nSpecVars; +    *p++ = pSes->nSpecFunc; +    *p++ = pSes->nGates; + +    /* gates */ +    for ( i = 0; i < pSes->nGates; ++i ) +    { +        nOp  = sat_solver_var_value( pSes->pSat, Ses_ManGateVar( pSes, i, 0, 1 ) ); +        nOp |= sat_solver_var_value( pSes->pSat, Ses_ManGateVar( pSes, i, 1, 0 ) ) << 1; +        nOp |= sat_solver_var_value( pSes->pSat, Ses_ManGateVar( pSes, i, 1, 1 ) ) << 2; + +        *p++ = nOp; +        *p++ = 2; + +        if ( pSes->fVeryVerbose ) +            printf( "add gate %d with operation %d", pSes->nSpecVars + i, nOp ); + +        for ( k = 0; k < pSes->nSpecVars + i; ++k ) +            for ( j = 0; j < k; ++j ) +                if ( sat_solver_var_value( pSes->pSat, Ses_ManSelectVar( pSes, i, j, k ) ) ) +                { +                    if ( pSes->fVeryVerbose ) +                        printf( " and operands %d and %d", j, k ); +                    *p++ = j; +                    *p++ = k; +                    break; +                } + +        if ( pSes->fVeryVerbose ) +        { +            if ( pSes->nMaxDepth > 0 ) +            { +                printf( " and depth vector " ); +                for ( j = 0; j <= pSes->nArrTimeMax + i; ++j ) +                    printf( "%d", sat_solver_var_value( pSes->pSat, Ses_ManDepthVar( pSes, i, j ) ) ); +            } +            printf( "\n" ); +        } +    } + +    /* pin-to-pin delay */ +    if ( pSes->nMaxDepth != -1 ) +    { +        pPerm = ABC_CALLOC( int, pSes->nGates * pSes->nSpecVars ); +        for ( i = 0; i < pSes->nGates; ++i ) +        { +            /* since all gates are binary for now */ +            j = pSol[3 + i * 4 + 2]; +            k = pSol[3 + i * 4 + 3]; + +            for ( l = 0; l < pSes->nSpecVars; ++l ) +            { +                /* pin-to-pin delay to input l of child nodes */ +                aj = j < pSes->nSpecVars ? 0 : pPerm[(j - pSes->nSpecVars) * pSes->nSpecVars + l]; +                ak = k < pSes->nSpecVars ? 0 : pPerm[(k - pSes->nSpecVars) * pSes->nSpecVars + l]; + +                if ( aj == 0 && ak == 0 ) +                    pPerm[i * pSes->nSpecVars + l] = ( l == j || l == k ) ? 1 : 0; +                else +                    pPerm[i * pSes->nSpecVars + l] = Abc_MaxInt( aj, ak ) + 1; +            } +        } +    } + +    /* outputs */ +    for ( h = 0; h < pSes->nSpecFunc; ++h ) +        for ( i = 0; i < pSes->nGates; ++i ) +            if ( sat_solver_var_value( pSes->pSat, Ses_ManOutputVar( pSes, h, i ) ) ) +            { +                *p++ = Abc_Var2Lit( i, ( pSes->bSpecInv >> h ) & 1 ); +                d = 0; +                if ( pSes->nMaxDepth != -1 ) +                    while ( d < pSes->nArrTimeMax + i && sat_solver_var_value( pSes->pSat, Ses_ManDepthVar( pSes, i, d ) ) ) +                        ++d; +                *p++ = d + pSes->nArrTimeDelta; +                if ( pSes->fVeryVerbose ) +                    printf( "output %d points to %d and has normalized delay %d\n", h, i, d ); +                for ( l = 0; l < pSes->nSpecVars; ++l ) +                { +                    d = ( pSes->nMaxDepth != -1 ) ? pPerm[i * pSes->nSpecVars + l] : 0; +                    if ( pSes->fVeryVerbose ) +                        printf( "  pin-to-pin arrival time from input %d is %d\n", l, d ); +                    *p++ = d; +                } +            } + +    /* pin-to-pin delays */ +    if ( pSes->nMaxDepth != -1 ) +        ABC_FREE( pPerm ); + +    /* have we used all the fields? */ +    assert( ( p - pSol ) == nSol ); + +    return pSol; +} + +static Abc_Ntk_t * Ses_ManExtractNtk( char const * pSol ) +{ +    int h, i; +    char const * p; +    Abc_Ntk_t * pNtk; +    Abc_Obj_t * pObj; +    Vec_Ptr_t * pGates, * vNames; +    char pGateTruth[5]; +    char * pSopCover; + +    pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); +    pNtk->pName = Extra_UtilStrsav( "exact" ); +    pGates = Vec_PtrAlloc( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NGATES] ); +    pGateTruth[3] = '0'; +    pGateTruth[4] = '\0'; +    vNames = Abc_NodeGetFakeNames( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NFUNC] ); + +    /* primary inputs */ +    Vec_PtrPush( pNtk->vObjs, NULL ); +    for ( i = 0; i < pSol[ABC_EXACT_SOL_NVARS]; ++i ) +    { +        pObj = Abc_NtkCreatePi( pNtk ); +        Abc_ObjAssignName( pObj, (char*)Vec_PtrEntry( vNames, i ), NULL ); +        Vec_PtrPush( pGates, pObj ); +    } + +    /* gates */ +    p = pSol + 3; +    for ( i = 0; i < pSol[ABC_EXACT_SOL_NGATES]; ++i ) +    { +        pGateTruth[2] = '0' + ( *p & 1 ); +        pGateTruth[1] = '0' + ( ( *p >> 1 ) & 1 ); +        pGateTruth[0] = '0' + ( ( *p >> 2 ) & 1 ); +        ++p; + +        assert( *p == 2 ); /* binary gate */ +        ++p; + +        pSopCover = Abc_SopFromTruthBin( pGateTruth ); +        pObj = Abc_NtkCreateNode( pNtk ); +        pObj->pData = Abc_SopRegister( (Mem_Flex_t*)pNtk->pManFunc, pSopCover ); +        Vec_PtrPush( pGates, pObj ); +        ABC_FREE( pSopCover ); + +        Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, *p++ ) ); +        Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, *p++ ) ); +    } + +    /* outputs */ +    for ( h = 0; h < pSol[ABC_EXACT_SOL_NFUNC]; ++h ) +    { +        pObj = Abc_NtkCreatePo( pNtk ); +        Abc_ObjAssignName( pObj, (char*)Vec_PtrEntry( vNames, pSol[ABC_EXACT_SOL_NVARS] + h ), NULL ); +        if ( Abc_LitIsCompl( *p ) ) +            Abc_ObjAddFanin( pObj, Abc_NtkCreateNodeInv( pNtk, (Abc_Obj_t *)Vec_PtrEntry( pGates, pSol[ABC_EXACT_SOL_NVARS] + Abc_Lit2Var( *p ) ) ) ); +        else +            Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, pSol[ABC_EXACT_SOL_NVARS] + Abc_Lit2Var( *p ) ) ); +        p += ( 2 + pSol[ABC_EXACT_SOL_NVARS] ); +    } +    Abc_NodeFreeNames( vNames ); + +    Vec_PtrFree( pGates ); + +    if ( !Abc_NtkCheck( pNtk ) ) +        printf( "Ses_ManExtractSolution(): Network check has failed.\n" ); + +    return pNtk; +} + +static Gia_Man_t * Ses_ManExtractGia( char const * pSol ) +{ +    int h, i; +    char const * p; +    Gia_Man_t * pGia; +    Vec_Int_t * pGates; +    Vec_Ptr_t * vNames; +    int nObj, nChild1, nChild2, fChild1Comp, fChild2Comp; + +    pGia = Gia_ManStart( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NGATES] + pSol[ABC_EXACT_SOL_NFUNC] + 1 ); +    pGia->nConstrs = 0; +    pGia->pName = Extra_UtilStrsav( "exact" ); + +    pGates = Vec_IntAlloc( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NGATES] ); +    vNames = Abc_NodeGetFakeNames( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NFUNC] ); + +    /* primary inputs */ +    pGia->vNamesIn = Vec_PtrStart( pSol[ABC_EXACT_SOL_NVARS] ); +    for ( i = 0; i < pSol[ABC_EXACT_SOL_NVARS]; ++i ) +    { +        nObj = Gia_ManAppendCi( pGia ); +        Vec_IntPush( pGates, nObj ); +        Vec_PtrSetEntry( pGia->vNamesIn, i, Extra_UtilStrsav( Vec_PtrEntry( vNames, i ) ) ); +    } + +    /* gates */ +    p = pSol + 3; +    for ( i = 0; i < pSol[ABC_EXACT_SOL_NGATES]; ++i ) +    { +        assert( p[1] == 2 ); +        nChild1 = Vec_IntEntry( pGates, p[2] ); +        nChild2 = Vec_IntEntry( pGates, p[3] ); +        fChild1Comp = fChild2Comp = 0; + +        if ( *p & 1 ) +        { +            nChild1 = Abc_LitNot( nChild1 ); +            fChild1Comp = 1; +        } +        if ( ( *p >> 1 ) & 1 ) +        { +            nChild2 = Abc_LitNot( nChild2 ); +            fChild2Comp = 1; +        } +        nObj = Gia_ManAppendAnd( pGia, nChild1, nChild2 ); +        if ( fChild1Comp && fChild2Comp ) +        { +            assert( ( *p >> 2 ) & 1 ); +            nObj = Abc_LitNot( nObj ); +        } + +        Vec_IntPush( pGates, nObj ); + +        p += 4; +    } + +    /* outputs */ +    pGia->vNamesOut = Vec_PtrStart( pSol[ABC_EXACT_SOL_NFUNC] ); +    for ( h = 0; h < pSol[ABC_EXACT_SOL_NFUNC]; ++h ) +    { +        nObj = Vec_IntEntry( pGates, pSol[ABC_EXACT_SOL_NVARS] + Abc_Lit2Var( *p ) ); +        if ( Abc_LitIsCompl( *p ) ) +            nObj = Abc_LitNot( nObj ); +        Gia_ManAppendCo( pGia, nObj ); +        Vec_PtrSetEntry( pGia->vNamesOut, h, Extra_UtilStrsav( Vec_PtrEntry( vNames, pSol[ABC_EXACT_SOL_NVARS] + h ) ) ); +        p += ( 2 + pSol[ABC_EXACT_SOL_NVARS] ); +    } +    Abc_NodeFreeNames( vNames ); + +    Vec_IntFree( pGates ); + +    return pGia; +} + +/**Function************************************************************* + +  Synopsis    [Debug.] + +***********************************************************************/ +static void Ses_ManPrintRuntime( Ses_Man_t * pSes ) +{ +    printf( "Runtime breakdown:\n" ); +    ABC_PRTP( "Sat   ", pSes->timeSat,      pSes->timeTotal ); +    ABC_PRTP( " Sat  ", pSes->timeSatSat,   pSes->timeTotal ); +    ABC_PRTP( " Unsat", pSes->timeSatUnsat, pSes->timeTotal ); +    ABC_PRTP( "ALL   ", pSes->timeTotal,    pSes->timeTotal ); +} + +static inline void Ses_ManPrintFuncs( Ses_Man_t * pSes ) +{ +    int h; + +    printf( "find optimum circuit for %d %d-variable functions:\n", pSes->nSpecFunc, pSes->nSpecVars ); +    for ( h = 0; h < pSes->nSpecFunc; ++h ) +    { +        printf( "  func %d: ", h + 1 ); +        Abc_TtPrintHexRev( stdout, &pSes->pSpec[h >> 2], pSes->nSpecVars ); +        printf( "\n" ); +    } +} + +static inline void Ses_ManPrintVars( Ses_Man_t * pSes ) +{ +    int h, i, j, k, p, q, t; + +    for ( i = 0; i < pSes->nGates; ++i ) +        for ( t = 0; t < pSes->nRows; ++t ) +            printf( "x(%d, %d) : %d\n", i, t, Ses_ManSimVar( pSes, i, t ) ); + +    for ( h = 0; h < pSes->nSpecFunc; ++h ) +        for ( i = 0; i < pSes->nGates; ++i ) +            printf( "h(%d, %d) : %d\n", h, i, Ses_ManOutputVar( pSes, h, i ) ); + +    for ( i = 0; i < pSes->nGates; ++i ) +        for ( p = 0; p <= 1; ++p ) +            for ( q = 0; q <= 1; ++ q) +            { +                if ( p == 0 && q == 0 ) { continue; } +                printf( "f(%d, %d, %d) : %d\n", i, p, q, Ses_ManGateVar( pSes, i, p, q ) ); +            } + +    for ( i = 0; i < pSes->nGates; ++i ) +        for ( j = 0; j < pSes->nSpecVars + i; ++j ) +            for ( k = j + 1; k < pSes->nSpecVars + i; ++k ) +                printf( "s(%d, %d, %d) : %d\n", i, j, k, Ses_ManSelectVar( pSes, i, j, k ) ); + +    if ( pSes->nMaxDepth > 0 ) +        for ( i = 0; i < pSes->nGates; ++i ) +            for ( j = 0; j <= i; ++j ) +                printf( "d(%d, %d) : %d\n", i, j, Ses_ManDepthVar( pSes, i, j ) ); + +} + +/**Function************************************************************* + +  Synopsis    [Synthesis algorithm.] + +***********************************************************************/ +static int Ses_ManFindMinimumSize( Ses_Man_t * pSes ) +{ +    int nGates = 0; + +    while ( true ) +    { +        ++nGates; + +        /* give up if number of gates is impossible for given depth */ +        if ( pSes->nMaxDepth != -1 && nGates >= ( 1 << pSes->nMaxDepth ) ) +            return 0; + +        Ses_ManCreateVars( pSes, nGates ); +        if ( !Ses_ManCreateClauses( pSes ) ) +            return 0; /* proven UNSAT while creating clauses */ + +        switch ( Ses_ManSolve( pSes ) ) +        { +        case 1: return 1; /* SAT */ +        case 2: return 0; /* resource limit */ +        } +    } + +    return 0; +} + +/**Function************************************************************* + +  Synopsis    [Find minimum size networks with a SAT solver.] + +  Description [If nMaxDepth is -1, then depth constraints are ignored. +               If nMaxDepth is not -1, one can set pArrTimeProfile which should have the length of nVars. +               One can ignore pArrTimeProfile by setting it to NULL.] + +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFindExact( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrTimeProfile, int fVerbose ) +{ +    Ses_Man_t * pSes; +    char * pSol; +    Abc_Ntk_t * pNtk = NULL; +    abctime timeStart; + +    /* some checks */ +    assert( nVars >= 2 && nVars <= 8 ); + +    timeStart = Abc_Clock(); + +    pSes = Ses_ManAlloc( pTruth, nVars, nFunc, nMaxDepth, pArrTimeProfile, 0, fVerbose ); +    if ( fVerbose ) +        Ses_ManPrintFuncs( pSes ); + +    if ( Ses_ManFindMinimumSize( pSes ) ) +    { +        pSol = Ses_ManExtractSolution( pSes ); +        pNtk = Ses_ManExtractNtk( pSol ); +        ABC_FREE( pSol ); +    } + +    pSes->timeTotal = Abc_Clock() - timeStart; + +    if ( fVerbose ) +        Ses_ManPrintRuntime( pSes ); + +    /* cleanup */ +    Ses_ManClean( pSes ); + +    return pNtk; +} + +Gia_Man_t * Gia_ManFindExact( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrTimeProfile, int fVerbose ) +{ +    Ses_Man_t * pSes; +    char * pSol; +    Gia_Man_t * pGia = NULL; +    abctime timeStart; + +    /* some checks */ +    assert( nVars >= 2 && nVars <= 8 ); + +    timeStart = Abc_Clock(); + +    pSes = Ses_ManAlloc( pTruth, nVars, nFunc, nMaxDepth, pArrTimeProfile, 1, fVerbose ); +    if ( fVerbose ) +        Ses_ManPrintFuncs( pSes ); + +    if ( Ses_ManFindMinimumSize( pSes ) ) +    { +        pSol = Ses_ManExtractSolution( pSes ); +        pGia = Ses_ManExtractGia( pSol ); +        ABC_FREE( pSol ); +    } + +    pSes->timeTotal = Abc_Clock() - timeStart; + +    if ( fVerbose ) +        Ses_ManPrintRuntime( pSes ); + +    /* cleanup */ +    Ses_ManClean( pSes ); + +    return pGia; +} + +/**Function************************************************************* + +  Synopsis    [Some test cases.] + +***********************************************************************/ + +Abc_Ntk_t * Abc_NtkFromTruthTable( word * pTruth, int nVars ) +{ +    Abc_Ntk_t * pNtk; +    Mem_Flex_t * pMan; +    char * pSopCover; + +    pMan = Mem_FlexStart(); +    pSopCover = Abc_SopCreateFromTruth( pMan, nVars, (unsigned*)pTruth ); +    pNtk = Abc_NtkCreateWithNode( pSopCover ); +    Abc_NtkShortNames( pNtk ); +    Mem_FlexStop( pMan, 0 ); + +    return pNtk; +} + +void Abc_ExactTestSingleOutput( int fVerbose ) +{ +    extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit ); + +    word pTruth[4] = {0xcafe, 0, 0, 0}; +    Abc_Ntk_t * pNtk, * pNtk2, * pNtk3, * pNtk4; +    int pArrTimeProfile[4] = {6, 2, 8, 5}; + +    pNtk = Abc_NtkFromTruthTable( pTruth, 4 ); + +    pNtk2 = Abc_NtkFindExact( pTruth, 4, 1, -1, NULL, fVerbose ); +    Abc_NtkShortNames( pNtk2 ); +    Abc_NtkCecSat( pNtk, pNtk2, 10000, 0 ); +    assert( pNtk2 ); +    assert( Abc_NtkNodeNum( pNtk2 ) == 6 ); +    Abc_NtkDelete( pNtk2 ); + +    pNtk3 = Abc_NtkFindExact( pTruth, 4, 1, 3, NULL, fVerbose ); +    Abc_NtkShortNames( pNtk3 ); +    Abc_NtkCecSat( pNtk, pNtk3, 10000, 0 ); +    assert( pNtk3 ); +    assert( Abc_NtkLevel( pNtk3 ) <= 3 ); +    Abc_NtkDelete( pNtk3 ); + +    pNtk4 = Abc_NtkFindExact( pTruth, 4, 1, 9, pArrTimeProfile, fVerbose ); +    Abc_NtkShortNames( pNtk4 ); +    Abc_NtkCecSat( pNtk, pNtk4, 10000, 0 ); +    assert( pNtk4 ); +    assert( Abc_NtkLevel( pNtk4 ) <= 9 ); +    Abc_NtkDelete( pNtk4 ); + +    assert( !Abc_NtkFindExact( pTruth, 4, 1, 2, NULL, fVerbose ) ); + +    assert( !Abc_NtkFindExact( pTruth, 4, 1, 8, pArrTimeProfile, fVerbose ) ); + +    Abc_NtkDelete( pNtk ); +} + +void Abc_ExactTestSingleOutputAIG( int fVerbose ) +{ +    word pTruth[4] = {0xcafe, 0, 0, 0}; +    Abc_Ntk_t * pNtk; +    Gia_Man_t * pGia, * pGia2, * pGia3, * pGia4, * pMiter; +    Cec_ParCec_t ParsCec, * pPars = &ParsCec; +    int pArrTimeProfile[4] = {6, 2, 8, 5}; + +    Cec_ManCecSetDefaultParams( pPars ); + +    pNtk = Abc_NtkFromTruthTable( pTruth, 4 ); +    Abc_NtkToAig( pNtk ); +    pGia = Abc_NtkAigToGia( pNtk, 1 ); + +    pGia2 = Gia_ManFindExact( pTruth, 4, 1, -1, NULL, fVerbose ); +    pMiter = Gia_ManMiter( pGia, pGia2, 0, 1, 0, 0, 1 ); +    assert( pMiter ); +    Cec_ManVerify( pMiter, pPars ); +    Gia_ManStop( pMiter ); + +    pGia3 = Gia_ManFindExact( pTruth, 4, 1, 3, NULL, fVerbose ); +    pMiter = Gia_ManMiter( pGia, pGia3, 0, 1, 0, 0, 1 ); +    assert( pMiter ); +    Cec_ManVerify( pMiter, pPars ); +    Gia_ManStop( pMiter ); + +    pGia4 = Gia_ManFindExact( pTruth, 4, 1, 9, pArrTimeProfile, fVerbose ); +    pMiter = Gia_ManMiter( pGia, pGia4, 0, 1, 0, 0, 1 ); +    assert( pMiter ); +    Cec_ManVerify( pMiter, pPars ); +    Gia_ManStop( pMiter ); + +    assert( !Gia_ManFindExact( pTruth, 4, 1, 2, NULL, fVerbose ) ); + +    assert( !Gia_ManFindExact( pTruth, 4, 1, 8, pArrTimeProfile, fVerbose ) ); + +    Gia_ManStop( pGia ); +    Gia_ManStop( pGia2 ); +    Gia_ManStop( pGia3 ); +    Gia_ManStop( pGia4 ); +} + +void Abc_ExactTest( int fVerbose ) +{ +    Abc_ExactTestSingleOutput( fVerbose ); +    Abc_ExactTestSingleOutputAIG( fVerbose ); + +    printf( "\n" ); +} + + +/**Function************************************************************* + +  Synopsis    [APIs for integraging with the mapper.] + +***********************************************************************/ +// may need to have a static pointer to the SAT-based synthesis engine and/or loaded library +// this procedure should return 1, if the engine/library are available, and 0 otherwise +int Abc_ExactIsRunning() +{ +    return s_pSesStore != NULL; +} +// this procedure returns the number of inputs of the library +// for example, somebody may try to map into 10-cuts while the library only contains 8-functions +int Abc_ExactInputNum() +{ +    return 8; +} +// start exact store manager +void Abc_ExactStart( int nBTLimit, int fMakeAIG, int fVerbose, const char * pFilename ) +{ +    if ( !s_pSesStore ) +    { +        s_pSesStore = Ses_StoreAlloc( nBTLimit, fMakeAIG, fVerbose ); +        if ( pFilename ) +            Ses_StoreRead( s_pSesStore, pFilename ); +    } +    else +        printf( "BMS manager already started\n" ); +} +// stop exact store manager +void Abc_ExactStop( const char * pFilename ) +{ +    if ( s_pSesStore ) +    { +        if ( pFilename ) +            Ses_StoreWrite( s_pSesStore, pFilename ); +        Ses_StoreClean( s_pSesStore ); +    } +    else +        printf( "BMS manager has not been started\n" ); +} +// show statistics about store manager +void Abc_ExactStats() +{ +    int i; + +    if ( !s_pSesStore ) +    { +        printf( "BMS manager has not been started\n" ); +        return; +    } + +    printf( "number of considered cuts :" ); +    for ( i = 2; i < 9; ++i ) +        printf( " %d = %lu  ", i, s_pSesStore->pCutCount[i] ); +    printf( " total = %lu\n", s_pSesStore->nCutCount ); +    printf( "cache hits                : %lu\n", s_pSesStore->nCacheHit ); +    printf( "number of entries         : %d\n", s_pSesStore->nEntriesCount ); +} +// this procedure takes TT and input arrival times (pArrTimeProfile) and return the smallest output arrival time; +// it also returns the pin-to-pin delays (pPerm) between each cut leaf and the cut output and the cut area cost (Cost) +// the area cost should not exceed 2048, if the cut is implementable; otherwise, it should be ABC_INFINITY +int Abc_ExactDelayCost( word * pTruth, int nVars, int * pArrTimeProfile, char * pPerm, int * Cost, int AigLevel ) +{ +    int i, l, fExists = 0; +    Ses_Man_t * pSes = NULL; +    char * pSol = NULL, * p; +    int Delay = ABC_INFINITY, nMaxDepth; +    abctime timeStart; + +    /* some checks */ +    if ( nVars < 0 || nVars > 8 ) +    { +        printf( "invalid truth table size %d\n", nVars ); +        assert( 0 ); +    } + +    if ( nVars == 0 ) +    { +        *Cost = 0; +        return 0; +    } + +    if ( nVars == 1 ) +    { +        *Cost = 0; +        pPerm[0] = (char)0; +        return pArrTimeProfile[0]; +    } + +    /* statistics */ +    s_pSesStore->nCutCount++; +    s_pSesStore->pCutCount[nVars]++; + +    pSol = Ses_StoreGetEntry( s_pSesStore, pTruth, nVars, pArrTimeProfile ); +    if ( pSol ) +    { +        s_pSesStore->nCacheHit++; +        fExists = 1; +    } +    else +    { +        nMaxDepth = pArrTimeProfile[0]; +        for ( i = 1; i < nVars; ++i ) +            nMaxDepth = Abc_MaxInt( nMaxDepth, pArrTimeProfile[i] ); +        nMaxDepth = Abc_MinInt( AigLevel, nMaxDepth + nVars + 1 ); + +        timeStart = Abc_Clock(); + +        *Cost = ABC_INFINITY; + +        pSes = Ses_ManAlloc( pTruth, nVars, 1 /* fSpecFunc */, nMaxDepth, pArrTimeProfile, s_pSesStore->fMakeAIG, s_pSesStore->fVerbose ); +        pSes->nBTLimit = s_pSesStore->nBTLimit; + +        while ( 1 ) /* there is improvement */ +        { +            if ( Ses_ManFindMinimumSize( pSes ) ) +            { +                if ( pSol ) +                    ABC_FREE( pSol ); +                pSol = Ses_ManExtractSolution( pSes ); +                pSes->nMaxDepth--; +            } +            else +                break; +        } + +        pSes->timeTotal = Abc_Clock() - timeStart; + +        /* cleanup */ +        Ses_ManClean( pSes ); +    } + +    if ( pSol ) +    { +        *Cost = pSol[ABC_EXACT_SOL_NGATES]; +        p = pSol + 3 + 4 * pSol[ABC_EXACT_SOL_NGATES] + 1; +        Delay = *p++; +        for ( l = 0; l < nVars; ++l ) +            pPerm[l] = *p++; + +        /* store solution */ +        if ( !fExists ) +            Ses_StoreAddEntry( s_pSesStore, pTruth, nVars, pArrTimeProfile, pSol ); +    } + +    return Delay; +} +// this procedure returns a new node whose output in terms of the given fanins +// has the smallest possible arrival time (in agreement with the above Abc_ExactDelayCost) +Abc_Obj_t * Abc_ExactBuildNode( word * pTruth, int nVars, int * pArrTimeProfile, Abc_Obj_t ** pFanins, Abc_Ntk_t * pNtk ) +{ +    char * pSol; +    int i, j; +    char const * p; +    Abc_Obj_t * pObj; +    Vec_Ptr_t * pGates; +    char pGateTruth[5]; +    char * pSopCover; + +    if ( nVars == 0 ) +        return (pTruth[0] & 1) ? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk); +    if ( nVars == 1 ) +        return (pTruth[0] & 1) ? Abc_NtkCreateNodeInv(pNtk, pFanins[0]) : Abc_NtkCreateNodeBuf(pNtk, pFanins[0]); + +    pSol = Ses_StoreGetEntry( s_pSesStore, pTruth, nVars, pArrTimeProfile ); +    if ( !pSol ) +        return NULL; + +    assert( pSol[ABC_EXACT_SOL_NVARS] == nVars ); +    assert( pSol[ABC_EXACT_SOL_NFUNC] == 1 ); + +    pGates = Vec_PtrAlloc( nVars + pSol[ABC_EXACT_SOL_NGATES] ); +    pGateTruth[3] = '0'; +    pGateTruth[4] = '\0'; + +    /* primary inputs */ +    for ( i = 0; i < nVars; ++i ) +    { +        Vec_PtrPush( pGates, pFanins[i] ); +    } + +    /* gates */ +    p = pSol + 3; +    for ( i = 0; i < pSol[ABC_EXACT_SOL_NGATES]; ++i ) +    { +        pGateTruth[2] = '0' + ( *p & 1 ); +        pGateTruth[1] = '0' + ( ( *p >> 1 ) & 1 ); +        pGateTruth[0] = '0' + ( ( *p >> 2 ) & 1 ); +        ++p; + +        assert( *p == 2 ); /* binary gate */ +        ++p; + +        /* invert truth table if we are last gate and inverted */ +        if ( i + 1 == pSol[ABC_EXACT_SOL_NGATES] && Abc_LitIsCompl( *( p + 2 ) ) ) +            for ( j = 0; j < 4; ++j ) +                pGateTruth[j] = ( pGateTruth[j] == '0' ) ? '1' : '0'; + +        pSopCover = Abc_SopFromTruthBin( pGateTruth ); +        pObj = Abc_NtkCreateNode( pNtk ); +        pObj->pData = Abc_SopRegister( (Mem_Flex_t*)pNtk->pManFunc, pSopCover ); +        Vec_PtrPush( pGates, pObj ); +        ABC_FREE( pSopCover ); + +        Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, *p++ ) ); +        Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, *p++ ) ); +    } + +    /* output */ +    pObj = (Abc_Obj_t *)Vec_PtrEntry( pGates, nVars + Abc_Lit2Var( *p ) ); + +    Vec_PtrFree( pGates ); + +    return pObj; +} + +void Abc_ExactStoreTest( int fVerbose ) +{ +    int i; +    word pTruth[4] = {0xcafe, 0, 0, 0}; +    int pArrTimeProfile[4] = {6, 2, 8, 5}; +    Abc_Ntk_t * pNtk; +    Abc_Obj_t * pFanins[4]; +    Vec_Ptr_t * vNames; +    char pPerm[4]; +    int Cost; + +    pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); +    pNtk->pName = Extra_UtilStrsav( "exact" ); +    vNames = Abc_NodeGetFakeNames( 4u ); + +    /* primary inputs */ +    Vec_PtrPush( pNtk->vObjs, NULL ); +    for ( i = 0; i < 4; ++i ) +    { +        pFanins[i] = Abc_NtkCreatePi( pNtk ); +        Abc_ObjAssignName( pFanins[i], (char*)Vec_PtrEntry( vNames, i ), NULL ); +    } +    Abc_NodeFreeNames( vNames ); + +    Abc_ExactStart( 10000, 1, fVerbose, NULL ); + +    assert( !Abc_ExactBuildNode( pTruth, 4, pArrTimeProfile, pFanins, pNtk ) ); + +    assert( Abc_ExactDelayCost( pTruth, 4, pArrTimeProfile, pPerm, &Cost, 12 ) == 1 ); + +    assert( Abc_ExactBuildNode( pTruth, 4, pArrTimeProfile, pFanins, pNtk ) ); + +    (*pArrTimeProfile)++; +    assert( !Abc_ExactBuildNode( pTruth, 4, pArrTimeProfile, pFanins, pNtk ) ); +    (*pArrTimeProfile)--; + +    Abc_ExactStop( NULL ); + +    Abc_NtkDelete( pNtk ); +} + +//////////////////////////////////////////////////////////////////////// +///                       END OF FILE                                /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END diff --git a/src/base/abci/abcFx.c b/src/base/abci/abcFx.c index 60f2e562..81b3e802 100644 --- a/src/base/abci/abcFx.c +++ b/src/base/abci/abcFx.c @@ -8,9 +8,9 @@    Synopsis    [Implementation of traditional "fast_extract" algorithm.] -  Author      [Alan Mishchenko] +  Author      [Alan Mishchenko, Bruno Schmitt] -  Affiliation [UC Berkeley] +  Affiliation [UC Berkeley, UFRGS]    Date        [Ver. 1.0. Started - April 26, 2013.] @@ -103,6 +103,7 @@ struct Fx_Man_t_      Vec_Int_t *     vCompls;    // complemented attribute of each cube pair      Vec_Int_t *     vCubeFree;  // cube-free divisor      Vec_Int_t *     vDiv;       // selected divisor +    Vec_Int_t *     vSCC;       // single cubes containment cubes      // statistics       abctime         timeStart;  // starting time      int             nVars;      // original problem variables @@ -312,11 +313,6 @@ int Abc_NtkFxPerform( Abc_Ntk_t * pNtk, int nNewNodesMax, int LitCountMax, int f          printf( "Abc_NtkFastExtract: Nodes have duplicated fanins. FX is not performed.\n" );          return 0;      } -    // sweep removes useless nodes -    Abc_NtkCleanup( pNtk, 0 ); -//    Abc_NtkOrderFanins( pNtk ); -    // makes sure the SOPs are SCC-free and D1C-free -    Abc_NtkMakeLegit( pNtk );      // collect information about the covers      vCubes = Abc_NtkFxRetrieve( pNtk );      // call the fast extract procedure @@ -359,6 +355,7 @@ Fx_Man_t * Fx_ManStart( Vec_Wec_t * vCubes )      p->vCompls   = Vec_IntAlloc( 100 );      p->vCubeFree = Vec_IntAlloc( 100 );      p->vDiv      = Vec_IntAlloc( 100 ); +    p->vSCC      = Vec_IntAlloc( 100 );      return p;  }  void Fx_ManStop( Fx_Man_t * p ) @@ -377,6 +374,7 @@ void Fx_ManStop( Fx_Man_t * p )      Vec_IntFree( p->vCompls );      Vec_IntFree( p->vCubeFree );      Vec_IntFree( p->vDiv ); +    Vec_IntFree( p->vSCC );      ABC_FREE( p );  } @@ -435,39 +433,16 @@ void Fx_ManComputeLevel( Fx_Man_t * p )    SeeAlso     []  ***********************************************************************/ -static inline char Fx_PrintDivLit( int Lit ) { return (Abc_LitIsCompl(Lit) ? 'A' : 'a') + Abc_Lit2Var(Lit); } -static inline void Fx_PrintDivOneReal( Vec_Int_t * vDiv ) -{ -    int i, Lit; -    Vec_IntForEachEntry( vDiv, Lit, i ) -        if ( !Abc_LitIsCompl(Lit) ) -            printf( "%c", Fx_PrintDivLit(Abc_Lit2Var(Lit)) ); -    printf( " + " ); -    Vec_IntForEachEntry( vDiv, Lit, i ) -        if ( Abc_LitIsCompl(Lit) ) -            printf( "%c", Fx_PrintDivLit(Abc_Lit2Var(Lit)) ); -} -static inline void Fx_PrintDivOne( Vec_Int_t * vDiv ) -{ -    int i, Lit; -    Vec_IntForEachEntry( vDiv, Lit, i ) -        if ( !Abc_LitIsCompl(Lit) ) -            printf( "%c", Fx_PrintDivLit( Abc_Var2Lit(i, Abc_LitIsCompl(Lit)) ) ); -    printf( " + " ); -    Vec_IntForEachEntry( vDiv, Lit, i ) -        if ( Abc_LitIsCompl(Lit) ) -            printf( "%c", Fx_PrintDivLit( Abc_Var2Lit(i, Abc_LitIsCompl(Lit)) ) ); -}  static inline void Fx_PrintDivArray( Vec_Int_t * vDiv )  {      int i, Lit;      Vec_IntForEachEntry( vDiv, Lit, i )          if ( !Abc_LitIsCompl(Lit) ) -            printf( "%d(1) ", Abc_Lit2Var(Lit) ); +            printf( "%d(1)", Abc_Lit2Var(Lit) );      printf( " + " );      Vec_IntForEachEntry( vDiv, Lit, i )          if ( Abc_LitIsCompl(Lit) ) -            printf( "%d(2) ", Abc_Lit2Var(Lit) ); +            printf( "%d(2)", Abc_Lit2Var(Lit) );  }  static inline void Fx_PrintDiv( Fx_Man_t * p, int iDiv )  { @@ -475,8 +450,7 @@ static inline void Fx_PrintDiv( Fx_Man_t * p, int iDiv )      printf( "%4d : ", p->nDivs );      printf( "Div %7d : ", iDiv );      printf( "Weight %12.5f  ", Vec_FltEntry(p->vWeights, iDiv) ); -//    printf( "Compl %4d  ", p->nCompls ); -    Fx_PrintDivOne( Hsh_VecReadEntry(p->pHash, iDiv) ); +    Fx_PrintDivArray( Hsh_VecReadEntry(p->pHash, iDiv) );      for ( i = Vec_IntSize(Hsh_VecReadEntry(p->pHash, iDiv)) + 3; i < 16; i++ )          printf( " " );      printf( "Lits =%7d  ", p->nLits ); @@ -489,45 +463,6 @@ static void Fx_PrintDivisors( Fx_Man_t * p )      for ( iDiv = 0; iDiv < Vec_FltSize(p->vWeights); iDiv++ )          Fx_PrintDiv( p, iDiv );  } -static void Fx_PrintLiterals( Fx_Man_t * p ) -{ -    Vec_Int_t * vTemp; -    int i; -    Vec_WecForEachLevel( p->vLits, vTemp, i ) -    { -        printf( "%c : ", Fx_PrintDivLit(i) ); -        Vec_IntPrint( vTemp ); -    } -} -static void Fx_PrintMatrix( Fx_Man_t * p ) -{ -    Vec_Int_t * vCube; -    int i, v, Lit, nObjs; -    char * pLine; -    if ( Vec_WecSize(p->vLits)/2 > 26 ) -        return; -    printf( "         " ); -    nObjs = Vec_WecSize(p->vLits)/2; -    for ( i = 0; i < Abc_MinInt(nObjs, 26); i++ ) -        printf( "%c", 'a' + i ); -    printf( "\n" ); -    pLine = ABC_CALLOC( char, nObjs+1 ); -    Vec_WecForEachLevel( p->vCubes, vCube, i ) -    { -        if ( Vec_IntSize(vCube) == 0 ) -            continue; -        memset( pLine, '-', nObjs ); -        Vec_IntForEachEntryStart( vCube, Lit, v, 1 ) -        { -            assert( Abc_Lit2Var(Lit) < nObjs ); -            pLine[Abc_Lit2Var(Lit)] = Abc_LitIsCompl(Lit) ? '0' : '1'; -        } -        printf( "%6d : %s %4d\n", i, pLine, Vec_IntEntry(vCube, 0) ); -    } -    ABC_FREE( pLine ); -    Fx_PrintLiterals( p ); -    Fx_PrintDivisors( p ); -}  static void Fx_PrintStats( Fx_Man_t * p, abctime clk )  {      printf( "Cubes =%8d  ", Vec_WecSizeUsed(p->vCubes) ); @@ -536,11 +471,7 @@ static void Fx_PrintStats( Fx_Man_t * p, abctime clk )      printf( "Divs+ =%8d  ", Vec_QueSize(p->vPrio) );      printf( "Compl =%8d  ", p->nDivMux[1] );      printf( "Extr  =%7d  ", p->nDivs ); -//    printf( "DivsS =%6d  ", p->nDivsS ); -//    printf( "PairS =%6d  ", p->nPairsS ); -//    printf( "PairD =%6d  ", p->nPairsD );      Abc_PrintTime( 1, "Time", clk ); -//    printf( "\n" );  }  /**Function************************************************************* @@ -638,10 +569,10 @@ static int Fx_ManDivNormalize( Vec_Int_t * vCubeFree ) // return 1 if complement  ***********************************************************************/  int Fx_ManDivFindCubeFree( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vCubeFree, int * fWarning )  { -    int * pBeg1 = vArr1->pArray + 1;  // skip variable ID -    int * pBeg2 = vArr2->pArray + 1;  // skip variable ID -    int * pEnd1 = vArr1->pArray + vArr1->nSize; -    int * pEnd2 = vArr2->pArray + vArr2->nSize; +    int * pBeg1 = Vec_IntArray( vArr1 ) + 1;  // skip variable ID +    int * pBeg2 = Vec_IntArray( vArr2 ) + 1;  // skip variable ID +    int * pEnd1 = Vec_IntLimit( vArr1 ); +    int * pEnd2 = Vec_IntLimit( vArr2 );      int Counter = 0, fAttr0 = 0, fAttr1 = 1;      Vec_IntClear( vCubeFree );      while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) @@ -664,9 +595,38 @@ int Fx_ManDivFindCubeFree( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vCu      if ( Vec_IntSize(vCubeFree) == 0 )          printf( "The SOP has duplicated cubes.\n" );      else if ( Vec_IntSize(vCubeFree) == 1 ) -        printf( "The SOP has contained cubes.\n" ); -//    else if ( Vec_IntSize(vCubeFree) == 2 && Abc_Lit2Var(Abc_Lit2Var(Vec_IntEntry(vCubeFree, 0))) == Abc_Lit2Var(Abc_Lit2Var(Vec_IntEntry(vCubeFree, 1))) && !*fWarning ) -//        printf( "The SOP has distance-1 cubes or it is not a prime cover.  Please make sure the result verifies.\n" ), *fWarning = 1; +        return -1; +    else if ( Vec_IntSize( vCubeFree ) == 3 ) +    { +        int * pArray = Vec_IntArray( vCubeFree );  + +        if ( Abc_Lit2Var( pArray[0] ) == Abc_LitNot( Abc_Lit2Var( pArray[1] ) ) ) +        { +            if ( Abc_LitIsCompl( pArray[0] ) == Abc_LitIsCompl( pArray[2] ) ) +                Vec_IntDrop( vCubeFree, 0 ); +            else +                Vec_IntDrop( vCubeFree, 1 ); +        } +        else if ( Abc_Lit2Var( pArray[1] ) == Abc_LitNot( Abc_Lit2Var( pArray[2] ) ) ) +        { +            if ( Abc_LitIsCompl( pArray[1] ) == Abc_LitIsCompl( pArray[0] ) ) +                Vec_IntDrop( vCubeFree, 1 ); +            else +                Vec_IntDrop( vCubeFree, 2 ); +        } + +        if ( Vec_IntSize( vCubeFree ) == 2 ) +        { +            int Lit0 = Abc_Lit2Var( pArray[0] ), +                Lit1 = Abc_Lit2Var( pArray[1] ); + +            if ( Lit0 > Lit1 ) +                ABC_SWAP( int, Lit0, Lit1 ); + +            Vec_IntWriteEntry( vCubeFree, 0, Abc_Var2Lit( Lit0, 0 ) ); +            Vec_IntWriteEntry( vCubeFree, 1, Abc_Var2Lit( Lit1, 1 ) ); +        } +    }      assert( !Abc_LitIsCompl(Vec_IntEntry(vCubeFree, 0)) );      return Counter;  } @@ -708,7 +668,11 @@ static inline int Fx_ManDivRemoveLits( Vec_Int_t * vCube, Vec_Int_t * vDiv, int      int i, Lit, Count = 0;      assert( !fCompl || Vec_IntSize(vDiv) == 4 );      Vec_IntForEachEntry( vDiv, Lit, i ) +    {          Count += Vec_IntRemove1( vCube, Abc_Lit2Var(Lit) ^ (fCompl && i > 1) );  // the last two lits can be complemented +        if ( Vec_IntSize( vDiv ) == 2 ) +            Count += Vec_IntRemove1( vCube, Abc_LitNot( Abc_Lit2Var(Lit) ) ); +    }      return Count;  }  static inline void Fx_ManDivAddLits( Vec_Int_t * vCube, Vec_Int_t * vCube2, Vec_Int_t * vDiv ) @@ -833,6 +797,17 @@ void Fx_ManCubeDoubleCubeDivisors( Fx_Man_t * p, int iFirst, Vec_Int_t * vPivot,          if ( Vec_IntEntry(vCube, 0) != Vec_IntEntry(vPivot, 0) )              break;          Base = Fx_ManDivFindCubeFree( vCube, vPivot, p->vCubeFree, fWarning ); +        if ( Base == -1 )  +        { +            if ( fRemove == 0 ) +            { +                if ( Vec_IntSize( vCube ) > Vec_IntSize( vPivot ) ) +                    Vec_IntPush( p->vSCC, Vec_WecLevelId( p->vCubes, vCube ) ); +                else +                    Vec_IntPush( p->vSCC, Vec_WecLevelId( p->vCubes, vPivot ) ); +            } +            continue; +        }          if ( Vec_IntSize(p->vCubeFree) == 4 )          {               int Value = Fx_ManDivNormalize( p->vCubeFree ); @@ -988,10 +963,9 @@ void Fx_ManFindCommonPairs( Vec_Wec_t * vCubes, Vec_Int_t * vPart0, Vec_Int_t *  ***********************************************************************/  void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning )  { -    Vec_Int_t * vCube, * vCube2, * vLitP, * vLitN; +    Vec_Int_t * vCube, * vCube2, * vLitP = NULL, * vLitN = NULL;      Vec_Int_t * vDiv = p->vDiv; -    int nLitsNew = p->nLits - (int)Vec_FltEntry(p->vWeights, iDiv); -    int i, k, Lit0, Lit1, iVarNew, RetValue, Level; +    int i, k, Lit0, Lit1, iVarNew = 0, RetValue, Level;      float Diff = Vec_FltEntry(p->vWeights, iDiv) - (float)((int)Vec_FltEntry(p->vWeights, iDiv));      assert( Diff > 0.0 && Diff < 1.0 ); @@ -1002,10 +976,6 @@ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning )      Fx_ManDivFindPivots( vDiv, &Lit0, &Lit1 );      assert( Lit0 >= 0 && Lit1 >= 0 ); -    // if the input cover is not prime, it may happen that we are extracting divisor (x + !x) -    // although it is not strictly correct, it seems to be fine to just skip such divisors -    if ( Abc_Lit2Var(Lit0) == Abc_Lit2Var(Lit1) && Vec_IntSize(Hsh_VecReadEntry(p->pHash, iDiv)) == 2 ) -        return;      // collect single-cube-divisor cubes      Vec_IntClear( p->vCubesS ); @@ -1041,6 +1011,9 @@ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning )      Vec_WecUnmarkLevels( p->vCubes, p->vCubesS );      Vec_WecUnmarkLevels( p->vCubes, p->vCubesD ); +    if ( Abc_Lit2Var(Lit0) == Abc_Lit2Var(Lit1) && Vec_IntSize(Hsh_VecReadEntry(p->pHash, iDiv)) == 2 ) +        goto ExtractFromPairs; +      // create new divisor      iVarNew = Vec_WecSize( p->vLits ) / 2;      assert( Vec_IntSize(p->vVarCube) == iVarNew ); @@ -1080,6 +1053,7 @@ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning )          p->nLits--;      }      // create updated double-cube divisor cube pairs +ExtractFromPairs:      k = 0;      p->nCompls = 0;      assert( Vec_IntSize(p->vCubesD) % 2 == 0 ); @@ -1092,18 +1066,22 @@ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning )          vCube2 = Vec_WecEntry( p->vCubes, Vec_IntEntry(p->vCubesD, i+1) );          RetValue  = Fx_ManDivRemoveLits( vCube, vDiv, fCompl );  // cube 2*i          RetValue += Fx_ManDivRemoveLits( vCube2, vDiv, fCompl ); // cube 2*i+1 -        assert( RetValue == Vec_IntSize(vDiv) ); -        if ( Vec_IntSize(vDiv) == 2 || fCompl ) +        assert( RetValue == Vec_IntSize(vDiv) || RetValue == Vec_IntSize( vDiv ) + 1); +        if ( iVarNew > 0 )          { -            Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 1) ); -            Vec_IntPush( vLitN, Vec_WecLevelId(p->vCubes, vCube) ); // MAKE SURE vCube IS SORTED BY ID -        } -        else  -        { -            Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 0) ); -            Vec_IntPush( vLitP, Vec_WecLevelId(p->vCubes, vCube) ); // MAKE SURE vCube IS SORTED BY ID +            if ( Vec_IntSize(vDiv) == 2 || fCompl ) +            { +                Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 1) ); +                Vec_IntPush( vLitN, Vec_WecLevelId(p->vCubes, vCube) ); // MAKE SURE vCube IS SORTED BY ID +            } +            else  +            { +                Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 0) ); +                Vec_IntPush( vLitP, Vec_WecLevelId(p->vCubes, vCube) ); // MAKE SURE vCube IS SORTED BY ID +            }          }          p->nLits -= Vec_IntSize(vDiv) + Vec_IntSize(vCube2) - 2; +          // remove second cube          Vec_IntWriteEntry( p->vCubesD, k++, Vec_WecLevelId(p->vCubes, vCube) );          Vec_IntClear( vCube2 );  @@ -1134,6 +1112,17 @@ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning )      Vec_WecUnmarkLevels( p->vCubes, p->vCubesS );      Vec_WecUnmarkLevels( p->vCubes, p->vCubesD ); +    // Deal with SCC +    if ( Vec_IntSize( p->vSCC ) ) +    { +        Vec_IntUniqify( p->vSCC ); +        Fx_ManForEachCubeVec( p->vSCC, p->vCubes, vCube, i ) +        { +            Fx_ManCubeDoubleCubeDivisors( p, Fx_ManGetFirstVarCube(p, vCube), vCube, 1, 1, fWarning );  // remove - update +            Vec_IntClear( vCube ); +        } +        Vec_IntClear( p->vSCC ); +    }      // add cost of the new divisor      if ( Vec_IntSize(vDiv) > 2 )      { @@ -1151,12 +1140,10 @@ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning )      Vec_IntForEachEntry( vDiv, Lit0, i )      {          Vec_IntTwoRemove( Vec_WecEntry(p->vLits, Abc_Lit2Var(Lit0)), p->vCubesD ); -        if ( p->nCompls && i > 1 ) // the last two lits are possibly complemented +        if ( (p->nCompls && i > 1) || Vec_IntSize( vDiv ) == 2 ) // the last two lits are possibly complemented              Vec_IntTwoRemove( Vec_WecEntry(p->vLits, Abc_LitNot(Abc_Lit2Var(Lit0))), p->vCubesD );      } -     -    // check predicted improvement: (new SOP lits == old SOP lits - divisor weight) -    assert( p->nLits == nLitsNew ); +  }  /**Function************************************************************* @@ -1186,7 +1173,7 @@ int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitC      Fx_ManComputeLevel( p );      Fx_ManCreateDivisors( p );      if ( fVeryVerbose ) -        Fx_PrintMatrix( p ); +        Fx_PrintDivisors( p );      if ( fVerbose )          Fx_PrintStats( p, Abc_Clock() - clk );      // perform extraction @@ -1198,7 +1185,7 @@ int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitC              Fx_PrintDiv( p, iDiv );          Fx_ManUpdate( p, iDiv, &fWarning );          if ( fVeryVeryVerbose ) -            Fx_PrintMatrix( p ); +            Fx_PrintDivisors( p );      }      if ( fVerbose )          Fx_PrintStats( p, Abc_Clock() - clk ); diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c index c45eaec5..08e2a560 100644 --- a/src/base/abci/abcIf.c +++ b/src/base/abci/abcIf.c @@ -116,7 +116,7 @@ Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars )      pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk);      // update timing info to reflect logic level -    if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib) && pNtk->pManTime ) +    if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib) && pNtk->pManTime )      {          int c;          if ( pNtk->AndGateDelay == 0.0 ) @@ -318,7 +318,7 @@ Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk )      // create the new network      if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )          pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); -    else if ( pIfMan->pPars->fUseSops || pIfMan->pPars->nGateSize > 0 ) +    else if ( pIfMan->pPars->fUseSops || pIfMan->pPars->fUserSesLib || pIfMan->pPars->nGateSize > 0 )          pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );      else          pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG ); @@ -445,12 +445,22 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t          return pNodeNew;      assert( pIfObj->Type == IF_AND );      // get the parameters of the best cut +    pCutBest = If_ObjCutBest( pIfObj ); +    if ( pIfMan->pPars->fUserSesLib ) +    { +        // create the subgraph composed of Abc_Obj_t nodes based on the given cut +        Abc_Obj_t * pFanins[IF_MAX_FUNC_LUTSIZE]; +        If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i ) +            pFanins[i] = Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover); +        pNodeNew = Abc_ExactBuildNode( If_CutTruthW(pIfMan, pCutBest), If_CutLeaveNum(pCutBest), If_CutArrTimeProfile(pIfMan, pCutBest), pFanins, pNtkNew ); +        If_ObjSetCopy( pIfObj, pNodeNew ); +        return pNodeNew; +    }      // create a new node       pNodeNew = Abc_NtkCreateNode( pNtkNew ); -    pCutBest = If_ObjCutBest( pIfObj ); -//    printf( "%d 0x%02X %d\n", pCutBest->nLeaves, 0xff & *If_CutTruth(pCutBest), pIfMan->pPars->pFuncCost(pCutBest) );  //    if ( pIfMan->pPars->pLutLib && pIfMan->pPars->pLutLib->fVarPinDelays ) -    if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->fUseTtPerm && !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->nGateSize ) +    if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->fUseTtPerm &&  +         !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize )          If_CutRotatePins( pIfMan, pCutBest );      if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )      { diff --git a/src/base/abci/abcMini.c b/src/base/abci/abcMini.c index bd893b5b..876f4c8c 100644 --- a/src/base/abci/abcMini.c +++ b/src/base/abci/abcMini.c @@ -205,7 +205,7 @@ void Abc_NtkMiniAigTest( Abc_Ntk_t * pNtk )      p = Abc_NtkToMiniAig( pNtk );      pNtkNew = Abc_NtkFromMiniAig( p );      Mini_AigStop( p ); -    Abc_NtkPrintStats( pNtkNew, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); +    Abc_NtkPrintStats( pNtkNew, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );      Abc_NtkDelete( pNtkNew );      // test dumping diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c index 40ce38b4..2129782f 100644 --- a/src/base/abci/abcPrint.c +++ b/src/base/abci/abcPrint.c @@ -235,7 +235,7 @@ float Abc_NtkGetArea( Abc_Ntk_t * pNtk )    SeeAlso     []  ***********************************************************************/ -void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower, int fGlitch, int fSkipBuf, int fPrintMem ) +void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower, int fGlitch, int fSkipBuf, int fSkipSmall, int fPrintMem )  {      int nSingles = fSkipBuf ? Abc_NtkGetBufNum(pNtk) : 0;      if ( fPrintMuxes && Abc_NtkIsStrash(pNtk) ) @@ -283,7 +283,7 @@ void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDum      if ( Abc_NtkIsNetlist(pNtk) )      {          Abc_Print( 1,"  net =%5d", Abc_NtkNetNum(pNtk) ); -        Abc_Print( 1,"  nd =%5d",  Abc_NtkNodeNum(pNtk) - nSingles ); +        Abc_Print( 1,"  nd =%5d",  fSkipSmall ? Abc_NtkGetLargeNodeNum(pNtk) : Abc_NtkNodeNum(pNtk) - nSingles );          Abc_Print( 1,"  wbox =%3d", Abc_NtkWhiteboxNum(pNtk) );          Abc_Print( 1,"  bbox =%3d", Abc_NtkBlackboxNum(pNtk) );      } @@ -295,7 +295,7 @@ void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDum      }      else      { -        Abc_Print( 1,"  nd =%6d", Abc_NtkNodeNum(pNtk) - nSingles ); +        Abc_Print( 1,"  nd =%6d", fSkipSmall ? Abc_NtkGetLargeNodeNum(pNtk) : Abc_NtkNodeNum(pNtk) - nSingles );          Abc_Print( 1,"  edge =%7d", Abc_NtkGetTotalFanins(pNtk) - nSingles );      } @@ -455,7 +455,7 @@ void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDum      fflush( stdout );      if ( pNtk->pExdc ) -        Abc_NtkPrintStats( pNtk->pExdc, fFactored, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf, fPrintMem ); +        Abc_NtkPrintStats( pNtk->pExdc, fFactored, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf, fSkipSmall, fPrintMem );  }  /**Function************************************************************* diff --git a/src/base/abci/module.make b/src/base/abci/module.make index a3c343ee..b97f526f 100644 --- a/src/base/abci/module.make +++ b/src/base/abci/module.make @@ -15,7 +15,9 @@ SRC +=    src/base/abci/abc.c \      src/base/abci/abcDetect.c \      src/base/abci/abcDress.c \      src/base/abci/abcDress2.c \ +    src/base/abci/abcDress3.c \      src/base/abci/abcDsd.c \ +    src/base/abci/abcExact.c \      src/base/abci/abcExtract.c \      src/base/abci/abcFraig.c \      src/base/abci/abcFx.c \ diff --git a/src/base/io/ioReadBench.c b/src/base/io/ioReadBench.c index 4fb21ad1..4d038200 100644 --- a/src/base/io/ioReadBench.c +++ b/src/base/io/ioReadBench.c @@ -94,6 +94,7 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p )      // allocate the empty network      pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); +    pNtk->nConstrs = 0;      // go through the lines of the file      vString = Vec_StrAlloc( 100 ); @@ -140,6 +141,7 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p )                          pTerm = Abc_NtkCreatePo( pNtk );                          Abc_ObjAddFanin( pTerm, pNet );                      } +                    pNtk->nConstrs++;                  }                  else                  { diff --git a/src/base/io/ioReadPlaMo.c b/src/base/io/ioReadPlaMo.c index 1cd453d2..d190d30a 100644 --- a/src/base/io/ioReadPlaMo.c +++ b/src/base/io/ioReadPlaMo.c @@ -297,6 +297,32 @@ static inline void Mop_ManRemoveEmpty( Mop_Man_t * p )  /**Function************************************************************* +  Synopsis    [Count how many times each variable appears in the input parts.] + +  Description [] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +Vec_Int_t * Mop_ManCollectStats( Mop_Man_t * p ) +{ +    int i, v, iCube, nVars = 32 * p->nWordsIn; +    Vec_Int_t * vStats = Vec_IntStart( nVars ); +    Vec_IntForEachEntry( p->vCubes, iCube, i ) +    { +        word * pCube = Mop_ManCubeIn(p, iCube); +        int nOutLits = Mop_ManCountOnes( Mop_ManCubeOut(p, iCube), p->nWordsOut ); +        for ( v = 0; v < nVars; v++ ) +            if ( Abc_TtGetQua(pCube, v) ) +                Vec_IntAddToEntry( vStats, v, nOutLits ); +    } +    return vStats; +} + +/**Function************************************************************* +    Synopsis    []    Description [] @@ -306,6 +332,20 @@ static inline void Mop_ManRemoveEmpty( Mop_Man_t * p )    SeeAlso     []  ***********************************************************************/ +// knowing that cubes are distance-1, find the different input variable +static inline int Mop_ManFindDiffVar( word * pCube1, word * pCube2, int nWords ) +{ +    int w, i; +    for ( w = 0; w < nWords; w++ ) +    { +        word Xor = pCube1[w] ^ pCube2[w]; +        for ( i = 0; i < 32; i++ ) +            if ( (Xor >> (i << 1)) & 0x3 ) +                return w * 32 + i; +    } +    assert( 0 ); +    return -1; +}  // check containment of input parts of two cubes  static inline int Mop_ManCheckDist1( word * pCube1, word * pCube2, int nWords )  { @@ -439,21 +479,30 @@ Vec_Int_t * Mop_ManFindDist1Pairs( Mop_Man_t * p, Vec_Int_t * vGroup )      return vPairs;  }  // merge distance-1 with identical output part -int Mop_ManMergeDist1Pairs( Mop_Man_t * p, Vec_Int_t * vGroup, Vec_Int_t * vGroupPrev ) +int Mop_ManMergeDist1Pairs( Mop_Man_t * p, Vec_Int_t * vGroup, Vec_Int_t * vGroupPrev, Vec_Int_t * vStats, int nLimit )  {      Vec_Int_t * vPairs    = Mop_ManFindDist1Pairs( p, vGroup );      Vec_Int_t * vPairsNew = Mop_ManCompatiblePairs( vPairs, Vec_IntSize(vGroup) ); -    int w, i, c1, c2, nCubes = Vec_IntSize(vGroup) + Vec_IntSize(vGroupPrev); +    int nCubes = Vec_IntSize(vGroup) + Vec_IntSize(vGroupPrev); +    int w, i, c1, c2, iCubeNew, iVar;      // move cubes to the previous group +    word * pCube, * pCube1, * pCube2; +    Vec_Int_t * vToFree = Vec_IntAlloc( Vec_IntSize(vPairsNew) );      Vec_IntForEachEntryDouble( vPairsNew, c1, c2, i )      { -        int iCubeNew  = Vec_IntPop( p->vFree ); +        pCube1 = Mop_ManCubeIn( p, Vec_IntEntry(vGroup, c1) ); +        pCube2 = Mop_ManCubeIn( p, Vec_IntEntry(vGroup, c2) ); +        assert( Mop_ManCheckDist1(pCube1, pCube2, p->nWordsIn) ); -        word * pCube  = Mop_ManCubeIn( p, iCubeNew ); -        word * pCube1 = Mop_ManCubeIn( p, Vec_IntEntry(vGroup, c1) ); -        word * pCube2 = Mop_ManCubeIn( p, Vec_IntEntry(vGroup, c2) ); +        // skip those cubes that have frequently appearing variables +        iVar = Mop_ManFindDiffVar( pCube1, pCube2, p->nWordsIn ); +        if ( Vec_IntEntry( vStats, iVar ) > nLimit ) +            continue; +        Vec_IntPush( vToFree, c1 ); +        Vec_IntPush( vToFree, c2 ); -        assert( Mop_ManCheckDist1(pCube1, pCube2, p->nWordsIn) ); +        iCubeNew  = Vec_IntPop( p->vFree ); +        pCube  = Mop_ManCubeIn( p, iCubeNew );          for ( w = 0; w < p->nWordsIn; w++ )              pCube[w] = pCube1[w] & pCube2[w]; @@ -467,13 +516,15 @@ int Mop_ManMergeDist1Pairs( Mop_Man_t * p, Vec_Int_t * vGroup, Vec_Int_t * vGrou          Vec_IntPush( vGroupPrev, iCubeNew );      } -    Vec_IntForEachEntry( vPairsNew, c1, i ) +//    Vec_IntForEachEntry( vPairsNew, c1, i ) +    Vec_IntForEachEntry( vToFree, c1, i )      {          if ( Vec_IntEntry(vGroup, c1) == -1 )              continue;          Vec_IntPush( p->vFree, Vec_IntEntry(vGroup, c1) );          Vec_IntWriteEntry( vGroup, c1, -1 );      } +    Vec_IntFree( vToFree );      if ( Vec_IntSize(vPairsNew) > 0 )          Map_ManGroupCompact( vGroup );      Vec_IntFree( vPairs ); @@ -529,7 +580,7 @@ int Mop_ManMergeDist1Pairs2( Mop_Man_t * p, Vec_Int_t * vGroup, Vec_Int_t * vGro          Map_ManGroupCompact( vGroup );      return Count;  } -int Mop_ManMergeDist1All( Mop_Man_t * p, Vec_Wec_t * vGroups ) +int Mop_ManMergeDist1All( Mop_Man_t * p, Vec_Wec_t * vGroups, Vec_Int_t * vStats, int nLimit )  {      Vec_Int_t * vGroup;      int i, nEqual, nReduce, Count = 0; @@ -544,7 +595,7 @@ int Mop_ManMergeDist1All( Mop_Man_t * p, Vec_Wec_t * vGroups )              return -1;          }          nEqual  = Mop_ManRemoveIdentical( p, vGroup ); -        nReduce = Mop_ManMergeDist1Pairs( p, vGroup, Vec_WecEntry(vGroups, i-1) ); +        nReduce = Mop_ManMergeDist1Pairs( p, vGroup, Vec_WecEntry(vGroups, i-1), vStats, nLimit );          //Mop_ManMergeDist1Pairs2( p, vGroup, Vec_WecEntry(vGroups, i-1) );          Count  += nEqual + nReduce;          //printf( "Group %3d : Equal =%5d. Reduce =%5d.\n", i, nEqual, nReduce ); @@ -599,16 +650,20 @@ void Mop_ManReduce2( Mop_Man_t * p )  {      abctime clk = Abc_Clock();      int nCubes  = Vec_IntSize(p->vCubes); +    Vec_Int_t * vStats = Mop_ManCollectStats( p );      Vec_Wec_t * vGroups = Mop_ManCreateGroups( p ); +    int nLimit    = ABC_INFINITY; // 5 * Vec_IntSum(vStats) / Vec_IntSize(vStats) + 1;      int nOutLits  = Mop_ManCountOutputLits( p );      int Count1    = Mop_ManMergeContainAll( p, vGroups ); -    int Count2    = Mop_ManMergeDist1All( p, vGroups ); +    int Count2    = Mop_ManMergeDist1All( p, vGroups, vStats, nLimit );      int Count3    = Mop_ManMergeContainAll( p, vGroups ); -    int Count4    = Mop_ManMergeDist1All( p, vGroups ); +    int Count4    = Mop_ManMergeDist1All( p, vGroups, vStats, nLimit );      int Count5    = Mop_ManMergeContainAll( p, vGroups );      int Removed   = Mop_ManUnCreateGroups( p, vGroups );      int nOutLits2 = Mop_ManCountOutputLits( p );      Vec_WecFree( vGroups ); +//Vec_IntPrint( vStats ); +    Vec_IntFree( vStats );      assert( Removed == Count1 + Count2 + Count3 );      // report      printf( "Cubes: %d -> %d.  C = %d.  M = %d.  C = %d.  M = %d.  C = %d.  Output lits: %d -> %d.   ",  diff --git a/src/base/wlc/wlc.h b/src/base/wlc/wlc.h index 51152fa8..bb5c4bfe 100644 --- a/src/base/wlc/wlc.h +++ b/src/base/wlc/wlc.h @@ -259,7 +259,7 @@ extern Vec_Int_t *    Wlc_NtkFindUifableMultiplierPairs( Wlc_Ntk_t * p );  extern Wlc_Ntk_t *    Wlc_NtkAbstractNodes( Wlc_Ntk_t * pNtk, Vec_Int_t * vNodes );  extern Wlc_Ntk_t *    Wlc_NtkUifNodePairs( Wlc_Ntk_t * pNtk, Vec_Int_t * vPairs );  /*=== wlcBlast.c ========================================================*/ -extern Gia_Man_t *    Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int fGiaSimple, int fAddOutputs ); +extern Gia_Man_t *    Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int iOutput, int nRange, int fGiaSimple, int fAddOutputs, int fBooth );  /*=== wlcCom.c ========================================================*/  extern void           Wlc_SetNtk( Abc_Frame_t * pAbc, Wlc_Ntk_t * pNtk );  /*=== wlcNtk.c ========================================================*/ diff --git a/src/base/wlc/wlcBlast.c b/src/base/wlc/wlcBlast.c index 79ad3659..c86c7cf0 100644 --- a/src/base/wlc/wlcBlast.c +++ b/src/base/wlc/wlcBlast.c @@ -143,16 +143,19 @@ void Wlc_BlastShiftRightInt( Gia_Man_t * pNew, int * pNum, int nNum, int * pShif  void Wlc_BlastShiftRight( Gia_Man_t * pNew, int * pNum, int nNum, int * pShift, int nShift, int fSticky, Vec_Int_t * vRes )  {      int nShiftMax = Abc_Base2Log(nNum); +    int * pShiftNew = ABC_ALLOC( int, nShift ); +    memcpy( pShiftNew, pShift, sizeof(int)*nShift );      if ( nShiftMax < nShift )      { -        int i, iRes = pShift[nShiftMax]; +        int i, iRes = pShiftNew[nShiftMax];          for ( i = nShiftMax + 1; i < nShift; i++ ) -            iRes = Gia_ManHashOr( pNew, iRes, pShift[i] ); -        pShift[nShiftMax++] = iRes; +            iRes = Gia_ManHashOr( pNew, iRes, pShiftNew[i] ); +        pShiftNew[nShiftMax++] = iRes;      }      else           nShiftMax = nShift; -    Wlc_BlastShiftRightInt( pNew, pNum, nNum, pShift, nShiftMax, fSticky, vRes ); +    Wlc_BlastShiftRightInt( pNew, pNum, nNum, pShiftNew, nShiftMax, fSticky, vRes ); +    ABC_FREE( pShiftNew );  }  void Wlc_BlastShiftLeftInt( Gia_Man_t * pNew, int * pNum, int nNum, int * pShift, int nShift, int fSticky, Vec_Int_t * vRes )  { @@ -176,16 +179,19 @@ void Wlc_BlastShiftLeftInt( Gia_Man_t * pNew, int * pNum, int nNum, int * pShift  void Wlc_BlastShiftLeft( Gia_Man_t * pNew, int * pNum, int nNum, int * pShift, int nShift, int fSticky, Vec_Int_t * vRes )  {      int nShiftMax = Abc_Base2Log(nNum); +    int * pShiftNew = ABC_ALLOC( int, nShift ); +    memcpy( pShiftNew, pShift, sizeof(int)*nShift );      if ( nShiftMax < nShift )      { -        int i, iRes = pShift[nShiftMax]; +        int i, iRes = pShiftNew[nShiftMax];          for ( i = nShiftMax + 1; i < nShift; i++ ) -            iRes = Gia_ManHashOr( pNew, iRes, pShift[i] ); -        pShift[nShiftMax++] = iRes; +            iRes = Gia_ManHashOr( pNew, iRes, pShiftNew[i] ); +        pShiftNew[nShiftMax++] = iRes;      }      else           nShiftMax = nShift; -    Wlc_BlastShiftLeftInt( pNew, pNum, nNum, pShift, nShiftMax, fSticky, vRes ); +    Wlc_BlastShiftLeftInt( pNew, pNum, nNum, pShiftNew, nShiftMax, fSticky, vRes ); +    ABC_FREE( pShiftNew );  }  void Wlc_BlastRotateRight( Gia_Man_t * pNew, int * pNum, int nNum, int * pShift, int nShift, Vec_Int_t * vRes )  { @@ -674,6 +680,7 @@ void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vL              Vec_IntPush( vProd, 0 );          assert( Vec_IntSize(vProd) == 2 );      } +//    Vec_WecPrint( vProds, 0 );      vLevel = Vec_WecEntry( vLevels, 0 );      Vec_IntClear( vRes ); @@ -684,7 +691,9 @@ void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vL          Vec_IntPush( vRes,   Vec_IntEntry(vProd, 0) );          Vec_IntPush( vLevel, Vec_IntEntry(vProd, 1) );      } -    Wlc_BlastAdder( pNew, Vec_IntArray(vRes), Vec_IntArray(vLevel), nSize ); +    Vec_IntPush( vRes,   0 ); +    Vec_IntPush( vLevel, 0 ); +    Wlc_BlastAdder( pNew, Vec_IntArray(vRes), Vec_IntArray(vLevel), Vec_IntSize(vRes) );  }  void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes )  { @@ -728,6 +737,81 @@ void Wlc_BlastSquare( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vTmp,      Vec_WecFree( vProds );      Vec_WecFree( vLevels );  } +void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned ) +{ +    Vec_Wec_t * vProds  = Vec_WecStart( nArgA + nArgB + 3 ); +    Vec_Wec_t * vLevels = Vec_WecStart( nArgA + nArgB + 3 ); +    int FillA = fSigned ? pArgA[nArgA-1] : 0; +    int FillB = fSigned ? pArgB[nArgB-1] : 0; +    int i, k, Sign; +    // create new arguments +    Vec_Int_t * vArgB = Vec_IntAlloc( nArgB + 3 ); +    Vec_IntPush( vArgB, 0 ); +    for ( i = 0; i < nArgB; i++ ) +        Vec_IntPush( vArgB, pArgB[i] ); +    Vec_IntPush( vArgB, FillB ); +    if ( Vec_IntSize(vArgB) % 2 == 0 ) +        Vec_IntPush( vArgB, FillB ); +    assert( Vec_IntSize(vArgB) % 2 == 1 ); +    // iterate through bit-pairs +    for ( k = 0; k+2 < Vec_IntSize(vArgB); k+=2 ) +    { +        int pp    = -1; +        int Q2jM1 = Vec_IntEntry(vArgB, k);   // q(2*j-1) +        int Q2j   = Vec_IntEntry(vArgB, k+1); // q(2*j+0) +        int Q2jP1 = Vec_IntEntry(vArgB, k+2); // q(2*j+1) +        int Neg   = Q2jP1; +        int One   = Gia_ManHashXor( pNew, Q2j, Q2jM1 ); +        int Two   = Gia_ManHashMux( pNew, Neg, Gia_ManHashAnd(pNew, Abc_LitNot(Q2j), Abc_LitNot(Q2jM1)), Gia_ManHashAnd(pNew, Q2j, Q2jM1) ); +        for ( i = 0; i <= nArgA; i++ ) +        { +            int This = i == nArgA ? FillA : pArgA[i]; +            int Prev = i ? pArgA[i-1] : 0; +            int Part = Gia_ManHashOr( pNew, Gia_ManHashAnd(pNew, One, This), Gia_ManHashAnd(pNew, Two, Prev) ); +             +            pp = Gia_ManHashXor( pNew, Part, Neg ); + +            if ( pp == 0 ) +                continue; +            Vec_WecPush( vProds,  k+i, pp ); +            Vec_WecPush( vLevels, k+i, 0 ); +        } +        // perform sign extension +        Sign = fSigned ? pp : Neg; +        if ( k == 0 ) +        { +            Vec_WecPush( vProds,  k+i, Sign ); +            Vec_WecPush( vLevels, k+i, 0 ); + +            Vec_WecPush( vProds,  k+i+1, Sign ); +            Vec_WecPush( vLevels, k+i+1, 0 ); + +            Vec_WecPush( vProds,  k+i+2, Abc_LitNot(Sign) ); +            Vec_WecPush( vLevels, k+i+2, 0 ); +        } +        else +        { +            Vec_WecPush( vProds,  k+i, Abc_LitNot(Sign) ); +            Vec_WecPush( vLevels, k+i, 0 ); + +            Vec_WecPush( vProds,  k+i+1, 1 ); +            Vec_WecPush( vLevels, k+i+1, 0 ); +        } +        // add neg to the first column +        if ( Neg == 0 ) +            continue; +        Vec_WecPush( vProds,  k, Neg ); +        Vec_WecPush( vLevels, k, 0 ); +    } +    //Vec_WecPrint( vProds, 0 ); + +    Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes ); + +    Vec_WecFree( vProds ); +    Vec_WecFree( vLevels ); +    Vec_IntFree( vArgB ); +} +  /**Function************************************************************* @@ -740,7 +824,7 @@ void Wlc_BlastSquare( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vTmp,    SeeAlso     []  ***********************************************************************/ -Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int fGiaSimple, int fAddOutputs ) +Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int iOutput, int nOutputRange, int fGiaSimple, int fAddOutputs, int fBooth )  {      int fVerbose = 0;      int fUseOldMultiplierBlasting = 0; @@ -1149,9 +1233,12 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int fGiaSimple,                  int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, fSigned );                  if ( Wlc_NtkCountConstBits(pArg0, nRangeMax) < Wlc_NtkCountConstBits(pArg1, nRangeMax) )                      ABC_SWAP( int *, pArg0, pArg1 ); -                Wlc_BlastMultiplier( pNew, pArg0, pArg1, nRangeMax, nRangeMax, vTemp2, vRes, fSigned ); +                if ( fBooth ) +                    Wlc_BlastBooth( pNew, pArg0, pArg1, nRange0, nRange1, vRes, fSigned ); +                else +                    Wlc_BlastMultiplier( pNew, pArg0, pArg1, nRangeMax, nRangeMax, vTemp2, vRes, fSigned );                  //Wlc_BlastMultiplier3( pNew, pArg0, pArg1, nRange0, nRange1, vRes ); -                if ( nRange > nRangeMax + nRangeMax ) +                if ( nRange > Vec_IntSize(vRes) )                      Vec_IntFillExtra( vRes, nRange, fSigned ? Vec_IntEntryLast(vRes) : 0 );                  else                      Vec_IntShrink( vRes, nRange ); @@ -1233,6 +1320,9 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int fGiaSimple,      // create COs      Wlc_NtkForEachCo( p, pObj, i )      { +        // skip all outputs except the given ones +        if ( iOutput >= 0 && (i < iOutput || i >= iOutput + nOutputRange) ) +            continue;          // create additional PO literals          if ( vAddOutputs && pObj->fIsFi )          { diff --git a/src/base/wlc/wlcCom.c b/src/base/wlc/wlcCom.c index 77bf36ba..2c504127 100644 --- a/src/base/wlc/wlcCom.c +++ b/src/base/wlc/wlcCom.c @@ -128,10 +128,10 @@ int Abc_CommandReadWlc( Abc_Frame_t * pAbc, int argc, char ** argv )          switch ( c )          {          case 'o': -            fPrintTree ^= 1; +            fOldParser ^= 1;              break;          case 'p': -            fOldParser ^= 1; +            fPrintTree ^= 1;              break;          case 'v':              fVerbose ^= 1; @@ -338,12 +338,34 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv )      Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc);      Vec_Int_t * vBoxIds = NULL;      Gia_Man_t * pNew = NULL; -    int c, fGiaSimple = 0, fAddOutputs = 0, fMulti = 0, fVerbose  = 0; +    int c, iOutput = -1, nOutputRange = 2, fGiaSimple = 0, fAddOutputs = 0, fMulti = 0, fBooth = 0, fVerbose  = 0;      Extra_UtilGetoptReset(); -    while ( ( c = Extra_UtilGetopt( argc, argv, "comvh" ) ) != EOF ) +    while ( ( c = Extra_UtilGetopt( argc, argv, "ORcombvh" ) ) != EOF )      {          switch ( c )          { +        case 'O': +            if ( globalUtilOptind >= argc ) +            { +                Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); +                goto usage; +            } +            iOutput = atoi(argv[globalUtilOptind]); +            globalUtilOptind++; +            if ( iOutput < 0 ) +                goto usage; +            break; +        case 'R': +            if ( globalUtilOptind >= argc ) +            { +                Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); +                goto usage; +            } +            nOutputRange = atoi(argv[globalUtilOptind]); +            globalUtilOptind++; +            if ( nOutputRange < 0 ) +                goto usage; +            break;          case 'c':              fGiaSimple ^= 1;              break; @@ -353,6 +375,9 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv )          case 'm':              fMulti ^= 1;              break; +        case 'b': +            fBooth ^= 1; +            break;          case 'v':              fVerbose ^= 1;              break; @@ -373,8 +398,13 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv )          if ( vBoxIds == NULL )              Abc_Print( 1, "Warning:  There is no multipliers in the design.\n" );      } +    if ( iOutput >= 0 && iOutput + nOutputRange > Wlc_NtkPoNum(pNtk) ) +    { +        Abc_Print( 1, "Abc_CommandBlast(): The output range [%d:%d] is incorrect.\n", iOutput, iOutput + nOutputRange - 1 ); +        return 0; +    }      // transform -    pNew = Wlc_NtkBitBlast( pNtk, vBoxIds, fGiaSimple, fAddOutputs ); +    pNew = Wlc_NtkBitBlast( pNtk, vBoxIds, iOutput, nOutputRange, fGiaSimple, fAddOutputs, fBooth );      Vec_IntFreeP( &vBoxIds );      if ( pNew == NULL )      { @@ -384,11 +414,14 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv )      Abc_FrameUpdateGia( pAbc, pNew );      return 0;  usage: -    Abc_Print( -2, "usage: %%blast [-comvh]\n" ); +    Abc_Print( -2, "usage: %%blast [-OR num] [-combvh]\n" );      Abc_Print( -2, "\t         performs bit-blasting of the word-level design\n" ); +    Abc_Print( -2, "\t-O num : zero-based index of the first word-level PO to bit-blast [default = %d]\n", iOutput ); +    Abc_Print( -2, "\t-R num : the total number of word-level POs to bit-blast [default = %d]\n", nOutputRange );      Abc_Print( -2, "\t-c     : toggle using AIG w/o const propagation and strashing [default = %s]\n", fGiaSimple? "yes": "no" );      Abc_Print( -2, "\t-o     : toggle using additional POs on the word-level boundaries [default = %s]\n", fAddOutputs? "yes": "no" );      Abc_Print( -2, "\t-m     : toggle creating boxes for all multipliers in the design [default = %s]\n", fMulti? "yes": "no" ); +    Abc_Print( -2, "\t-b     : toggle generating radix-4 Booth multipliers [default = %s]\n", fBooth? "yes": "no" );      Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );      Abc_Print( -2, "\t-h     : print the command usage\n");      return 1; diff --git a/src/base/wlc/wlcReadSmt.c b/src/base/wlc/wlcReadSmt.c index ed6092a5..fcd47274 100644 --- a/src/base/wlc/wlcReadSmt.c +++ b/src/base/wlc/wlcReadSmt.c @@ -276,13 +276,9 @@ static inline int Smt_PrsCreateNode( Wlc_Ntk_t * pNtk, int Type, int fSigned, in      assert( fSigned >= 0 );      Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj), vFanins );      if ( fSigned ) -    {          Wlc_NtkObj(pNtk, iObj)->Signed = fSigned; -//        if ( Vec_IntSize(vFanins) > 0 ) -//            Wlc_NtkObj(pNtk, Vec_IntEntry(vFanins, 0))->Signed = fSigned; -//        if ( Vec_IntSize(vFanins) > 1 ) -//            Wlc_NtkObj(pNtk, Vec_IntEntry(vFanins, 1))->Signed = fSigned; -    } +    if ( Type == WLC_OBJ_SHIFT_RA ) +        Wlc_NtkObj(pNtk, iObj)->Signed = 1;      if ( pName == NULL )      {          sprintf( Buffer, "_n%d_", iObj ); @@ -511,6 +507,13 @@ Wlc_Ntk_t * Smt_PrsBuild( Smt_Prs_t * p )          // skip ()          Fan = Vec_IntEntry(vFans, 2);          assert( !Smt_EntryIsName(Fan) ); +        vFans2 = Smt_VecEntryNode(p, vFans, 2); +        if ( Vec_IntSize(vFans2) > 0 ) +        { +            printf( "File parsing error: Uninterpreted functions are not supported.\n" ); +            Wlc_NtkFree( pNtk ); pNtk = NULL; +            goto finish; +        }          // check type (Bool or BitVec)          Fan = Vec_IntEntry(vFans, 3);          if ( Smt_EntryIsName(Fan) )  @@ -921,6 +924,13 @@ Wlc_Ntk_t * Smt_PrsBuild2( Smt_Prs_t * p )              // skip ()              Fan = Vec_IntEntry(vFans, 2);              assert( !Smt_EntryIsName(Fan) ); +            vFans2 = Smt_VecEntryNode(p, vFans, 2); +            if ( Vec_IntSize(vFans2) > 0 ) +            { +                printf( "File parsing error: Uninterpreted functions are not supported.\n" ); +                Wlc_NtkFree( pNtk ); pNtk = NULL; +                goto finish; +            }              // check type (Bool or BitVec)              Fan = Vec_IntEntry(vFans, 3);              if ( Smt_EntryIsName(Fan) )  diff --git a/src/base/wlc/wlcReadVer.c b/src/base/wlc/wlcReadVer.c index 824cf80b..08dc8e98 100644 --- a/src/base/wlc/wlcReadVer.c +++ b/src/base/wlc/wlcReadVer.c @@ -1265,10 +1265,10 @@ Wlc_Ntk_t * Wlc_ReadVer( char * pFileName )      // derive topological order      pNtk = Wlc_NtkDupDfs( p->pNtk );      Wlc_NtkTransferNames( pNtk, p->pNtk ); +    pNtk->pSpec = Abc_UtilStrsav( pFileName );  finish:      Wlc_PrsPrintErrorMessage( p );      Wlc_PrsStop( p ); -    pNtk->pSpec = Abc_UtilStrsav( pFileName );      return pNtk;  } @@ -1291,7 +1291,7 @@ void Io_ReadWordTest( char * pFileName )          return;      Wlc_WriteVer( pNtk, "test.v", 0, 0 ); -    pNew = Wlc_NtkBitBlast( pNtk, NULL, 0, 0 ); +    pNew = Wlc_NtkBitBlast( pNtk, NULL, -1, 0, 0, 0, 0 );      Gia_AigerWrite( pNew, "test.aig", 0, 0 );      Gia_ManStop( pNew ); diff --git a/src/base/wlc/wlcSim.c b/src/base/wlc/wlcSim.c index 73d5307f..20ac8c61 100644 --- a/src/base/wlc/wlcSim.c +++ b/src/base/wlc/wlcSim.c @@ -129,7 +129,7 @@ Vec_Ptr_t * Wlc_NtkSimulate( Wlc_Ntk_t * p, Vec_Int_t * vNodes, int nWords, int  {      Gia_Obj_t * pObj;       Vec_Ptr_t * vOne, * vRes; -    Gia_Man_t * pGia = Wlc_NtkBitBlast( p, NULL, 0, 0 ); +    Gia_Man_t * pGia = Wlc_NtkBitBlast( p, NULL, -1, 0, 0, 0, 0 );      Wlc_Obj_t * pWlcObj;      int f, i, k, w, nBits, Counter = 0;      // allocate simulation info for one timeframe diff --git a/src/map/if/if.h b/src/map/if/if.h index 0282a1bd..ca7e0411 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -124,6 +124,7 @@ struct If_Par_t_      int                fDelayOptLut;  // delay optimization for LUTs      int                fDsdBalance;   // special delay optimization      int                fUserRecLib;   // use recorded library +    int                fUserSesLib;   // use SAT-based synthesis      int                fBidec;        // use bi-decomposition      int                fUse34Spec;    // use specialized matching      int                fUseBat;       // use one specialized feature @@ -263,6 +264,7 @@ struct If_Man_t_      int                nBestCutSmall[2];      int                nCountNonDec[2];      Vec_Int_t *        vCutData;      // cut data storage +    int                pArrTimeProfile[IF_MAX_FUNC_LUTSIZE];      // timing manager      Tim_Man_t *        pManTim; @@ -616,6 +618,7 @@ extern void            If_ManDerefNodeCutSet( If_Man_t * p, If_Obj_t * pObj );  extern void            If_ManDerefChoiceCutSet( If_Man_t * p, If_Obj_t * pObj );  extern void            If_ManSetupSetAll( If_Man_t * p, int nCrossCut );  /*=== ifMap.c =============================================================*/ +extern int *           If_CutArrTimeProfile( If_Man_t * p, If_Cut_t * pCut );  extern void            If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess, int fFirst );  extern void            If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess );  extern int             If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fPreprocess, int fFirst, char * pLabel ); diff --git a/src/map/if/ifCut.c b/src/map/if/ifCut.c index 9e0c5a70..9b8d75ad 100644 --- a/src/map/if/ifCut.c +++ b/src/map/if/ifCut.c @@ -753,7 +753,7 @@ void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut )      if ( !pCut->fUseless &&            (p->pPars->fUseDsd || p->pPars->fUseBat ||  -          p->pPars->pLutStruct || p->pPars->fUserRecLib ||  +          p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib ||             p->pPars->fEnableCheck07 || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec ||             p->pPars->fUseDsdTune || p->pPars->fEnableCheck75 || p->pPars->fEnableCheck75u) )      { diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c index c4053f52..76d3c757 100644 --- a/src/map/if/ifMap.c +++ b/src/map/if/ifMap.c @@ -28,7 +28,8 @@ ABC_NAMESPACE_IMPL_START  ////////////////////////////////////////////////////////////////////////  extern char * Dau_DsdMerge( char * pDsd0i, int * pPerm0, char * pDsd1i, int * pPerm1, int fCompl0, int fCompl1, int nVars ); -extern int    If_CutDelayRecCost3(If_Man_t* p, If_Cut_t* pCut, If_Obj_t * pObj); +extern int    If_CutDelayRecCost3( If_Man_t* p, If_Cut_t* pCut, If_Obj_t * pObj ); +extern int    Abc_ExactDelayCost( word * pTruth, int nVars, int * pArrTimeProfile, char * pPerm, int * Cost, int AigLevel );  ////////////////////////////////////////////////////////////////////////  ///                     FUNCTION DEFINITIONS                         /// @@ -80,6 +81,25 @@ float If_CutDelaySpecial( If_Man_t * p, If_Cut_t * pCut, int fCarry )      return Delay;  } +/**Function************************************************************* + +  Synopsis    [Returns arrival time profile of the cut.] + +  Description [The procedure returns static storage, which should not be +  deallocated and is only valid until before the procedure is called again.] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +int * If_CutArrTimeProfile( If_Man_t * p, If_Cut_t * pCut ) +{ +    int i; +    for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) +        p->pArrTimeProfile[i] = (int)If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; +    return p->pArrTimeProfile; +}  /**Function************************************************************* @@ -99,7 +119,8 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep      If_Cut_t * pCut0R, * pCut1R;      int fFunc0R, fFunc1R;      int i, k, v, iCutDsd, fChange; -    int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUseDsdTune || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->pLutStruct != NULL; +    int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib ||  +        p->pPars->fUseDsdTune || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->pLutStruct != NULL;      int fUseAndCut = (p->pPars->nAndDelay > 0) || (p->pPars->nAndArea > 0);      assert( !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->pCutSet->nCuts > 0 );      assert( !If_ObjIsAnd(pObj->pFanin1) || pObj->pFanin1->pCutSet->nCuts > 0 ); @@ -127,6 +148,19 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep              pCut->Delay = If_CutDsdBalanceEval( p, pCut, NULL );          else if ( p->pPars->fUserRecLib )              pCut->Delay = If_CutDelayRecCost3( p, pCut, pObj );  +        else if ( p->pPars->fUserSesLib ) +        { +            int Cost = 0; +            pCut->fUser = 1; +            pCut->Delay = (float)Abc_ExactDelayCost( If_CutTruthW(p, pCut), If_CutLeaveNum(pCut), If_CutArrTimeProfile(p, pCut), If_CutPerm(pCut), &Cost, (int)pObj->Level );  +            if ( Cost == ABC_INFINITY ) +            { +                for ( v = 0; v < If_CutLeaveNum(pCut); v++ ) +                    If_CutPerm(pCut)[v] = IF_BIG_CHAR; +                pCut->Cost = IF_COST_MAX; +                pCut->fUseless = 1; +            } +        }          else if ( p->pPars->fDelayOptLut )              pCut->Delay = If_CutLutBalanceEval( p, pCut );          else if( p->pPars->nGateSize > 0 ) @@ -333,22 +367,23 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep              continue;          // check if the cut satisfies the required times          if ( p->pPars->fDelayOpt ) -        {              pCut->Delay = If_CutSopBalanceEval( p, pCut, NULL ); -//            if ( pCut->Delay >= pObj->Level && pCut->nLeaves > 2 ) -//                pCut->Delay += 1; -        }          else if ( p->pPars->fDsdBalance ) -        {              pCut->Delay = If_CutDsdBalanceEval( p, pCut, NULL ); -//            if ( pCut->Delay >= pObj->Level && pCut->nLeaves > 2 ) -//                pCut->Delay += 1; -        }          else if ( p->pPars->fUserRecLib ) -        {              pCut->Delay = If_CutDelayRecCost3( p, pCut, pObj );  -//            if ( pCut->Delay >= pObj->Level && pCut->nLeaves > 2 ) -//                pCut->Delay += 1; +        else if ( p->pPars->fUserSesLib ) +        { +            int Cost = 0; +            pCut->fUser = 1; +            pCut->Delay = (float)Abc_ExactDelayCost( If_CutTruthW(p, pCut), If_CutLeaveNum(pCut), If_CutArrTimeProfile(p, pCut), If_CutPerm(pCut), &Cost, (int)pObj->Level );  +            if ( Cost == ABC_INFINITY ) +            { +                for ( v = 0; v < If_CutLeaveNum(pCut); v++ ) +                    If_CutPerm(pCut)[v] = IF_BIG_CHAR; +                pCut->Cost = IF_COST_MAX; +                pCut->fUseless = 1; +            }          }          else if ( p->pPars->fDelayOptLut )              pCut->Delay = If_CutLutBalanceEval( p, pCut ); @@ -378,7 +413,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep      if ( !fPreprocess || pCutSet->ppCuts[0]->Delay <= pObj->Required + p->fEpsilon )      {          If_CutCopy( p, If_ObjCutBest(pObj), pCutSet->ppCuts[0] ); -        if(p->pPars->fUserRecLib) +        if ( p->pPars->fUserRecLib || p->pPars->fUserSesLib )              assert(If_ObjCutBest(pObj)->Cost < IF_COST_MAX && If_ObjCutBest(pObj)->Delay < ABC_INFINITY);      }      // add the trivial cut to the set @@ -421,7 +456,7 @@ void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fP      If_Set_t * pCutSet;      If_Obj_t * pTemp;      If_Cut_t * pCutTemp, * pCut; -    int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUse34Spec; +    int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUse34Spec;      assert( pObj->pEquiv != NULL );      // prepare diff --git a/src/opt/fxch/Fxch.c b/src/opt/fxch/Fxch.c index 6c3983ef..84a4c566 100644 --- a/src/opt/fxch/Fxch.c +++ b/src/opt/fxch/Fxch.c @@ -15,7 +15,6 @@    Revision    []  ***********************************************************************/ -  #include "Fxch.h"  ABC_NAMESPACE_IMPL_START @@ -26,6 +25,128 @@ ABC_NAMESPACE_IMPL_START  /**Function************************************************************* +  Synopsis    [] + +  Description [] + +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +void Fxch_CubesGruping(Fxch_Man_t* pFxchMan) +{ +    Vec_Int_t* vCube; +    int iCube, nOutputs, SizeOutputID; +    Hsh_VecMan_t* pCubeHash; + +    /* Identify the number of Outputs and create the translation table */ +    pFxchMan->vTranslation = Vec_IntAlloc( 32 ); +    Vec_WecForEachLevel( pFxchMan->vCubes, vCube, iCube ) +    { +        int Id = Vec_IntEntry( vCube, 0 ); +        int iTranslation = Vec_IntFind( pFxchMan->vTranslation, Id ); + +        if ( iTranslation == -1 ) +            Vec_IntPush( pFxchMan->vTranslation, Id ); +    } +    nOutputs = Vec_IntSize( pFxchMan->vTranslation ); + +    /* Size of the OutputID in number o ints */ +    SizeOutputID = ( nOutputs >> 5 ) + ( ( nOutputs & 31 ) > 0 ); + +    /* Initialize needed structures */ +    pFxchMan->vOutputID = Vec_IntAlloc( 4096 ); +    pFxchMan->pTempOutputID = ABC_CALLOC( int, SizeOutputID ); +    pFxchMan->nSizeOutputID = SizeOutputID; + +    pCubeHash =  Hsh_VecManStart( 1024 ); + +    /* Identify equal cubes */ +    Vec_WecForEachLevel( pFxchMan->vCubes, vCube, iCube ) +    { +        int Id = Vec_IntEntry( vCube, 0 ); +        int iTranslation = Vec_IntFind( pFxchMan->vTranslation, Id ); +        int i, iCubeNoID, Temp, * pEntry; +        Vec_IntWriteEntry( vCube, 0, 0 ); // Clear ID, Outputs will be identified by it later + +        iCubeNoID = Hsh_VecManAdd( pCubeHash, vCube ); +        Temp = ( 1 << ( iTranslation & 31 ) ); +        if ( iCubeNoID == Vec_IntSize( pFxchMan->vOutputID ) / SizeOutputID ) +        { +            for ( i = 0; i < SizeOutputID; i++ ) +                pFxchMan->pTempOutputID[i] = 0; + +            pFxchMan->pTempOutputID[ iTranslation >> 5 ] = Temp; +            Vec_IntPushArray( pFxchMan->vOutputID, pFxchMan->pTempOutputID, SizeOutputID );  +        } +        else +        { +            Vec_IntClear( vCube ); +            pEntry = Vec_IntEntryP( pFxchMan->vOutputID, ( iCubeNoID * SizeOutputID ) + ( iTranslation >> 5 ) ); +            *pEntry |= Temp; +        } +    } + +    Hsh_VecManStop( pCubeHash ); +    Vec_WecRemoveEmpty( pFxchMan->vCubes ); +} + +/**Function************************************************************* + +  Synopsis    [] + +  Description [] + +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +void Fxch_CubesUnGruping(Fxch_Man_t* pFxchMan) +{ +    int iCube; +    int i, j; +    Vec_Int_t* vCube; +    Vec_Int_t* vNewCube; + +    assert( Vec_WecSize( pFxchMan->vCubes ) == ( Vec_IntSize( pFxchMan->vOutputID ) / pFxchMan->nSizeOutputID ) ); +    Vec_WecForEachLevel( pFxchMan->vCubes, vCube, iCube ) +    { +        int * pOutputID, nOnes; +        if ( Vec_IntSize( vCube ) == 0 || Vec_IntEntry( vCube, 0 ) != 0 ) +            continue; + +        pOutputID = Vec_IntEntryP( pFxchMan->vOutputID, iCube * pFxchMan->nSizeOutputID ); +        nOnes = 0; + +        for ( i = 0; i < pFxchMan->nSizeOutputID; i++ ) +            nOnes += Fxch_CountOnes( (unsigned int) pOutputID[i] ); + +        for ( i = 0; i < pFxchMan->nSizeOutputID && nOnes; i++ ) +            for ( j = 0; j < 32 && nOnes; j++ ) +                if ( pOutputID[i] & ( 1 << j ) ) +                { +                    if ( nOnes == 1 ) +                        Vec_IntWriteEntry( vCube, 0, Vec_IntEntry( pFxchMan->vTranslation, ( i << 5 ) | j ) ); +                    else +                    { +                        vNewCube = Vec_WecPushLevel( pFxchMan->vCubes ); +                        Vec_IntAppend( vNewCube, vCube ); +                        Vec_IntWriteEntry( vNewCube, 0, Vec_IntEntry( pFxchMan->vTranslation, (i << 5 ) | j ) ); +                    } +                    nOnes -= 1; +                } +    } + +    Vec_IntFree( pFxchMan->vTranslation ); +    Vec_IntFree( pFxchMan->vOutputID ); +    ABC_FREE( pFxchMan->pTempOutputID ); +    return; +} + +/**Function************************************************************* +    Synopsis    [ Performs fast extract with cube hashing on a set                  of covers. ] @@ -47,6 +168,7 @@ int Fxch_FastExtract( Vec_Wec_t* vCubes,      int i;      TempTime = Abc_Clock(); +    Fxch_CubesGruping( pFxchMan );      Fxch_ManMapLiteralsIntoCubes( pFxchMan, ObjIdMax );      Fxch_ManGenerateLitHashKeys( pFxchMan );      Fxch_ManComputeLevel( pFxchMan ); @@ -61,6 +183,7 @@ int Fxch_FastExtract( Vec_Wec_t* vCubes,          Fxch_ManPrintStats( pFxchMan );      TempTime = Abc_Clock(); +          for ( i = 0; (!nMaxDivExt || i < nMaxDivExt) && Vec_QueTopPriority( pFxchMan->vDivPrio ) > 0.0; i++ )      {          int iDiv = Vec_QuePop( pFxchMan->vDivPrio ); @@ -70,6 +193,7 @@ int Fxch_FastExtract( Vec_Wec_t* vCubes,          Fxch_ManUpdate( pFxchMan, iDiv );      } +         pFxchMan->timeExt = Abc_Clock() - TempTime;      if ( fVerbose ) @@ -80,9 +204,12 @@ int Fxch_FastExtract( Vec_Wec_t* vCubes,          Abc_PrintTime( 1, "[FXCH]    +-> Extr", pFxchMan->timeExt );      } +    Fxch_CubesUnGruping( pFxchMan );      Fxch_ManSCHashTablesFree( pFxchMan );      Fxch_ManFree( pFxchMan ); +      Vec_WecRemoveEmpty( vCubes ); +    Vec_WecSortByFirstInt( vCubes, 0 );      return 1;  } diff --git a/src/opt/fxch/Fxch.h b/src/opt/fxch/Fxch.h index 5781846c..8291e042 100644 --- a/src/opt/fxch/Fxch.h +++ b/src/opt/fxch/Fxch.h @@ -28,6 +28,9 @@  ABC_NAMESPACE_HEADER_START +typedef unsigned char uint8_t; +typedef unsigned int  uint32_t; +  ////////////////////////////////////////////////////////////////////////  ///                    TYPEDEF DECLARATIONS                          ///  //////////////////////////////////////////////////////////////////////// @@ -52,25 +55,22 @@ typedef struct Fxch_SCHashTable_Entry_t_ Fxch_SCHashTable_Entry_t;   *   its literals.   *   */ +  struct Fxch_SubCube_t_  { -    unsigned int Id, -                 iCube; -    unsigned int iLit0 : 16, -                 iLit1 : 16; +    uint32_t Id, +             iCube; +    uint32_t iLit0 : 16, +             iLit1 : 16;  };  /* Sub-cube Hash Table - *   */  struct Fxch_SCHashTable_Entry_t_  { -    Fxch_SubCube_t SCData; - -    unsigned int iTable : 31, -                 Used   :  1; -    unsigned int iPrev, -                 iNext; +    Fxch_SubCube_t* vSCData; +    uint32_t Size : 16, +             Cap : 16;  };  struct Fxch_SCHashTable_t_ @@ -80,7 +80,6 @@ struct Fxch_SCHashTable_t_      Fxch_SCHashTable_Entry_t* pBins;      unsigned int nEntries,                   SizeMask; -    Vec_Int_t*   vCubeLinks;      /* Temporary data */      Vec_Int_t    vSubCube0; @@ -91,6 +90,7 @@ struct Fxch_Man_t_  {      /* user's data */      Vec_Wec_t* vCubes; +    int nCubesInit;      int LitCountMax;      /* internal data */ @@ -107,12 +107,21 @@ struct Fxch_Man_t_      Vec_Int_t*    vLevels;       /* variable levels */ +    // Cube Grouping +    Vec_Int_t* vTranslation; +    Vec_Int_t* vOutputID; +    int* pTempOutputID; +    int  nSizeOutputID; +      // temporary data to update the data-structure when a divisor is extracted -    Vec_Int_t*     vCubesS;     /* cubes for the given single cube divisor */ -    Vec_Int_t*     vPairs;     /* cube pairs for the given double cube divisor */ -    Vec_Int_t*     vCubeFree;  // cube-free divisor -    Vec_Int_t*     vDiv;       // selected divisor -    Vec_Int_t*     vSCC; +    Vec_Int_t* vCubesS;    /* cubes for the given single cube divisor */ +    Vec_Int_t* vPairs;     /* cube pairs for the given double cube divisor */ +    Vec_Int_t* vCubeFree;  // cube-free divisor +    Vec_Int_t* vDiv;       // selected divisor + +    Vec_Int_t* vCubesToRemove; +    Vec_Int_t* vCubesToUpdate; +    Vec_Int_t* vSCC;      /* Statistics */      abctime timeInit;   /* Initialization time */ @@ -135,6 +144,15 @@ extern Vec_Wec_t* Abc_NtkFxRetrieve( Abc_Ntk_t* pNtk );  extern void       Abc_NtkFxInsert( Abc_Ntk_t* pNtk, Vec_Wec_t* vCubes );  extern int        Abc_NtkFxCheck( Abc_Ntk_t* pNtk ); +static inline int Fxch_CountOnes( unsigned num ) +{ +    num = ( num & 0x55555555 ) + ( ( num >> 1) & 0x55555555 ); +    num = ( num & 0x33333333 ) + ( ( num >> 2) & 0x33333333 ); +    num = ( num & 0x0F0F0F0F ) + ( ( num >> 4) & 0x0F0F0F0F ); +    num = ( num & 0x00FF00FF ) + ( ( num >> 8) & 0x00FF00FF ); +    return  ( num & 0x0000FFFF ) + ( num >> 16 ); +} +  /*===== Fxch.c =======================================================*/  int Abc_NtkFxchPerform( Abc_Ntk_t* pNtk, int nMaxDivExt, int fVerbose, int fVeryVerbose );  int Fxch_FastExtract( Vec_Wec_t* vCubes, int ObjIdMax, int nMaxDivExt, int fVerbose, int fVeryVerbose ); @@ -177,26 +195,25 @@ static inline int Fxch_ManGetLit( Fxch_Man_t* pFxchMan,  }  /*===== FxchSCHashTable.c ============================================*/ -Fxch_SCHashTable_t* Fxch_SCHashTableCreate( Fxch_Man_t* pFxchMan, Vec_Int_t* vCubeLinks, int nEntries ); +Fxch_SCHashTable_t* Fxch_SCHashTableCreate( Fxch_Man_t* pFxchMan, int nEntries );  void Fxch_SCHashTableDelete( Fxch_SCHashTable_t* );  int Fxch_SCHashTableInsert( Fxch_SCHashTable_t* pSCHashTable,                              Vec_Wec_t* vCubes, -                            unsigned int SubCubeID, -                            unsigned int iSubCube, -                            unsigned int iCube, -                            unsigned int iLit0, -                            unsigned int iLit1, +                            uint32_t SubCubeID, +                            uint32_t iCube, +                            uint32_t iLit0, +                            uint32_t iLit1,                              char fUpdate ); +  int Fxch_SCHashTableRemove( Fxch_SCHashTable_t* pSCHashTable,                              Vec_Wec_t* vCubes, -                            unsigned int SubCubeID, -                            unsigned int iSubCube, -                            unsigned int iCube, -                            unsigned int iLit0, -                            unsigned int iLit1, +                            uint32_t SubCubeID, +                            uint32_t iCube, +                            uint32_t iLit0, +                            uint32_t iLit1,                              char fUpdate );  unsigned int Fxch_SCHashTableMemory( Fxch_SCHashTable_t* ); diff --git a/src/opt/fxch/FxchDiv.c b/src/opt/fxch/FxchDiv.c index 18c8bbfb..99c260c6 100644 --- a/src/opt/fxch/FxchDiv.c +++ b/src/opt/fxch/FxchDiv.c @@ -142,10 +142,20 @@ int Fxch_DivCreate( Fxch_Man_t* pFxchMan,          SC0_Lit1 = Fxch_ManGetLit( pFxchMan, pSubCube0->iCube, pSubCube0->iLit1 );          SC1_Lit1 = Fxch_ManGetLit( pFxchMan, pSubCube1->iCube, pSubCube1->iLit1 ); -        Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit0, 0 ) ); -        Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit0, 1 ) ); -        Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit1, 0 ) ); -        Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit1, 1 ) ); +        if ( SC0_Lit0 < SC1_Lit0 ) +        { +            Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit0, 0 ) ); +            Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit0, 1 ) ); +            Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit1, 0 ) ); +            Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit1, 1 ) ); +        } +        else +        { +            Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit0, 0 ) ); +            Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit0, 1 ) ); +            Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit1, 0 ) ); +            Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit1, 1 ) ); +        }          RetValue = Fxch_DivNormalize( pFxchMan->vCubeFree );          if ( RetValue == -1 ) diff --git a/src/opt/fxch/FxchMan.c b/src/opt/fxch/FxchMan.c index 44695f91..19ce1461 100644 --- a/src/opt/fxch/FxchMan.c +++ b/src/opt/fxch/FxchMan.c @@ -15,7 +15,6 @@    Revision    []  ***********************************************************************/ -  #include "Fxch.h"  ABC_NAMESPACE_IMPL_START @@ -25,7 +24,6 @@ ABC_NAMESPACE_IMPL_START  ////////////////////////////////////////////////////////////////////////  static inline int Fxch_ManSCAddRemove( Fxch_Man_t* pFxchMan,                                         unsigned int SubCubeID, -                                       unsigned int iSubCube,                                         unsigned int iCube,                                         unsigned int iLit0,                                         unsigned int iLit1, @@ -37,13 +35,13 @@ static inline int Fxch_ManSCAddRemove( Fxch_Man_t* pFxchMan,      if ( fAdd )      {          ret = Fxch_SCHashTableInsert( pFxchMan->pSCHashTable, pFxchMan->vCubes, -                                      SubCubeID, iSubCube, +                                      SubCubeID,                                        iCube, iLit0, iLit1, fUpdate );      }      else      {          ret = Fxch_SCHashTableRemove( pFxchMan->pSCHashTable, pFxchMan->vCubes, -                                      SubCubeID, iSubCube, +                                      SubCubeID,                                        iCube, iLit0, iLit1, fUpdate );      } @@ -63,26 +61,38 @@ static inline int Fxch_ManDivSingleCube( Fxch_Man_t* pFxchMan,          fSingleCube = 1,          fBase = 0; -    if ( Vec_IntSize(vCube) < 2 ) +    if ( Vec_IntSize( vCube ) < 2 )          return 0;      Vec_IntForEachEntryStart( vCube, Lit0, i, 1)      Vec_IntForEachEntryStart( vCube, Lit1, k, (i + 1) )      { +        int * pOutputID, nOnes, j, z;          assert( Lit0 < Lit1 );          Vec_IntClear( pFxchMan->vCubeFree );          Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( Abc_LitNot( Lit0 ), 0 ) );          Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( Abc_LitNot( Lit1 ), 1 ) ); +        pOutputID = Vec_IntEntryP( pFxchMan->vOutputID, iCube * pFxchMan->nSizeOutputID ); +        nOnes = 0; + +        for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) +            nOnes += Fxch_CountOnes( pOutputID[j] ); + +        if ( nOnes == 0 ) +            nOnes = 1; +          if (fAdd)          { -            Fxch_DivAdd( pFxchMan, fUpdate, fSingleCube, fBase ); +            for ( z = 0; z < nOnes; z++ ) +                Fxch_DivAdd( pFxchMan, fUpdate, fSingleCube, fBase );              pFxchMan->nPairsS++;          }          else          { -            Fxch_DivRemove( pFxchMan, fUpdate, fSingleCube, fBase ); +            for ( z = 0; z < nOnes; z++ ) +                Fxch_DivRemove( pFxchMan, fUpdate, fSingleCube, fBase );              pFxchMan->nPairsS--;          }      } @@ -98,15 +108,13 @@ static inline void Fxch_ManDivDoubleCube( Fxch_Man_t* pFxchMan,      Vec_Int_t* vLitHashKeys = pFxchMan->vLitHashKeys,               * vCube = Vec_WecEntry( pFxchMan->vCubes, iCube );      int SubCubeID = 0, -        nHashedSC = 0,          iLit0,          Lit0;      Vec_IntForEachEntryStart( vCube, Lit0, iLit0, 1)          SubCubeID += Vec_IntEntry( vLitHashKeys, Lit0 ); -    Fxch_ManSCAddRemove( pFxchMan, -                         SubCubeID, nHashedSC++, +    Fxch_ManSCAddRemove( pFxchMan, SubCubeID,                           iCube, 0, 0,                           (char)fAdd, (char)fUpdate ); @@ -115,8 +123,7 @@ static inline void Fxch_ManDivDoubleCube( Fxch_Man_t* pFxchMan,          /* 1 Lit remove */          SubCubeID -= Vec_IntEntry( vLitHashKeys, Lit0 ); -        pFxchMan->nPairsD += Fxch_ManSCAddRemove( pFxchMan, -                                                  SubCubeID, nHashedSC++, +        pFxchMan->nPairsD += Fxch_ManSCAddRemove( pFxchMan, SubCubeID,                                                    iCube, iLit0, 0,                                                    (char)fAdd, (char)fUpdate ); @@ -130,8 +137,7 @@ static inline void Fxch_ManDivDoubleCube( Fxch_Man_t* pFxchMan,                  /* 2 Lit remove */                  SubCubeID -= Vec_IntEntry( vLitHashKeys, Lit1 ); -                pFxchMan->nPairsD += Fxch_ManSCAddRemove( pFxchMan, -                                                          SubCubeID, nHashedSC++, +                pFxchMan->nPairsD += Fxch_ManSCAddRemove( pFxchMan, SubCubeID,                                                            iCube, iLit0, iLit1,                                                            (char)fAdd, (char)fUpdate ); @@ -165,14 +171,20 @@ Fxch_Man_t* Fxch_ManAlloc( Vec_Wec_t* vCubes )      Fxch_Man_t* pFxchMan = ABC_CALLOC( Fxch_Man_t, 1 );      pFxchMan->vCubes = vCubes; -    pFxchMan->pDivHash = Hsh_VecManStart( 1000 ); -    pFxchMan->vDivWeights = Vec_FltAlloc( 1000 ); -    pFxchMan->vDivCubePairs = Vec_WecAlloc( 1000 ); -    pFxchMan->vCubeFree = Vec_IntAlloc( 100 ); -    pFxchMan->vDiv = Vec_IntAlloc( 100 ); +    pFxchMan->nCubesInit = Vec_WecSize( vCubes ); + +    pFxchMan->pDivHash = Hsh_VecManStart( 1024 ); +    pFxchMan->vDivWeights = Vec_FltAlloc( 1024 ); +    pFxchMan->vDivCubePairs = Vec_WecAlloc( 1024 ); + +    pFxchMan->vCubeFree = Vec_IntAlloc( 4 ); +    pFxchMan->vDiv = Vec_IntAlloc( 4 ); + +    pFxchMan->vCubesS = Vec_IntAlloc( 128 ); +    pFxchMan->vPairs = Vec_IntAlloc( 128 ); +    pFxchMan->vCubesToUpdate = Vec_IntAlloc( 64 ); +    pFxchMan->vCubesToRemove = Vec_IntAlloc( 64 );      pFxchMan->vSCC = Vec_IntAlloc( 64 ); -    pFxchMan->vCubesS = Vec_IntAlloc( 100 ); -    pFxchMan->vPairs = Vec_IntAlloc( 100 );      return pFxchMan;  } @@ -187,11 +199,16 @@ void Fxch_ManFree( Fxch_Man_t* pFxchMan )      Vec_QueFree( pFxchMan->vDivPrio );      Vec_WecFree( pFxchMan->vDivCubePairs );      Vec_IntFree( pFxchMan->vLevels ); +      Vec_IntFree( pFxchMan->vCubeFree );      Vec_IntFree( pFxchMan->vDiv ); -    Vec_IntFree( pFxchMan->vSCC ); +      Vec_IntFree( pFxchMan->vCubesS );      Vec_IntFree( pFxchMan->vPairs ); +    Vec_IntFree( pFxchMan->vCubesToUpdate ); +    Vec_IntFree( pFxchMan->vCubesToRemove ); +    Vec_IntFree( pFxchMan->vSCC ); +      ABC_FREE( pFxchMan );  } @@ -248,22 +265,19 @@ void Fxch_ManGenerateLitHashKeys( Fxch_Man_t* pFxchMan )  void Fxch_ManSCHashTablesInit( Fxch_Man_t* pFxchMan )  {      Vec_Wec_t* vCubes = pFxchMan->vCubes; -    Vec_Int_t* vCube, -             * vCubeLinks; +    Vec_Int_t* vCube;      int iCube,          nTotalHashed = 0; -    vCubeLinks = Vec_IntAlloc( Vec_WecSize( vCubes ) + 1 );      Vec_WecForEachLevel( vCubes, vCube, iCube )      {          int nLits = Vec_IntSize( vCube ) - 1,              nSubCubes = nLits <= 2? nLits + 1: ( nLits * nLits + nLits ) / 2; -        Vec_IntPush( vCubeLinks, ( nTotalHashed + 1 ) );          nTotalHashed += nSubCubes + 1;      } -    pFxchMan->pSCHashTable = Fxch_SCHashTableCreate( pFxchMan, vCubeLinks, nTotalHashed ); +    pFxchMan->pSCHashTable = Fxch_SCHashTableCreate( pFxchMan, nTotalHashed );  }  void Fxch_ManSCHashTablesFree( Fxch_Man_t* pFxchMan ) @@ -364,56 +378,135 @@ static inline void Fxch_ManExtractDivFromCube( Fxch_Man_t* pFxchMan,          Vec_IntPush( vCube0, Abc_Var2Lit( iVarNew, 0 ) );          Vec_IntPush( vLitP, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); +        Vec_IntPush( pFxchMan->vCubesToUpdate, iCube0 );          pFxchMan->nLits--;      }  }  /* Extract divisor from cube pairs */ -static inline int Fxch_ManExtractDivFromCubePairs( Fxch_Man_t* pFxchMan, +static inline void Fxch_ManExtractDivFromCubePairs( Fxch_Man_t* pFxchMan,                                                     const int iVarNew )  {      /* For each pair (Ci, Cj) */ -    int k = 0, -        iCube0, iCube1, i; +    int iCube0, iCube1, i; -    Vec_Int_t* vLitP = Vec_WecEntry( pFxchMan->vLits, Vec_WecSize( pFxchMan->vLits ) - 2 ), -             * vLitN = Vec_WecEntry( pFxchMan->vLits, Vec_WecSize( pFxchMan->vLits ) - 1 );      Vec_IntForEachEntryDouble( pFxchMan->vPairs, iCube0, iCube1, i )      { -        int RetValue,   +        int j, Lit, +            RetValue,                fCompl = 0; +        int * pOutputID0, * pOutputID1; -        Vec_Int_t* vCube0 = Fxch_ManGetCube( pFxchMan, iCube0 ), -                 * vCube1 = Fxch_ManGetCube( pFxchMan, iCube1 ); +        Vec_Int_t* vCube = NULL, +                 * vCube0 = Fxch_ManGetCube( pFxchMan, iCube0 ), +                 * vCube1 = Fxch_ManGetCube( pFxchMan, iCube1 ), +                 * vCube0Copy = Vec_IntDup( vCube0 ), +                 * vCube1Copy = Vec_IntDup( vCube1 ); -        RetValue  = Fxch_DivRemoveLits( vCube0, vCube1, pFxchMan->vDiv, &fCompl ); +        RetValue  = Fxch_DivRemoveLits( vCube0Copy, vCube1Copy, pFxchMan->vDiv, &fCompl );          assert( RetValue == Vec_IntSize( pFxchMan->vDiv ) );          pFxchMan->nLits -= Vec_IntSize( pFxchMan->vDiv ) + Vec_IntSize( vCube1 ) - 2; -        /* Remove second cube */ -        Vec_IntClear( vCube1 ); -        Vec_IntWriteEntry( pFxchMan->vPairs, k++, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); +        /* Identify type of Extraction */ +        pOutputID0 = Vec_IntEntryP( pFxchMan->vOutputID, iCube0 * pFxchMan->nSizeOutputID ); +        pOutputID1 = Vec_IntEntryP( pFxchMan->vOutputID, iCube1 * pFxchMan->nSizeOutputID ); +        RetValue = 1; +        for ( j = 0; j < pFxchMan->nSizeOutputID && RetValue; j++ ) +            RetValue = ( pOutputID0[j] == pOutputID1[j] ); + +        /* Exact Extractraion */ +        if ( RetValue ) +        { +            Vec_IntClear( vCube0 ); +            Vec_IntAppend( vCube0, vCube0Copy ); +            vCube = vCube0; + +            Vec_IntPush( pFxchMan->vCubesToUpdate, iCube0 ); +            Vec_IntClear( vCube1 ); + +            /* Update Lit -> Cube mapping */ +            Vec_IntForEachEntry( pFxchMan->vDiv, Lit, j ) +            { +                Vec_IntRemove( Vec_WecEntry( pFxchMan->vLits, Abc_Lit2Var( Lit ) ),  +                               Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); +                Vec_IntRemove( Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Abc_Lit2Var( Lit ) ) ),  +                               Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); +            } + +        } +        /* Unexact Extraction */ +        else +        { +            for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) +                pFxchMan->pTempOutputID[j] = ( pOutputID0[j] & pOutputID1[j] ); + +            /* Create new cube */ +            vCube = Vec_WecPushLevel( pFxchMan->vCubes ); +            Vec_IntAppend( vCube, vCube0Copy ); +            Vec_IntPushArray( pFxchMan->vOutputID, pFxchMan->pTempOutputID, pFxchMan->nSizeOutputID );  +            Vec_IntPush( pFxchMan->vCubesToUpdate, Vec_WecLevelId( pFxchMan->vCubes, vCube ) ); + +            /* Update Lit -> Cube mapping */ +            Vec_IntForEachEntryStart( vCube, Lit, j, 1 ) +                Vec_WecPush( pFxchMan->vLits, Lit, Vec_WecLevelId( pFxchMan->vCubes, vCube ) ); + +            /*********************************************************/ +            RetValue = 0; +            for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) +            { +                pFxchMan->pTempOutputID[j] = pOutputID0[j]; +                RetValue |= ( pOutputID0[j] & ~( pOutputID1[j] ) ); +                pOutputID0[j] &= ~( pOutputID1[j] ); +            } + +            if ( RetValue != 0 ) +                Vec_IntPush( pFxchMan->vCubesToUpdate, iCube0 ); +            else +                Vec_IntClear( vCube0 ); + +            /*********************************************************/ +            RetValue = 0; +            for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) +            { +                RetValue |= ( pOutputID1[j] & ~( pFxchMan->pTempOutputID[j] ) ); +                pOutputID1[j] &= ~( pFxchMan->pTempOutputID[j] ); +            } + +            if ( RetValue != 0 ) +                Vec_IntPush( pFxchMan->vCubesToUpdate, iCube1 ); +            else +                Vec_IntClear( vCube1 ); + +        } +        Vec_IntFree( vCube0Copy ); +        Vec_IntFree( vCube1Copy );          if ( iVarNew )          { +            Vec_Int_t* vLitP = Vec_WecEntry( pFxchMan->vLits, Vec_WecSize( pFxchMan->vLits ) - 2 ), +                     * vLitN = Vec_WecEntry( pFxchMan->vLits, Vec_WecSize( pFxchMan->vLits ) - 1 ); +  +            assert( vCube );              if ( Vec_IntSize( pFxchMan->vDiv ) == 2 || fCompl )              { -                Vec_IntPush( vCube0, Abc_Var2Lit( iVarNew, 1 ) ); -                Vec_IntPush( vLitN, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); +                Vec_IntPush( vCube, Abc_Var2Lit( iVarNew, 1 ) ); +                Vec_IntPush( vLitN, Vec_WecLevelId( pFxchMan->vCubes, vCube ) ); +                Vec_IntSort( vLitN, 0 );              }              else              { -                Vec_IntPush( vCube0, Abc_Var2Lit( iVarNew, 0 ) ); -                Vec_IntPush( vLitP, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); +                Vec_IntPush( vCube, Abc_Var2Lit( iVarNew, 0 ) ); +                Vec_IntPush( vLitP, Vec_WecLevelId( pFxchMan->vCubes, vCube ) ); +                Vec_IntSort( vLitP, 0 );              }          }      } -    return k; +    return;  }  static inline int Fxch_ManCreateCube( Fxch_Man_t* pFxchMan, @@ -421,7 +514,8 @@ static inline int Fxch_ManCreateCube( Fxch_Man_t* pFxchMan,                                        int Lit1 )  {      int Level, -        iVarNew; +        iVarNew,  +        j;      Vec_Int_t* vCube0,               * vCube1; @@ -429,6 +523,10 @@ static inline int Fxch_ManCreateCube( Fxch_Man_t* pFxchMan,      iVarNew = pFxchMan->nVars;      pFxchMan->nVars++; +    /* Clear temporary outputID vector */ +    for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) +        pFxchMan->pTempOutputID[j] = 0; +          /* Create new Lit hash keys */      Vec_IntPush( pFxchMan->vLitHashKeys, Gia_ManRandom(0) & 0x3FFFFFF );      Vec_IntPush( pFxchMan->vLitHashKeys, Gia_ManRandom(0) & 0x3FFFFFF ); @@ -436,6 +534,7 @@ static inline int Fxch_ManCreateCube( Fxch_Man_t* pFxchMan,      /* Create new Cube */      vCube0 = Vec_WecPushLevel( pFxchMan->vCubes );      Vec_IntPush( vCube0, iVarNew ); +    Vec_IntPushArray( pFxchMan->vOutputID, pFxchMan->pTempOutputID, pFxchMan->nSizeOutputID );      if ( Vec_IntSize( pFxchMan->vDiv ) == 2 )      { @@ -448,12 +547,27 @@ static inline int Fxch_ManCreateCube( Fxch_Man_t* pFxchMan,      }      else      { +        int i; +        int Lit; +          vCube1 = Vec_WecPushLevel( pFxchMan->vCubes ); -        vCube0 = Fxch_ManGetCube( pFxchMan, Vec_WecSize( pFxchMan->vCubes ) - 2 );          Vec_IntPush( vCube1, iVarNew ); +        Vec_IntPushArray( pFxchMan->vOutputID, pFxchMan->pTempOutputID, pFxchMan->nSizeOutputID ); + +        vCube0 = Fxch_ManGetCube( pFxchMan, Vec_WecSize( pFxchMan->vCubes ) - 2 );          Fxch_DivSepareteCubes( pFxchMan->vDiv, vCube0, vCube1 );          Level = 2 + Abc_MaxInt( Fxch_ManComputeLevelCube( pFxchMan, vCube0 ),                                  Fxch_ManComputeLevelCube( pFxchMan, vCube1 ) ); + +        Vec_IntPush( pFxchMan->vCubesToUpdate, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); +        Vec_IntPush( pFxchMan->vCubesToUpdate, Vec_WecLevelId( pFxchMan->vCubes, vCube1 ) ); + +        /* Update Lit -> Cube mapping */ +        Vec_IntForEachEntryStart( vCube0, Lit, i, 1 ) +            Vec_WecPush( pFxchMan->vLits, Lit, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); + +        Vec_IntForEachEntryStart( vCube1, Lit, i, 1 ) +            Vec_WecPush( pFxchMan->vLits, Lit, Vec_WecLevelId( pFxchMan->vCubes, vCube1 ) );      }      assert( Vec_IntSize( pFxchMan->vLevels ) == iVarNew );      Vec_IntPush( pFxchMan->vLevels, Level ); @@ -470,7 +584,7 @@ static inline int Fxch_ManCreateCube( Fxch_Man_t* pFxchMan,  void Fxch_ManUpdate( Fxch_Man_t* pFxchMan,                       int iDiv )  { -    int i, k, iCube0, iCube1, +    int i, iCube0, iCube1,          Lit0 = -1,          Lit1 = -1,          iVarNew; @@ -519,89 +633,128 @@ void Fxch_ManUpdate( Fxch_Man_t* pFxchMan,      /* subtract cost of single-cube divisors */      Vec_IntForEachEntry( pFxchMan->vCubesS, iCube0, i ) -        Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1); /* remove (fAdd = 0) - fUpdate = 1 */ - -    Vec_IntForEachEntryDouble( pFxchMan->vPairs, iCube0, iCube1, i ) -        Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1), /* remove (fAdd = 0) - fUpdate = 1 */ -        Fxch_ManDivSingleCube( pFxchMan, iCube1, 0, 1); /* remove (fAdd = 0) - fUpdate = 1 */ +    { +        Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1); -    /* subtract cost of double-cube divisors */ -    Vec_IntForEachEntry( pFxchMan->vCubesS, iCube0, i ) -        if ( iCube0 < Vec_IntSize(pFxchMan->pSCHashTable->vCubeLinks) ) -            Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 ); /* remove (fAdd = 0) - fUpdate = 1 */ +        if ( Vec_WecEntryEntry( pFxchMan->vCubes, iCube0, 0 ) == 0 ) +            Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 ); +    }      Vec_IntForEachEntry( pFxchMan->vPairs, iCube0, i ) -        if ( iCube0 < Vec_IntSize(pFxchMan->pSCHashTable->vCubeLinks) ) -            Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 ); /* remove (fAdd = 0) - fUpdate = 1 */ +    { +        Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1); -    k = 0; +        if ( Vec_WecEntryEntry( pFxchMan->vCubes, iCube0, 0 ) == 0 ) +            Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 ); +    } + +    Vec_IntClear( pFxchMan->vCubesToUpdate );      if ( Fxch_DivIsNotConstant1( pFxchMan->vDiv ) )      {          iVarNew = Fxch_ManCreateCube( pFxchMan, Lit0, Lit1 );          Fxch_ManExtractDivFromCube( pFxchMan, Lit0, Lit1, iVarNew ); -        k = Fxch_ManExtractDivFromCubePairs( pFxchMan, iVarNew ); +        Fxch_ManExtractDivFromCubePairs( pFxchMan, iVarNew );      }      else -        k = Fxch_ManExtractDivFromCubePairs( pFxchMan, 0 ); +        Fxch_ManExtractDivFromCubePairs( pFxchMan, 0 ); -    assert( k == Vec_IntSize( pFxchMan->vPairs ) / 2 ); -    Vec_IntShrink( pFxchMan->vPairs, k ); - -    /* Add cost of single-cube divisors */ -    Vec_IntForEachEntry( pFxchMan->vCubesS, iCube0, i ) -        Fxch_ManDivSingleCube( pFxchMan, iCube0, 1, 1 ); /* fAdd = 1 - fUpdate = 1 */ - -    Vec_IntForEachEntry( pFxchMan->vPairs, iCube0, i ) -        Fxch_ManDivSingleCube( pFxchMan, iCube0, 1, 1 ); /* fAdd = 1 - fUpdate = 1 */ +    assert( Vec_IntSize( pFxchMan->vCubesToUpdate ) ); -    /* Add cost of double-cube divisors */ -    Vec_IntForEachEntry( pFxchMan->vCubesS, iCube0, i ) -        if ( iCube0 < Vec_IntSize(pFxchMan->pSCHashTable->vCubeLinks) ) -            Fxch_ManDivDoubleCube( pFxchMan, iCube0, 1, 1 ); /* fAdd = 1 - fUpdate = 1 */ +    /* Add cost */ +    Vec_IntForEachEntry( pFxchMan->vCubesToUpdate, iCube0, i ) +    { +        Fxch_ManDivSingleCube( pFxchMan, iCube0, 1, 1 ); -    Vec_IntForEachEntry( pFxchMan->vPairs, iCube0, i ) -        if ( iCube0 < Vec_IntSize(pFxchMan->pSCHashTable->vCubeLinks) ) -            Fxch_ManDivDoubleCube( pFxchMan, iCube0, 1, 1 ); /* fAdd = 1 - fUpdate = 1 */ +        if ( Vec_WecEntryEntry( pFxchMan->vCubes, iCube0, 0 ) == 0 ) +            Fxch_ManDivDoubleCube( pFxchMan, iCube0, 1, 1 ); +    }      /* Deal with SCC */ -    if ( Vec_IntSize( pFxchMan->vSCC ) ) +    if ( Vec_IntSize( pFxchMan->vSCC ) && pFxchMan->nExtDivs < 17 )      { -        Vec_IntUniqify( pFxchMan->vSCC ); -        Vec_IntForEachEntry( pFxchMan->vSCC, iCube0, i ) -            if ( iCube0 < Vec_IntSize(pFxchMan->pSCHashTable->vCubeLinks) ) +        Vec_IntUniqifyPairs( pFxchMan->vSCC ); +        assert( Vec_IntSize( pFxchMan->vSCC ) % 2 == 0 ); + +        Vec_IntForEachEntryDouble( pFxchMan->vSCC, iCube0, iCube1, i ) +        { +            int j, RetValue = 1; +            int* pOutputID0 = Vec_IntEntryP( pFxchMan->vOutputID, iCube0 * pFxchMan->nSizeOutputID ); +            int* pOutputID1 = Vec_IntEntryP( pFxchMan->vOutputID, iCube1 * pFxchMan->nSizeOutputID ); +            vCube0 = Vec_WecEntry( pFxchMan->vCubes, iCube0 ); +            vCube1 = Vec_WecEntry( pFxchMan->vCubes, iCube1 ); + +            if ( !Vec_WecIntHasMark( vCube0 ) )              { -                Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 ); /* remove (fAdd = 0) - fUpdate = 1 */ -                vCube0 = Fxch_ManGetCube( pFxchMan, iCube0 ), -                Vec_IntClear( vCube0 ); +                Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1 ); +                Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 ); +                Vec_WecIntSetMark( vCube0 );              } -        Vec_IntClear( pFxchMan->vSCC ); -    } +            if ( !Vec_WecIntHasMark( vCube1 ) ) +            { +                Fxch_ManDivSingleCube( pFxchMan, iCube1, 0, 1 ); +                Fxch_ManDivDoubleCube( pFxchMan, iCube1, 0, 1 ); +                Vec_WecIntSetMark( vCube1 ); +            } +            if ( Vec_IntSize( vCube0 ) == Vec_IntSize( vCube1 ) ) +            { +                for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) +                { +                    pOutputID1[j] |= pOutputID0[j]; +                    pOutputID0[j] = 0; +                } +                Vec_IntClear( Vec_WecEntry( pFxchMan->vCubes, iCube0 ) ); +                Vec_WecIntXorMark( vCube0 ); +                continue; +            } -    /* If it's a double-cube devisor add its cost */ -    if ( Vec_IntSize( pFxchMan->vDiv ) > 2 ) -    { -        iCube0 = Vec_WecSize( pFxchMan->vCubes ) - 2; -        iCube1 = Vec_WecSize( pFxchMan->vCubes ) - 1; +            for ( j = 0; j < pFxchMan->nSizeOutputID && RetValue; j++ ) +                RetValue = ( pOutputID0[j] == pOutputID1[j] ); -        Fxch_ManDivSingleCube( pFxchMan, iCube0, 1, 1 );  /* fAdd = 1 - fUpdate = 1 */ -        Fxch_ManDivSingleCube( pFxchMan, iCube1, 1, 1 );  /* fAdd = 1 - fUpdate = 1 */ +            if ( RetValue ) +            { +                Vec_IntClear( Vec_WecEntry( pFxchMan->vCubes, iCube0 ) ); +                Vec_WecIntXorMark( vCube0 ); +            } +            else +            { +                RetValue = 0; +                for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) +                { +                    RetValue |= ( pOutputID0[j] & ~( pOutputID1[j] ) ); +                    pOutputID0[j] &= ~( pOutputID1[j] ); +                } + +                if ( RetValue == 0 ) +                { +                    Vec_IntClear( Vec_WecEntry( pFxchMan->vCubes, iCube0 ) ); +                    Vec_WecIntXorMark( vCube0 ); +                } +            } +        } -        vCube0 = Vec_WecEntry( pFxchMan->vCubes, iCube0 ); -        Vec_IntForEachEntryStart( vCube0, Lit0, i, 1 ) -            Vec_WecPush( pFxchMan->vLits, Lit0, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); +        Vec_IntForEachEntryDouble( pFxchMan->vSCC, iCube0, iCube1, i ) +        { +            vCube0 = Vec_WecEntry( pFxchMan->vCubes, iCube0 ); +            vCube1 = Vec_WecEntry( pFxchMan->vCubes, iCube1 ); -        vCube1 = Vec_WecEntry( pFxchMan->vCubes, iCube1 ); -        Vec_IntForEachEntryStart( vCube1, Lit0, i, 1 ) -            Vec_WecPush( pFxchMan->vLits, Lit0, Vec_WecLevelId( pFxchMan->vCubes, vCube1 ) ); -    } +            if ( Vec_WecIntHasMark( vCube0 ) ) +            { +                Fxch_ManDivSingleCube( pFxchMan, iCube0, 1, 1 ); +                Fxch_ManDivDoubleCube( pFxchMan, iCube0, 1, 1 ); +                Vec_WecIntXorMark( vCube0 ); +            } -    /* remove these cubes from the lit array of the divisor */ -    Vec_IntForEachEntry( pFxchMan->vDiv, Lit0, i ) -    { -        Vec_IntTwoRemove( Vec_WecEntry( pFxchMan->vLits, Abc_Lit2Var( Lit0 ) ), pFxchMan->vPairs ); -        Vec_IntTwoRemove( Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Abc_Lit2Var( Lit0 ) ) ), pFxchMan->vPairs ); +            if ( Vec_WecIntHasMark( vCube1 ) ) +            { +                Fxch_ManDivSingleCube( pFxchMan, iCube1, 1, 1 ); +                Fxch_ManDivDoubleCube( pFxchMan, iCube1, 1, 1 ); +                Vec_WecIntXorMark( vCube1 ); +            } +        } + +        Vec_IntClear( pFxchMan->vSCC );      }      pFxchMan->nExtDivs++; diff --git a/src/opt/fxch/FxchSCHashTable.c b/src/opt/fxch/FxchSCHashTable.c index a37009eb..0796a28c 100644 --- a/src/opt/fxch/FxchSCHashTable.c +++ b/src/opt/fxch/FxchSCHashTable.c @@ -19,11 +19,6 @@  ABC_NAMESPACE_IMPL_START -//#ifdef _WIN32 -typedef unsigned int uint32_t; -typedef unsigned char uint8_t; -//#endif -  ////////////////////////////////////////////////////////////////////////  ///                     FUNCTION DEFINITIONS                         ///  //////////////////////////////////////////////////////////////////////// @@ -92,7 +87,6 @@ static inline void MurmurHash3_x86_32 ( const void* key,  }  Fxch_SCHashTable_t* Fxch_SCHashTableCreate( Fxch_Man_t* pFxchMan, -                                            Vec_Int_t* vCubeLinks,                                              int nEntries )  {      Fxch_SCHashTable_t* pSCHashTable = ABC_CALLOC( Fxch_SCHashTable_t, 1 ); @@ -101,7 +95,6 @@ Fxch_SCHashTable_t* Fxch_SCHashTableCreate( Fxch_Man_t* pFxchMan,      pSCHashTable->pFxchMan = pFxchMan;      pSCHashTable->SizeMask = (1 << nBits) - 1; -    pSCHashTable->vCubeLinks = vCubeLinks;      pSCHashTable->pBins = ABC_CALLOC( Fxch_SCHashTable_Entry_t, pSCHashTable->SizeMask + 1 );      return pSCHashTable; @@ -109,7 +102,6 @@ Fxch_SCHashTable_t* Fxch_SCHashTableCreate( Fxch_Man_t* pFxchMan,  void Fxch_SCHashTableDelete( Fxch_SCHashTable_t* pSCHashTable )  { -    Vec_IntFree( pSCHashTable->vCubeLinks );      Vec_IntErase( &pSCHashTable->vSubCube0 );      Vec_IntErase( &pSCHashTable->vSubCube1 );      ABC_FREE( pSCHashTable->pBins ); @@ -122,49 +114,6 @@ static inline Fxch_SCHashTable_Entry_t* Fxch_SCHashTableBin( Fxch_SCHashTable_t*      return pSCHashTable->pBins + (SubCubeID & pSCHashTable->SizeMask);  } -static inline Fxch_SCHashTable_Entry_t* Fxch_SCHashTableEntry( Fxch_SCHashTable_t* pSCHashTable, -                                                               unsigned int iEntry ) -{ -    if ( ( iEntry > 0 ) && ( iEntry < ( pSCHashTable->SizeMask + 1 ) ) ) -        return pSCHashTable->pBins + iEntry; - -    return NULL; -} - -static inline void Fxch_SCHashTableInsertLink( Fxch_SCHashTable_t* pSCHashTable, -                                               unsigned int iEntry0, -                                               unsigned int iEntry1 ) -{ -    Fxch_SCHashTable_Entry_t* pEntry0 = Fxch_SCHashTableEntry( pSCHashTable, iEntry0 ), -                            * pEntry1 = Fxch_SCHashTableEntry( pSCHashTable, iEntry1 ), -                            * pEntry0Next = Fxch_SCHashTableEntry( pSCHashTable, pEntry0->iNext ); - -    assert( pEntry0Next->iPrev == iEntry0 ); - -    pEntry1->iNext = pEntry0->iNext; -    pEntry0->iNext = iEntry1; -    pEntry1->iPrev = iEntry0; -    pEntry0Next->iPrev = iEntry1; -} - -static inline void Fxch_SCHashTableRemoveLink( Fxch_SCHashTable_t* pSCHashTable, -                                               int iEntry0, -                                               int iEntry1 ) -{ -    Fxch_SCHashTable_Entry_t* pEntry0 = Fxch_SCHashTableEntry( pSCHashTable, iEntry0 ), -                            * pEntry1 = Fxch_SCHashTableEntry( pSCHashTable, iEntry1 ), -                            * pEntry1Next = Fxch_SCHashTableEntry( pSCHashTable, pEntry1->iNext ); - -    assert( (int)pEntry0->iNext == iEntry1 ); -    assert( (int)pEntry1->iPrev == iEntry0 ); -    assert( (int)pEntry1Next->iPrev == iEntry1 ); - -    pEntry0->iNext = pEntry1->iNext; -    pEntry1->iNext = 0; -    pEntry1Next->iPrev = pEntry1->iPrev; -    pEntry1->iPrev = 0; -} -  static inline int Fxch_SCHashTableEntryCompare( Fxch_SCHashTable_t* pSCHashTable,                                                  Vec_Wec_t* vCubes,                                                  Fxch_SubCube_t* pSCData0, @@ -173,12 +122,22 @@ static inline int Fxch_SCHashTableEntryCompare( Fxch_SCHashTable_t* pSCHashTable      Vec_Int_t* vCube0 = Vec_WecEntry( vCubes, pSCData0->iCube ),               * vCube1 = Vec_WecEntry( vCubes, pSCData1->iCube ); +    int* pOutputID0 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pSCData0->iCube * pSCHashTable->pFxchMan->nSizeOutputID ), +       * pOutputID1 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pSCData1->iCube * pSCHashTable->pFxchMan->nSizeOutputID ); +    int i, Result = 0; +      if ( !Vec_IntSize( vCube0 ) ||           !Vec_IntSize( vCube1 ) ||           Vec_IntEntry( vCube0, 0 ) != Vec_IntEntry( vCube1, 0 ) ||           pSCData0->Id != pSCData1->Id )          return 0; +    for ( i = 0; i < pSCHashTable->pFxchMan->nSizeOutputID && Result == 0; i++ ) +        Result = ( pOutputID0[i] & pOutputID1[i] ); + +    if ( Result == 0 ) +        return 0; +      Vec_IntClear( &pSCHashTable->vSubCube0 );      Vec_IntClear( &pSCHashTable->vSubCube1 ); @@ -189,7 +148,6 @@ static inline int Fxch_SCHashTableEntryCompare( Fxch_SCHashTable_t* pSCHashTable             Vec_IntEntry( vCube0, pSCData0->iLit1 ) == Vec_IntEntry( vCube1, pSCData1->iLit1 ) ) )          return 0; -      if ( pSCData0->iLit0 > 0 )          Vec_IntAppendSkip( &pSCHashTable->vSubCube0, vCube0, pSCData0->iLit0 );      else @@ -200,7 +158,6 @@ static inline int Fxch_SCHashTableEntryCompare( Fxch_SCHashTable_t* pSCHashTable      else          Vec_IntAppend( &pSCHashTable->vSubCube1, vCube1 ); -      if ( pSCData0->iLit1 > 0)          Vec_IntDrop( &pSCHashTable->vSubCube0,                         pSCData0->iLit0 < pSCData0->iLit1 ? pSCData0->iLit1 - 1 : pSCData0->iLit1 ); @@ -209,167 +166,169 @@ static inline int Fxch_SCHashTableEntryCompare( Fxch_SCHashTable_t* pSCHashTable          Vec_IntDrop( &pSCHashTable->vSubCube1,                         pSCData1->iLit0 < pSCData1->iLit1 ? pSCData1->iLit1 - 1 : pSCData1->iLit1 ); -    Vec_IntDrop( &pSCHashTable->vSubCube0, 0 ); -    Vec_IntDrop( &pSCHashTable->vSubCube1, 0 ); -      return Vec_IntEqual( &pSCHashTable->vSubCube0, &pSCHashTable->vSubCube1 );  }  int Fxch_SCHashTableInsert( Fxch_SCHashTable_t* pSCHashTable,                              Vec_Wec_t* vCubes, -                            unsigned int SubCubeID, -                            unsigned int iSubCube, -                            unsigned int iCube, -                            unsigned int iLit0, -                            unsigned int iLit1, +                            uint32_t SubCubeID, +                            uint32_t iCube, +                            uint32_t iLit0, +                            uint32_t iLit1,                              char fUpdate )  { -    unsigned int BinID; -    unsigned int iNewEntry; -    Fxch_SCHashTable_Entry_t* pBin,* pNewEntry; - -    Fxch_SCHashTable_Entry_t* pEntry; -    unsigned int iEntry; -    char Pairs = 0, -         fStart = 1; +    int iNewEntry; +    int Pairs = 0; +    uint32_t BinID; +    Fxch_SCHashTable_Entry_t* pBin; +    Fxch_SubCube_t* pNewEntry; +    int iEntry;      MurmurHash3_x86_32( ( void* ) &SubCubeID, sizeof( int ), 0x9747b28c, &BinID); - -    iNewEntry = ( unsigned int )( Vec_IntEntry( pSCHashTable->vCubeLinks, iCube ) ) + iSubCube;      pBin = Fxch_SCHashTableBin( pSCHashTable, BinID ); -    pNewEntry = Fxch_SCHashTableEntry( pSCHashTable, iNewEntry ); - -    assert( pNewEntry->Used == 0 ); - -    pNewEntry->SCData.Id = SubCubeID; -    pNewEntry->SCData.iCube = iCube; -    pNewEntry->SCData.iLit0 = iLit0; -    pNewEntry->SCData.iLit1 = iLit1; +     +    if ( pBin->vSCData == NULL ) +    { +        pBin->vSCData = ABC_CALLOC( Fxch_SubCube_t, 16 ); +        pBin->Size = 0; +        pBin->Cap = 16; +    } +    else if ( pBin->Size == pBin->Cap ) +    { +        pBin->Cap = 2 * pBin->Size; +        pBin->vSCData = ABC_REALLOC( Fxch_SubCube_t, pBin->vSCData, pBin->Cap ); +    } -    pNewEntry->Used = 1; +    iNewEntry = pBin->Size++; +    pBin->vSCData[iNewEntry].Id = SubCubeID; +    pBin->vSCData[iNewEntry].iCube = iCube; +    pBin->vSCData[iNewEntry].iLit0 = iLit0; +    pBin->vSCData[iNewEntry].iLit1 = iLit1;      pSCHashTable->nEntries++; -    if ( pBin->iTable == 0 ) -    { -        pBin->iTable = iNewEntry; -        pNewEntry->iNext = iNewEntry; -        pNewEntry->iPrev = iNewEntry; + +    if ( pBin->Size == 1 )          return 0; -    } -    for ( iEntry = pBin->iTable; iEntry != pBin->iTable || fStart; iEntry = pEntry->iNext, fStart = 0 ) +    pNewEntry = &( pBin->vSCData[iNewEntry] ); +    for ( iEntry = 0; iEntry < (int)pBin->Size - 1; iEntry++ )      { +        Fxch_SubCube_t* pEntry = &( pBin->vSCData[iEntry] ); +        int* pOutputID0 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pEntry->iCube * pSCHashTable->pFxchMan->nSizeOutputID ); +        int* pOutputID1 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pNewEntry->iCube * pSCHashTable->pFxchMan->nSizeOutputID ); +        int Result = 0;          int Base; -        int iNewDiv; +        int iNewDiv, i, z; -        pEntry = Fxch_SCHashTableBin( pSCHashTable, iEntry ); - -        if ( !Fxch_SCHashTableEntryCompare( pSCHashTable, vCubes, &( pEntry->SCData ), &( pNewEntry->SCData ) ) ) +        if ( !Fxch_SCHashTableEntryCompare( pSCHashTable, vCubes, pEntry, pNewEntry ) )              continue; -        if ( ( pEntry->SCData.iLit0 == 0 ) || ( pNewEntry->SCData.iLit0 == 0 ) ) +        if ( ( pEntry->iLit0 == 0 ) || ( pNewEntry->iLit0 == 0 ) )          { -            Vec_Int_t* vCube0 = Fxch_ManGetCube( pSCHashTable->pFxchMan, pEntry->SCData.iCube ), -                     * vCube1 = Fxch_ManGetCube( pSCHashTable->pFxchMan, pEntry->SCData.iCube ); +            Vec_Int_t* vCube0 = Fxch_ManGetCube( pSCHashTable->pFxchMan, pEntry->iCube ), +                     * vCube1 = Fxch_ManGetCube( pSCHashTable->pFxchMan, pNewEntry->iCube );              if ( Vec_IntSize( vCube0 ) > Vec_IntSize( vCube1 ) ) -                Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pEntry->SCData.iCube ); +            { +                Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pEntry->iCube ); +                Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pNewEntry->iCube ); +            }              else -                Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pNewEntry->SCData.iCube ); +            { +                Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pNewEntry->iCube ); +                Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pEntry->iCube ); +            }              continue;          } -        if ( pEntry->SCData.iCube < pNewEntry->SCData.iCube ) -            Base = Fxch_DivCreate( pSCHashTable->pFxchMan, &( pEntry->SCData ), &( pNewEntry->SCData ) ); -        else -            Base = Fxch_DivCreate( pSCHashTable->pFxchMan, &( pNewEntry->SCData ), &( pEntry->SCData ) ); +        Base = Fxch_DivCreate( pSCHashTable->pFxchMan, pEntry, pNewEntry );          if ( Base < 0 )              continue; -        iNewDiv = Fxch_DivAdd( pSCHashTable->pFxchMan, fUpdate, 0, Base ); +        for ( i = 0; i < pSCHashTable->pFxchMan->nSizeOutputID; i++ ) +            Result += Fxch_CountOnes( pOutputID0[i] & pOutputID1[i] ); -        Vec_WecPush( pSCHashTable->pFxchMan->vDivCubePairs, iNewDiv, pEntry->SCData.iCube ); -        Vec_WecPush( pSCHashTable->pFxchMan->vDivCubePairs, iNewDiv, pNewEntry->SCData.iCube ); +        for ( z = 0; z < Result; z++ ) +            iNewDiv = Fxch_DivAdd( pSCHashTable->pFxchMan, fUpdate, 0, Base ); + +        Vec_WecPush( pSCHashTable->pFxchMan->vDivCubePairs, iNewDiv, pEntry->iCube ); +        Vec_WecPush( pSCHashTable->pFxchMan->vDivCubePairs, iNewDiv, pNewEntry->iCube );          Pairs++;      } -    assert( iEntry == (unsigned int)( pBin->iTable ) ); - -    pEntry = Fxch_SCHashTableBin( pSCHashTable, iEntry ); -    Fxch_SCHashTableInsertLink( pSCHashTable, pEntry->iPrev, iNewEntry );      return Pairs;  }  int Fxch_SCHashTableRemove( Fxch_SCHashTable_t* pSCHashTable,                              Vec_Wec_t* vCubes, -                            unsigned int SubCubeID, -                            unsigned int iSubCube, -                            unsigned int iCube, -                            unsigned int iLit0, -                            unsigned int iLit1, +                            uint32_t SubCubeID, +                            uint32_t iCube, +                            uint32_t iLit0, +                            uint32_t iLit1,                              char fUpdate )  { -    unsigned int BinID; -    unsigned int iEntry; -    Fxch_SCHashTable_Entry_t* pBin,* pEntry; -    Fxch_SCHashTable_Entry_t* pNextEntry; -    int iNextEntry, -        Pairs = 0, -        fStart = 1; +    int iEntry; +    int Pairs = 0; +    uint32_t BinID; +    Fxch_SCHashTable_Entry_t* pBin; +    Fxch_SubCube_t* pEntry; +    int idx;      MurmurHash3_x86_32( ( void* ) &SubCubeID, sizeof( int ), 0x9747b28c, &BinID); -    iEntry = ( unsigned int )( Vec_IntEntry( pSCHashTable->vCubeLinks, iCube ) ) + iSubCube;      pBin = Fxch_SCHashTableBin( pSCHashTable, BinID ); -    pEntry = Fxch_SCHashTableEntry( pSCHashTable, iEntry ); - -    assert( pEntry->Used == 1 ); -    assert( pEntry->SCData.iCube == iCube ); -    if ( pEntry->iNext == iEntry ) +    if ( pBin->Size == 1 )      { -        assert( pEntry->iPrev == iEntry ); -        pBin->iTable = 0; -        pEntry->iNext = 0; -        pEntry->iPrev = 0; -        pEntry->Used = 0; +        pBin->Size = 0;          return 0;      } -    for ( iNextEntry = (int)pEntry->iNext; iNextEntry != (int)iEntry; iNextEntry = pNextEntry->iNext, fStart = 0 ) +    for ( iEntry = 0; iEntry < (int)pBin->Size; iEntry++ ) +        if ( pBin->vSCData[iEntry].iCube == iCube ) +            break; + +    assert( ( iEntry != pBin->Size ) && ( pBin->Size != 0 ) ); + +    pEntry = &( pBin->vSCData[iEntry] ); +    for ( idx = 0; idx < (int)pBin->Size; idx++ ) +    if ( idx != iEntry )      {          int Base,              iDiv; -        int i, +        int i, z,              iCube0,              iCube1; +        Fxch_SubCube_t* pNextEntry = &( pBin->vSCData[idx] );          Vec_Int_t* vDivCubePairs; +        int* pOutputID0 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pEntry->iCube * pSCHashTable->pFxchMan->nSizeOutputID ); +        int* pOutputID1 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pNextEntry->iCube * pSCHashTable->pFxchMan->nSizeOutputID ); +        int Result = 0; -        pNextEntry = Fxch_SCHashTableBin( pSCHashTable, iNextEntry ); - -        if ( !Fxch_SCHashTableEntryCompare( pSCHashTable, vCubes, &( pEntry->SCData ), &( pNextEntry->SCData ) ) -             || pEntry->SCData.iLit0 == 0 -             || pNextEntry->SCData.iLit0 == 0 ) +        if ( !Fxch_SCHashTableEntryCompare( pSCHashTable, vCubes, pEntry, pNextEntry ) +             || pEntry->iLit0 == 0 +             || pNextEntry->iLit0 == 0 )              continue; -        if ( pNextEntry->SCData.iCube < pEntry->SCData.iCube ) -            Base = Fxch_DivCreate( pSCHashTable->pFxchMan, &( pNextEntry->SCData ), &( pEntry->SCData ) ); -        else -            Base = Fxch_DivCreate( pSCHashTable->pFxchMan, &( pEntry->SCData ), &( pNextEntry->SCData ) ); +        Base = Fxch_DivCreate( pSCHashTable->pFxchMan, pNextEntry, pEntry );          if ( Base < 0 )              continue; -        iDiv = Fxch_DivRemove( pSCHashTable->pFxchMan, fUpdate, 0, Base ); +        for ( i = 0; i < pSCHashTable->pFxchMan->nSizeOutputID; i++ ) +            Result += Fxch_CountOnes( pOutputID0[i] & pOutputID1[i] ); + +        for ( z = 0; z < Result; z++ ) +            iDiv = Fxch_DivRemove( pSCHashTable->pFxchMan, fUpdate, 0, Base );          vDivCubePairs = Vec_WecEntry( pSCHashTable->pFxchMan->vDivCubePairs, iDiv );          Vec_IntForEachEntryDouble( vDivCubePairs, iCube0, iCube1, i ) -            if ( ( iCube0 == (int)pNextEntry->SCData.iCube &&  iCube1 == (int)pEntry->SCData.iCube )  || -                 ( iCube0 == (int)pEntry->SCData.iCube &&  iCube1 == (int)pNextEntry->SCData.iCube ) ) +            if ( ( iCube0 == (int)pNextEntry->iCube && iCube1 == (int)pEntry->iCube )  || +                 ( iCube0 == (int)pEntry->iCube && iCube1 == (int)pNextEntry->iCube ) )              {                  Vec_IntDrop( vDivCubePairs, i+1 );                  Vec_IntDrop( vDivCubePairs, i ); @@ -379,12 +338,10 @@ int Fxch_SCHashTableRemove( Fxch_SCHashTable_t* pSCHashTable,          Pairs++;      } +     +    memmove(pBin->vSCData + iEntry, pBin->vSCData + iEntry + 1, (pBin->Size - iEntry - 1) * sizeof(*pBin->vSCData)); +    pBin->Size -= 1; -    if ( pBin->iTable == iEntry ) -        pBin->iTable = ( pEntry->iNext != iEntry ) ? pEntry->iNext : 0; - -    pEntry->Used = 0; -    Fxch_SCHashTableRemoveLink( pSCHashTable, pEntry->iPrev, iEntry );      return Pairs;  } @@ -392,7 +349,6 @@ unsigned int Fxch_SCHashTableMemory( Fxch_SCHashTable_t* pHashTable )  {      unsigned int Memory = sizeof ( Fxch_SCHashTable_t ); -    Memory += Vec_IntMemory( pHashTable->vCubeLinks );      Memory += sizeof( Fxch_SubCube_t ) * ( pHashTable->SizeMask + 1 );      return Memory; diff --git a/src/proof/acec/acec.h b/src/proof/acec/acec.h index f39041c8..c61b4485 100644 --- a/src/proof/acec/acec.h +++ b/src/proof/acec/acec.h @@ -53,7 +53,7 @@ ABC_NAMESPACE_HEADER_START  /*=== acecCore.c ========================================================*/  extern int           Gia_PolynCec( Gia_Man_t * pGia0, Gia_Man_t * pGia1, Cec_ParCec_t * pPars );  /*=== acecFadds.c ========================================================*/ -extern Vec_Int_t *   Gia_ManDetectFullAdders( Gia_Man_t * p, int fVerbose ); +extern Vec_Int_t *   Gia_ManDetectFullAdders( Gia_Man_t * p, int fVerbose, Vec_Int_t ** vCutsXor2 );  extern Vec_Int_t *   Gia_ManDetectHalfAdders( Gia_Man_t * p, int fVerbose );  /*=== acecOrder.c ========================================================*/  extern Vec_Int_t *   Gia_PolynReorder( Gia_Man_t * pGia, int fVerbose, int fVeryVerbose ); diff --git a/src/proof/acec/acecCover.c b/src/proof/acec/acecCover.c new file mode 100644 index 00000000..e0d16419 --- /dev/null +++ b/src/proof/acec/acecCover.c @@ -0,0 +1,263 @@ +/**CFile**************************************************************** + +  FileName    [acecCover.c] + +  SystemName  [ABC: Logic synthesis and verification system.] + +  PackageName [CEC for arithmetic circuits.] + +  Synopsis    [Core procedures.] + +  Author      [Alan Mishchenko] +   +  Affiliation [UC Berkeley] + +  Date        [Ver. 1.0. Started - June 20, 2005.] + +  Revision    [$Id: acecCover.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "acecInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +///                        DECLARATIONS                              /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +///                     FUNCTION DEFINITIONS                         /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + +  Synopsis    [] + +  Description [] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +void Gia_AcecMark_rec( Gia_Man_t * p, int iObj, int fFirst ) +{ +    Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); +    if ( pObj->fMark0 && !fFirst ) +        return; +    assert( Gia_ObjIsAnd(pObj) ); +    pObj->fMark1 = 1; +    Gia_AcecMark_rec( p, Gia_ObjFaninId0(pObj, iObj), 0 ); +    Gia_AcecMark_rec( p, Gia_ObjFaninId1(pObj, iObj), 0 ); +} +void Gia_AcecMarkFadd( Gia_Man_t * p, int * pSigs ) +{ +//    if ( Gia_ManObj(p, pSigs[3])->fMark1 || Gia_ManObj(p, pSigs[4])->fMark1 ) +//        return; +    Gia_ManObj( p, pSigs[0] )->fMark0 = 1; +    Gia_ManObj( p, pSigs[1] )->fMark0 = 1; +    Gia_ManObj( p, pSigs[2] )->fMark0 = 1; +//    assert( !Gia_ManObj(p, pSigs[3])->fMark1 ); +//    assert( !Gia_ManObj(p, pSigs[4])->fMark1 ); +    Gia_AcecMark_rec( p, pSigs[3], 1 ); +    Gia_AcecMark_rec( p, pSigs[4], 1 ); +} +void Gia_AcecMarkHadd( Gia_Man_t * p, int * pSigs ) +{ +    Gia_Obj_t * pObj = Gia_ManObj( p, pSigs[0] ); +    int iFan0 = Gia_ObjFaninId0( pObj, pSigs[0] ); +    int iFan1 = Gia_ObjFaninId1( pObj, pSigs[0] ); +    Gia_ManObj( p, iFan0 )->fMark0 = 1; +    Gia_ManObj( p, iFan1 )->fMark0 = 1; +    Gia_AcecMark_rec( p, pSigs[0], 1 ); +    Gia_AcecMark_rec( p, pSigs[1], 1 ); +} + +/**Function************************************************************* + +  Synopsis    [Collect XORs reachable from the last output.] + +  Description [] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +void Gia_AcecCollectXors_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Bit_t * vMap, Vec_Int_t * vXors ) +{ +    if ( !Gia_ObjIsXor(pObj) )//|| Vec_BitEntry(vMap, Gia_ObjId(p, pObj)) ) +        return; +    Vec_IntPush( vXors, Gia_ObjId(p, pObj) ); +    Gia_AcecCollectXors_rec( p, Gia_ObjFanin0(pObj), vMap, vXors ); +    Gia_AcecCollectXors_rec( p, Gia_ObjFanin1(pObj), vMap, vXors ); +} +Vec_Int_t * Gia_AcecCollectXors( Gia_Man_t * p, Vec_Bit_t * vMap ) +{ +    Vec_Int_t * vXors = Vec_IntAlloc( 100 ); +    Gia_Obj_t * pObj = Gia_ObjFanin0( Gia_ManCo(p, Gia_ManCoNum(p)-1) ); +    Gia_AcecCollectXors_rec( p, pObj, vMap, vXors ); +    return vXors; +} + +/**Function************************************************************* + +  Synopsis    [] + +  Description [] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +void Gia_AcecExplore( Gia_Man_t * p, int fVerbose ) +{ +    Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); +    Vec_Int_t * vFadds, * vHadds, * vXors; +    Vec_Bit_t * vMap = Vec_BitStart( Gia_ManObjNum(p) ); +    Gia_Obj_t * pObj;  +    int i, nSupp, nCone, nHadds = 0; +    assert( p->pMuxes != NULL ); +    vFadds = Gia_ManDetectFullAdders( p, fVerbose, NULL ); +    vHadds = Gia_ManDetectHalfAdders( p, fVerbose ); + +    pObj = Gia_ManObj( p, 352 ); +    printf( "Xor = %d.\n", Gia_ObjIsXor(pObj) ); +    printf( "Fanin0 = %d.  Fanin1 = %d.\n", Gia_ObjFaninId0(pObj, 352), Gia_ObjFaninId1(pObj, 352) ); +    printf( "Fan00 = %d.  Fan01 = %d.   Fan10 = %d.  Fan11 = %d.\n",  +        Gia_ObjFaninId0(Gia_ObjFanin0(pObj), Gia_ObjFaninId0(pObj, 352)),  +        Gia_ObjFaninId1(Gia_ObjFanin0(pObj), Gia_ObjFaninId0(pObj, 352)),  +        Gia_ObjFaninId0(Gia_ObjFanin1(pObj), Gia_ObjFaninId1(pObj, 352)),  +        Gia_ObjFaninId1(Gia_ObjFanin1(pObj), Gia_ObjFaninId1(pObj, 352)) ); + +    // create a map of all HADD/FADD outputs +    for ( i = 0; i < Vec_IntSize(vHadds)/2; i++ ) +    { +        int * pSigs = Vec_IntEntryP(vHadds, 2*i); +        Vec_BitWriteEntry( vMap, pSigs[0], 1 ); +        Vec_BitWriteEntry( vMap, pSigs[1], 1 ); +    } +    for ( i = 0; i < Vec_IntSize(vFadds)/5; i++ ) +    { +        int * pSigs = Vec_IntEntryP(vFadds, 5*i); +        Vec_BitWriteEntry( vMap, pSigs[3], 1 ); +        Vec_BitWriteEntry( vMap, pSigs[4], 1 ); +    } + +    Gia_ManCleanMark01( p ); + +    // mark outputs +    Gia_ManForEachCo( p, pObj, i ) +        Gia_ObjFanin0(pObj)->fMark0 = 1; + +    // collect XORs +    vXors = Gia_AcecCollectXors( p, vMap ); +    Vec_BitFree( vMap ); + +    printf( "Collected XORs: " ); +    Vec_IntPrint( vXors ); + +    // mark their fanins +    Gia_ManForEachObjVec( vXors, p, pObj, i ) +    { +        pObj->fMark1 = 1; +        Gia_ObjFanin0(pObj)->fMark0 = 1; +        Gia_ObjFanin1(pObj)->fMark0 = 1; +    } + +    // mark FADDs +    for ( i = 0; i < Vec_IntSize(vFadds)/5; i++ ) +        Gia_AcecMarkFadd( p, Vec_IntEntryP(vFadds, 5*i) ); + +    // iterate through HADDs and find those that fit in +    while ( 1 ) +    { +        int fChange = 0; +        for ( i = 0; i < Vec_IntSize(vHadds)/2; i++ ) +        { +            int * pSigs = Vec_IntEntryP(vHadds, 2*i); +            if ( !Gia_ManObj(p, pSigs[0])->fMark0 || !Gia_ManObj(p, pSigs[1])->fMark0 ) +                continue; +            if ( Gia_ManObj(p, pSigs[0])->fMark1 || Gia_ManObj(p, pSigs[1])->fMark1 ) +                continue; +            Gia_AcecMarkHadd( p, pSigs ); +            fChange = 1; +            nHadds++; +        } +        if ( !fChange ) +            break; +    } +    // print inputs to the adder network +    Gia_ManForEachAnd( p, pObj, i ) +        if ( pObj->fMark0 && !pObj->fMark1 ) +        { +            nSupp = Gia_ManSuppSize( p, &i, 1 ); +            nCone = Gia_ManConeSize( p, &i, 1 ); +            printf( "Node %5d : Supp = %5d.  Cone = %5d.\n", i, nSupp, nCone ); +            Vec_IntPush( vNodes, i ); +        } +    printf( "Fadds = %d. Hadds = %d.  Root nodes found = %d.\n", Vec_IntSize(vFadds)/5, nHadds, Vec_IntSize(vNodes) ); + +    Gia_ManCleanMark01( p ); + +    Gia_ManForEachObjVec( vNodes, p, pObj, i ) +        pObj->fMark0 = 1; + +    Vec_IntFree( vFadds ); +    Vec_IntFree( vHadds ); +    Vec_IntFree( vNodes ); +} + + +/**Function************************************************************* + +  Synopsis    [] + +  Description [] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +void Gia_AcecCover( Gia_Man_t * p ) +{ +    int fVerbose = 1; +    int i, k, Entry; +    Gia_Obj_t * pObj; +    Vec_Int_t * vCutsXor2 = NULL; +    Vec_Int_t * vFadds = Gia_ManDetectFullAdders( p, fVerbose, &vCutsXor2 ); + +    // mark FADDs +    Gia_ManCleanMark01( p ); +    for ( i = 0; i < Vec_IntSize(vFadds)/5; i++ ) +        Gia_AcecMarkFadd( p, Vec_IntEntryP(vFadds, 5*i) ); + +    k = 0; +    Vec_IntForEachEntry( vCutsXor2, Entry, i ) +    { +        if ( i % 3 != 2 ) +            continue; +        pObj = Gia_ManObj( p, Entry ); +        if ( pObj->fMark1 ) +            continue; +        printf( "%d ", Entry ); +    } +    printf( "\n" ); + +    Gia_ManCleanMark01( p ); + +    Vec_IntFree( vFadds ); +    Vec_IntFree( vCutsXor2 ); +} + +//////////////////////////////////////////////////////////////////////// +///                       END OF FILE                                /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/acec/acecFadds.c b/src/proof/acec/acecFadds.c index 6b954398..7f6dcd53 100644 --- a/src/proof/acec/acecFadds.c +++ b/src/proof/acec/acecFadds.c @@ -59,6 +59,7 @@ Vec_Int_t * Gia_ManDetectHalfAdders( Gia_Man_t * p, int fVerbose )          {              if ( !Gia_ObjIsXor(pObj) )                  continue; +            Count = 0;              iFan0 = Gia_ObjFaninId0(pObj, i);              iFan1 = Gia_ObjFaninId1(pObj, i);              if ( (iLit = Gia_ManHashLookupInt(p, Abc_Var2Lit(iFan0, 0), Abc_Var2Lit(iFan1, 0))) ) @@ -69,6 +70,7 @@ Vec_Int_t * Gia_ManDetectHalfAdders( Gia_Man_t * p, int fVerbose )                  Vec_IntPushTwo( vHadds, i, Abc_Lit2Var(iLit) ), Count++;              if ( (iLit = Gia_ManHashLookupInt(p, Abc_Var2Lit(iFan0, 1), Abc_Var2Lit(iFan1, 0))) )                  Vec_IntPushTwo( vHadds, i, Abc_Lit2Var(iLit) ), Count++; +            Counts[Count]++;          }      }      else @@ -116,7 +118,10 @@ Vec_Int_t * Gia_ManDetectHalfAdders( Gia_Man_t * p, int fVerbose )          printf( "\n" );          Vec_IntForEachEntryDouble( vHadds, iXor, iAnd, i ) -            printf( "%3d : %5d %5d\n", i, iXor, iAnd ); +        { +            pObj = Gia_ManObj( p, iXor ); +            printf( "%3d : %5d %5d -> %5d %5d\n", i, Gia_ObjFaninId0(pObj, iXor), Gia_ObjFaninId1(pObj, iXor), iXor, iAnd ); +        }      }      return vHadds;  } @@ -255,6 +260,8 @@ int Dtc_ObjComputeTruth( Gia_Man_t * p, int iObj, int * pCut, int * pTruth )      Dtc_ObjCleanTruth_rec( Gia_ManObj(p, iObj) );      if ( pTruth )           *pTruth = Truth; +    if ( Truth == 0x66 || Truth == 0x99 ) +        return 3;      if ( Truth == 0x96 || Truth == 0x69 )          return 1;      if ( Truth == 0xE8 || Truth == 0xD4 || Truth == 0xB2 || Truth == 0x71 || @@ -262,11 +269,13 @@ int Dtc_ObjComputeTruth( Gia_Man_t * p, int iObj, int * pCut, int * pTruth )          return 2;      return 0;  } -void Dtc_ManCutMerge( Gia_Man_t * p, int iObj, int * pList0, int * pList1, Vec_Int_t * vCuts, Vec_Int_t * vCutsXor, Vec_Int_t * vCutsMaj ) +void Dtc_ManCutMerge( Gia_Man_t * p, int iObj, int * pList0, int * pList1, Vec_Int_t * vCuts, Vec_Int_t * vCutsXor2, Vec_Int_t * vCutsXor, Vec_Int_t * vCutsMaj )  {      int fVerbose = 0;      Vec_Int_t * vTemp;      int i, k, c, Type, * pCut0, * pCut1, pCut[4]; +    if ( fVerbose ) +        printf( "Object %d = :\n", iObj );      Vec_IntFill( vCuts, 2, 1 );      Vec_IntPush( vCuts, iObj );      Dtc_ForEachCut( pList0, pCut0, i ) @@ -277,8 +286,28 @@ void Dtc_ManCutMerge( Gia_Man_t * p, int iObj, int * pList0, int * pList1, Vec_I          if ( Dtc_ManCutCheckEqual(vCuts, pCut) )              continue;          Vec_IntAddToEntry( vCuts, 0, 1 );   +        if ( fVerbose ) +            printf( "%d : ", pCut[0] );          for ( c = 0; c <= pCut[0]; c++ ) +        {              Vec_IntPush( vCuts, pCut[c] ); +            if ( fVerbose && c ) +                printf( "%d ", pCut[c] ); +        } +        if ( fVerbose ) +            printf( "\n" ); +        if ( pCut[0] == 2 ) +        { +            int Value = Dtc_ObjComputeTruth( p, iObj, pCut, NULL ); +            assert( Value == 3 || Value == 0 ); +            if ( Value == 3 ) +            { +                Vec_IntPush( vCutsXor2, pCut[1] ); +                Vec_IntPush( vCutsXor2, pCut[2] ); +                Vec_IntPush( vCutsXor2, iObj ); +            } +            continue; +        }          if ( pCut[0] != 3 )              continue;          Type = Dtc_ObjComputeTruth( p, iObj, pCut, NULL ); @@ -298,11 +327,12 @@ void Dtc_ManCutMerge( Gia_Man_t * p, int iObj, int * pList0, int * pList1, Vec_I          Vec_IntPush( vTemp, iObj );      }  } -void Dtc_ManComputeCuts( Gia_Man_t * p, Vec_Int_t ** pvCutsXor, Vec_Int_t ** pvCutsMaj, int fVerbose ) +void Dtc_ManComputeCuts( Gia_Man_t * p, Vec_Int_t ** pvCutsXor2, Vec_Int_t ** pvCutsXor, Vec_Int_t ** pvCutsMaj, int fVerbose )  {      Gia_Obj_t * pObj;       int * pList0, * pList1, i, nCuts = 0;      Vec_Int_t * vTemp = Vec_IntAlloc( 1000 ); +    Vec_Int_t * vCutsXor2 = Vec_IntAlloc( Gia_ManAndNum(p) );      Vec_Int_t * vCutsXor = Vec_IntAlloc( Gia_ManAndNum(p) );      Vec_Int_t * vCutsMaj = Vec_IntAlloc( Gia_ManAndNum(p) );      Vec_Int_t * vCuts = Vec_IntAlloc( 30 * Gia_ManAndNum(p) ); @@ -319,7 +349,7 @@ void Dtc_ManComputeCuts( Gia_Man_t * p, Vec_Int_t ** pvCutsXor, Vec_Int_t ** pvC      {          pList0 = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, Gia_ObjFaninId0(pObj, i)) );          pList1 = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, Gia_ObjFaninId1(pObj, i)) ); -        Dtc_ManCutMerge( p, i, pList0, pList1, vTemp, vCutsXor, vCutsMaj ); +        Dtc_ManCutMerge( p, i, pList0, pList1, vTemp, vCutsXor2, vCutsXor, vCutsMaj );          Vec_IntWriteEntry( vCuts, i, Vec_IntSize(vCuts) );          Vec_IntAppend( vCuts, vTemp );          nCuts += Vec_IntEntry( vTemp, 0 ); @@ -329,6 +359,10 @@ void Dtc_ManComputeCuts( Gia_Man_t * p, Vec_Int_t ** pvCutsXor, Vec_Int_t ** pvC              Gia_ManAndNum(p), nCuts, 1.0*nCuts/Gia_ManAndNum(p), 1.0*Vec_IntSize(vCuts)/Gia_ManAndNum(p) );      Vec_IntFree( vTemp );      Vec_IntFree( vCuts ); +    if ( pvCutsXor2 ) +        *pvCutsXor2 = vCutsXor2; +    else +        Vec_IntFree( vCutsXor2 );      *pvCutsXor = vCutsXor;      *pvCutsMaj = vCutsMaj;  } @@ -375,6 +409,12 @@ void Dtc_ManPrintFadds( Vec_Int_t * vFadds )          printf( "%6d ", Vec_IntEntry(vFadds, 5*i+3) );          printf( "%6d ", Vec_IntEntry(vFadds, 5*i+4) );          printf( "\n" ); + +        if ( i == 100 ) +        { +            printf( "Skipping other FADDs.\n" ); +            break; +        }      }  }  int Dtc_ManCompare( int * pCut0, int * pCut1 ) @@ -394,10 +434,10 @@ int Dtc_ManCompare2( int * pCut0, int * pCut1 )      return 0;  }  // returns array of 5-tuples containing inputs/sum/cout of each full adder -Vec_Int_t * Gia_ManDetectFullAdders( Gia_Man_t * p, int fVerbose ) +Vec_Int_t * Gia_ManDetectFullAdders( Gia_Man_t * p, int fVerbose, Vec_Int_t ** pvCutsXor2 )  {      Vec_Int_t * vCutsXor, * vCutsMaj, * vFadds; -    Dtc_ManComputeCuts( p, &vCutsXor, &vCutsMaj, fVerbose ); +    Dtc_ManComputeCuts( p, pvCutsXor2, &vCutsXor, &vCutsMaj, fVerbose );      qsort( Vec_IntArray(vCutsXor), Vec_IntSize(vCutsXor)/4, 16, (int (*)(const void *, const void *))Dtc_ManCompare );      qsort( Vec_IntArray(vCutsMaj), Vec_IntSize(vCutsMaj)/4, 16, (int (*)(const void *, const void *))Dtc_ManCompare );      vFadds = Dtc_ManFindCommonCuts( p, vCutsXor, vCutsMaj ); @@ -762,7 +802,7 @@ Gia_Man_t * Gia_ManDupWithNaturalBoxes( Gia_Man_t * p, int nFaddMin, int fVerbos      assert( Gia_ManBoxNum(p) == 0 );      // detect FADDs -    vFadds = Gia_ManDetectFullAdders( p, fVerbose ); +    vFadds = Gia_ManDetectFullAdders( p, fVerbose, NULL );      assert( Vec_IntSize(vFadds) % 5 == 0 );      // map MAJ into its FADD      vMap = Gia_ManCreateMap( p, vFadds ); diff --git a/src/proof/acec/acecOrder.c b/src/proof/acec/acecOrder.c index 9b2242d0..93ef7f10 100644 --- a/src/proof/acec/acecOrder.c +++ b/src/proof/acec/acecOrder.c @@ -198,7 +198,7 @@ Vec_Int_t * Gia_PolynFindOrder( Gia_Man_t * pGia, Vec_Int_t * vFadds, Vec_Int_t  ***********************************************************************/  Vec_Int_t * Gia_PolynReorder( Gia_Man_t * pGia, int fVerbose, int fVeryVerbose )  { -    Vec_Int_t * vFadds  = Gia_ManDetectFullAdders( pGia, fVeryVerbose ); +    Vec_Int_t * vFadds  = Gia_ManDetectFullAdders( pGia, fVeryVerbose, NULL );      Vec_Int_t * vHadds  = Gia_ManDetectHalfAdders( pGia, fVeryVerbose );      Vec_Int_t * vRecord = Gia_PolynFindOrder( pGia, vFadds, vHadds, fVerbose, fVeryVerbose );      Vec_Int_t * vOrder  = Vec_IntAlloc( Gia_ManAndNum(pGia) ); diff --git a/src/proof/acec/acecPolyn.c b/src/proof/acec/acecPolyn.c index be601405..042e0c59 100644 --- a/src/proof/acec/acecPolyn.c +++ b/src/proof/acec/acecPolyn.c @@ -64,26 +64,6 @@ struct Pln_Man_t_  /**Function************************************************************* -  Synopsis    [] - -  Description [] -                -  SideEffects [] - -  SeeAlso     [] - -***********************************************************************/ -Vec_Int_t * Pln_ManSimpleOrder( Gia_Man_t * p ) -{ -    Vec_Int_t * vOrder; int Id; -    vOrder = Vec_IntStart( Gia_ManObjNum(p) ); -    Gia_ManForEachAndId( p, Id ) -        Vec_IntWriteEntry( vOrder, Id, Id ); -    return vOrder; -} - -/**Function************************************************************* -    Synopsis    [Computation manager.]    Description [] @@ -108,7 +88,7 @@ Pln_Man_t * Pln_ManAlloc( Gia_Man_t * pGia, Vec_Int_t * vOrder )      p->vTempM[1] = Vec_IntAlloc( 100 );      p->vTempM[2] = Vec_IntAlloc( 100 );      p->vTempM[3] = Vec_IntAlloc( 100 ); -    p->vOrder    = vOrder ? vOrder : Vec_IntStartNatural( Gia_ManObjNum(pGia) ); +    p->vOrder    = vOrder ? Vec_IntDup(vOrder) : Vec_IntStartNatural( Gia_ManObjNum(pGia) );      assert( Vec_IntSize(p->vOrder) == Gia_ManObjNum(pGia) );      Vec_QueSetPriority( p->vQue, Vec_FltArrayP(p->vCounts) );      // add 0-constant and 1-monomial @@ -131,36 +111,52 @@ void Pln_ManStop( Pln_Man_t * p )      Vec_IntFree( p->vTempM[1] );      Vec_IntFree( p->vTempM[2] );      Vec_IntFree( p->vTempM[3] ); -    //Vec_IntFree( p->vOrder ); +    Vec_IntFree( p->vOrder );      ABC_FREE( p );  } +int Pln_ManCompare3( int * pData0, int * pData1 ) +{ +    if ( pData0[0] < pData1[0] ) return -1; +    if ( pData0[0] > pData1[0] ) return  1; +    if ( pData0[1] < pData1[1] ) return -1; +    if ( pData0[1] > pData1[1] ) return  1; +    return 0; +}  void Pln_ManPrintFinal( Pln_Man_t * p, int fVerbose, int fVeryVerbose )  {      Vec_Int_t * vArray; -    int k, Entry, iMono, iConst, Count = 0; +    int i, k, Entry, iMono, iConst; +    // collect triples +    Vec_Int_t * vPairs = Vec_IntAlloc( 100 );      Vec_IntForEachEntry( p->vCoefs, iConst, iMono )      {          if ( iConst == 0 )               continue; - -        Count++; - -        if ( !fVerbose ) -            continue; - -        if ( Count > 25 ) +        vArray = Hsh_VecReadEntry( p->pHashC, iConst ); +        Vec_IntPush( vPairs, Vec_IntEntry(vArray, 0) ); +        vArray = Hsh_VecReadEntry( p->pHashM, iMono ); +        Vec_IntPush( vPairs, Vec_IntSize(vArray) ? Vec_IntEntry(vArray, 0) : 0 ); +        Vec_IntPushTwo( vPairs, iConst, iMono ); +    } +    // sort triples +    qsort( Vec_IntArray(vPairs), Vec_IntSize(vPairs)/4, 16, (int (*)(const void *, const void *))Pln_ManCompare3 ); +    // print +    if ( fVerbose ) +    Vec_IntForEachEntryDouble( vPairs, iConst, iMono, i ) +    { +        if ( i % 4 == 0 )              continue; - +        printf( "%-6d : ", i/4 );          vArray = Hsh_VecReadEntry( p->pHashC, iConst );          Vec_IntForEachEntry( vArray, Entry, k )              printf( "%s%d", Entry < 0 ? "-" : "+", (1 << (Abc_AbsInt(Entry)-1)) ); -          vArray = Hsh_VecReadEntry( p->pHashM, iMono );          Vec_IntForEachEntry( vArray, Entry, k )              printf( " * %d", Entry );          printf( "\n" );      } -    printf( "HashC = %d. HashM = %d.  Total = %d. Used = %d.\n", Hsh_VecSize(p->pHashC), Hsh_VecSize(p->pHashM), p->nBuilds, Count ); +    printf( "HashC = %d. HashM = %d.  Total = %d. Used = %d.  ", Hsh_VecSize(p->pHashC), Hsh_VecSize(p->pHashM), p->nBuilds, Vec_IntSize(vPairs)/4 ); +    Vec_IntFree( vPairs );  }  /**Function************************************************************* @@ -400,7 +396,7 @@ void Gia_PolynBuild( Gia_Man_t * pGia, Vec_Int_t * vOrder, int fSigned, int fVer              else                  Vec_BitSetEntry( vPres, LevCur, 1 ); -            if ( fVerbose ) +            if ( fVeryVerbose )                  printf( "Line%5d   Iter%10d : Obj =%6d.  Order =%6d.  HashC =%6d. HashM =%10d.  Total =%10d. Used =%10d.\n",                       Line++, Iter, LevCur, Vec_IntEntry(p->vOrder, LevCur), Hsh_VecSize(p->pHashC), Hsh_VecSize(p->pHashM), p->nBuilds, p->nUsed );          } @@ -409,14 +405,37 @@ void Gia_PolynBuild( Gia_Man_t * pGia, Vec_Int_t * vOrder, int fSigned, int fVer          Gia_PolynBuildOne( p, iMono );          //clk2 += Abc_Clock() - temp;      } -    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );      //Abc_PrintTime( 1, "Time2", clk2 );      Pln_ManPrintFinal( p, fVerbose, fVeryVerbose ); +    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );      Pln_ManStop( p );      Vec_BitFree( vPres );  } + +/**Function************************************************************* + +  Synopsis    [] + +  Description [] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +void Gia_PolynBuild2( Gia_Man_t * pGia, int fSigned, int fVerbose, int fVeryVerbose ) +{ +    Hsh_VecMan_t * pHashC = Hsh_VecManStart( 1000 );    // hash table for constants +    Hsh_VecMan_t * pHashM = Hsh_VecManStart( 1000 );    // hash table for monomials +    Vec_Wec_t * vLit2Mono = Vec_WecStart( Gia_ManObjNum(pGia) * 2 ); + +    Hsh_VecManStop( pHashC ); +    Hsh_VecManStop( pHashM ); +} + +  ////////////////////////////////////////////////////////////////////////  ///                       END OF FILE                                ///  //////////////////////////////////////////////////////////////////////// diff --git a/src/proof/acec/module.make b/src/proof/acec/module.make index c70b0a7d..900d3f5f 100644 --- a/src/proof/acec/module.make +++ b/src/proof/acec/module.make @@ -1,4 +1,5 @@  SRC +=    src/proof/acec/acecCore.c \ +    src/proof/acec/acecCover.c \      src/proof/acec/acecFadds.c \      src/proof/acec/acecOrder.c \      src/proof/acec/acecPolyn.c \ diff --git a/src/proof/cec/cec.h b/src/proof/cec/cec.h index a0b92b52..e8b243d3 100644 --- a/src/proof/cec/cec.h +++ b/src/proof/cec/cec.h @@ -108,6 +108,7 @@ struct Cec_ParFra_t_      int              fColorDiff;    // miter with separate outputs      int              fSatSweeping;  // enable SAT sweeping      int              fRunCSat;      // enable another solver +    int              fUseOrigIds;   // enable recording of original IDs      int              fVeryVerbose;  // verbose stats      int              fVerbose;      // verbose stats      int              iOutFail;      // the failed output diff --git a/src/proof/cec/cecCore.c b/src/proof/cec/cecCore.c index c9e9f67a..ed5c4ab7 100644 --- a/src/proof/cec/cecCore.c +++ b/src/proof/cec/cecCore.c @@ -236,7 +236,7 @@ Gia_Man_t * Cec_ManSatSolving( Gia_Man_t * pAig, Cec_ParSat_t * pPars )      Gia_Man_t * pNew;      Cec_ManPat_t * pPat;      pPat = Cec_ManPatStart(); -    Cec_ManSatSolve( pPat, pAig, pPars ); +    Cec_ManSatSolve( pPat, pAig, pPars, NULL, NULL, NULL );  //    pNew = Gia_ManDupDfsSkip( pAig );      pNew = Gia_ManDup( pAig );      Cec_ManPatStop( pPat ); @@ -351,6 +351,12 @@ Gia_Man_t * Cec_ManSatSweeping( Gia_Man_t * pAig, Cec_ParFra_t * pPars, int fSil      pIni = Gia_ManDup(pAig);      pIni->pReprs = pAig->pReprs; pAig->pReprs = NULL;      pIni->pNexts = pAig->pNexts; pAig->pNexts = NULL; +    if ( pPars->fUseOrigIds ) +    { +        Gia_ManOrigIdsInit( pIni ); +        Vec_IntFreeP( &pAig->vIdsEquiv ); +        pAig->vIdsEquiv = Vec_IntAlloc( 1000 ); +    }      // prepare the managers      // SAT sweeping @@ -429,7 +435,7 @@ clk = Abc_Clock();          if ( pPars->fRunCSat )              Cec_ManSatSolveCSat( pPat, pSrm, pParsSat );           else -            Cec_ManSatSolve( pPat, pSrm, pParsSat );  +            Cec_ManSatSolve( pPat, pSrm, pParsSat, p->pAig->vIdsOrig, p->vXorNodes, pAig->vIdsEquiv );   p->timeSat += Abc_Clock() - clk;          if ( Cec_ManFraClassesUpdate( p, pSim, pPat, pSrm ) )          { diff --git a/src/proof/cec/cecInt.h b/src/proof/cec/cecInt.h index ef1dd983..d93e5e86 100644 --- a/src/proof/cec/cecInt.h +++ b/src/proof/cec/cecInt.h @@ -201,7 +201,7 @@ extern int                  Cec_ManCountNonConstOutputs( Gia_Man_t * pAig );  extern int                  Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig );  /*=== cecSolve.c ============================================================*/  extern int                  Cec_ObjSatVarValue( Cec_ManSat_t * p, Gia_Obj_t * pObj ); -extern void                 Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars ); +extern void                 Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Int_t * vIdsOrig, Vec_Int_t * vMiterPairs, Vec_Int_t * vEquivPairs );  extern void                 Cec_ManSatSolveCSat( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars );  extern Vec_Str_t *          Cec_ManSatSolveSeq( Vec_Ptr_t * vPatts, Gia_Man_t * pAig, Cec_ParSat_t * pPars, int nRegs, int * pnPats );  extern Vec_Int_t *          Cec_ManSatSolveMiter( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Str_t ** pvStatus ); diff --git a/src/proof/cec/cecSolve.c b/src/proof/cec/cecSolve.c index e3db0b93..f75914e4 100644 --- a/src/proof/cec/cecSolve.c +++ b/src/proof/cec/cecSolve.c @@ -673,7 +673,7 @@ p->timeSatUndec += Abc_Clock() - clk;    SeeAlso     []  ***********************************************************************/ -void Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars ) +void Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Int_t * vIdsOrig, Vec_Int_t * vMiterPairs, Vec_Int_t * vEquivPairs )  {      Bar_Progress_t * pProgress = NULL;      Cec_ManSat_t * p; @@ -706,6 +706,16 @@ clk2 = Abc_Clock();          status = Cec_ManSatCheckNode( p, Gia_ObjChild0(pObj) );          pObj->fMark0 = (status == 0);          pObj->fMark1 = (status == 1); +        if ( status == 1 && vIdsOrig ) +        { +            int iObj1 = Vec_IntEntry(vMiterPairs, 2*i); +            int iObj2 = Vec_IntEntry(vMiterPairs, 2*i+1); +            int OrigId1 = Vec_IntEntry(vIdsOrig, iObj1); +            int OrigId2 = Vec_IntEntry(vIdsOrig, iObj2); +            assert( OrigId1 >= 0 && OrigId2 >= 0 ); +            Vec_IntPushTwo( vEquivPairs, OrigId1, OrigId2 ); +        } +  /*          if ( status == -1 )          { diff --git a/src/proof/ssw/sswConstr.c b/src/proof/ssw/sswConstr.c index a9ed17fc..a3a7e66f 100644 --- a/src/proof/ssw/sswConstr.c +++ b/src/proof/ssw/sswConstr.c @@ -533,8 +533,10 @@ clk = Abc_Clock();                  continue;              }              Ssw_NodesAreConstrained( p, pObjNew, Aig_ManConst0(p->pFrames) ); -        } - +        }         +        // sweep flops +        Saig_ManForEachLo( p->pAig, pObj, i ) +            p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 1 );          // sweep internal nodes          Aig_ManForEachNode( p->pAig, pObj, i )          { diff --git a/src/proof/ssw/sswSweep.c b/src/proof/ssw/sswSweep.c index 6db673cc..77cb24de 100644 --- a/src/proof/ssw/sswSweep.c +++ b/src/proof/ssw/sswSweep.c @@ -287,6 +287,9 @@ clk = Abc_Clock();          Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );          Saig_ManForEachPi( p->pAig, pObj, i )              Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreateCi(p->pFrames) ); +        // sweep flops +        Saig_ManForEachLo( p->pAig, pObj, i ) +            p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 1, NULL );          // sweep internal nodes          Aig_ManForEachNode( p->pAig, pObj, i )          { diff --git a/src/sat/bsat/satSolver.c b/src/sat/bsat/satSolver.c index 9d885701..88a05093 100644 --- a/src/sat/bsat/satSolver.c +++ b/src/sat/bsat/satSolver.c @@ -1019,7 +1019,7 @@ sat_solver* sat_solver_new(void)      sat_solver* s = (sat_solver*)ABC_CALLOC( char, sizeof(sat_solver));  //    Vec_SetAlloc_(&s->Mem, 15); -    Sat_MemAlloc_(&s->Mem, 15); +    Sat_MemAlloc_(&s->Mem, 17);      s->hLearnts = -1;      s->hBinary = Sat_MemAppend( &s->Mem, NULL, 2, 0, 0 );      s->binary = clause_read( s, s->hBinary ); | 
