From ac59789e9bb659e206704ff5fa8c11585a8b824a Mon Sep 17 00:00:00 2001
From: Alan Mishchenko <alanmi@berkeley.edu>
Date: Fri, 31 Mar 2017 21:07:19 -0700
Subject: Experiments with don't-cares.

---
 src/base/abci/abc.c   |   1 +
 src/base/acb/acbAbc.c |   8 +-
 src/base/acb/acbMfs.c | 247 ++++++++++++++++++++++++++++++++++++++------------
 3 files changed, 196 insertions(+), 60 deletions(-)

(limited to 'src/base')

diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c
index 01bffece..4b03cf87 100644
--- a/src/base/abci/abc.c
+++ b/src/base/abci/abc.c
@@ -5777,6 +5777,7 @@ int Abc_CommandMfse( Abc_Frame_t * pAbc, int argc, char ** argv )
         Abc_Print( -1, "Command is only applicable to LUT size no more than 6.\n" );
         return 1;
     }
+    Abc_NtkToSop( pNtk, -1, ABC_INFINITY );
     pNtkNew = Abc_NtkOptMfse( pNtk, pPars );
     if ( pNtkNew == NULL )
     {
diff --git a/src/base/acb/acbAbc.c b/src/base/acb/acbAbc.c
index 9be3bdab..dd97816c 100644
--- a/src/base/acb/acbAbc.c
+++ b/src/base/acb/acbAbc.c
@@ -209,11 +209,11 @@ void Acb_ParSetDefault( Acb_Par_t * pPars )
 {
     memset( pPars, 0, sizeof(Acb_Par_t) );
     pPars->nLutSize     =    4;    // LUT size
-    pPars->nTfoLevMax   =    1;    // the maximum fanout levels
+    pPars->nTfoLevMax   =    2;    // the maximum fanout levels
     pPars->nTfiLevMax   =    2;    // the maximum fanin levels
-    pPars->nFanoutMax   =   10;    // the maximum number of fanouts
-    pPars->nDivMax      =   16;    // the maximum divisor count
-    pPars->nTabooMax    =    4;    // the minimum MFFC size
+    pPars->nFanoutMax   =   20;    // the maximum number of fanouts
+    pPars->nDivMax      =   24;    // the maximum divisor count
+    pPars->nTabooMax    =    1;    // the minimum MFFC size
     pPars->nGrowthLevel =    0;    // the maximum allowed growth in level
     pPars->nBTLimit     =    0;    // the maximum number of conflicts in one SAT run
     pPars->nNodesMax    =    0;    // the maximum number of nodes to try
diff --git a/src/base/acb/acbMfs.c b/src/base/acb/acbMfs.c
index a536a08b..f13ab9f5 100644
--- a/src/base/acb/acbMfs.c
+++ b/src/base/acb/acbMfs.c
@@ -255,11 +255,10 @@ Cnf_Dat_t * Acb_NtkWindow2Cnf( Acb_Ntk_t * p, Vec_Int_t * vWinObjs, int Pivot )
   SeeAlso     []
 
 ***********************************************************************/
-sat_solver * Acb_NtkWindow2Solver( Cnf_Dat_t * pCnf, int PivotVar, int nDivs, int nTimes )
+int Acb_NtkWindow2Solver( sat_solver * pSat, Cnf_Dat_t * pCnf, int PivotVar, int nDivs, int nTimes )
 {
     int n, i, RetValue, nRounds = nTimes <= 2 ? nTimes-1 : 2;
     Vec_Int_t * vFlips = Cnf_DataCollectFlipLits( pCnf, PivotVar );
-    sat_solver * pSat = sat_solver_new(); 
     sat_solver_setnvars( pSat, nTimes * pCnf->nVars + nRounds * nDivs + 1 );
     assert( nTimes == 1 || nTimes == 2 || nTimes == 6 );
     for ( n = 0; n < nTimes; n++ )
@@ -272,7 +271,7 @@ sat_solver * Acb_NtkWindow2Solver( Cnf_Dat_t * pCnf, int PivotVar, int nDivs, in
             {
                 Vec_IntFree( vFlips );
                 sat_solver_delete( pSat );
-                return NULL;
+                return 0;
             }
         }
         if ( n & 1 )
@@ -297,9 +296,9 @@ sat_solver * Acb_NtkWindow2Solver( Cnf_Dat_t * pCnf, int PivotVar, int nDivs, in
     if ( RetValue == 0 )
     {
         sat_solver_delete( pSat );
-        return NULL;    
+        return 0;    
     }
-    return pSat;
+    return 1;
 }
 
 
@@ -324,6 +323,22 @@ void Acb_NtkPrintVec( Acb_Ntk_t * p, Vec_Int_t * vVec, char * pName )
         printf( "%d ", Vec_IntEntry(&p->vArray2, vVec->pArray[i]) );
     printf( "\n" );
 }
+void Acb_NtkPrintNode( Acb_Ntk_t * p, int Node )
+{
+    int k, iFanin, * pFanins;
+    printf( "Node %d : ", Vec_IntEntry(&p->vArray2, Node) );
+    Acb_ObjForEachFaninFast( p, Node, pFanins, iFanin, k )
+        printf( "%d ", Vec_IntEntry(&p->vArray2, iFanin) );
+    printf( "\n" );
+}
+void Acb_NtkPrintVec2( Acb_Ntk_t * p, Vec_Int_t * vVec, char * pName )
+{
+    int i;
+    printf( "%s: \n", pName );
+    for ( i = 0; i < vVec->nSize; i++ )
+        Acb_NtkPrintNode( p, vVec->pArray[i] );
+    printf( "\n" );
+}
 
 /**Function*************************************************************
 
@@ -400,16 +415,15 @@ Vec_Int_t * Acb_NtkDivisors( Acb_Ntk_t * p, int Pivot, int * pTaboo, int nTaboo,
   SeeAlso     []
 
 ***********************************************************************/
-void Acb_ObjMarkTfo_rec( Acb_Ntk_t * p, int iObj, int Pivot, int nTfoLevMax, int nFanMax )
+void Acb_ObjMarkTfo_rec( Acb_Ntk_t * p, int iObj, int nTfoLevMax, int nFanMax )
 {
     int iFanout, i;
     if ( Acb_ObjSetTravIdCur(p, iObj) )
         return;
-//printf( "Labeling %d.\n", Vec_IntEntry(&p->vArray2, iObj) );
-    if ( Acb_ObjLevelD(p, iObj) > nTfoLevMax || Acb_ObjFanoutNum(p, iObj) > nFanMax || iObj == Pivot )
+    if ( Acb_ObjLevelD(p, iObj) > nTfoLevMax || Acb_ObjFanoutNum(p, iObj) > nFanMax )
         return;
     Acb_ObjForEachFanout( p, iObj, iFanout, i )
-        Acb_ObjMarkTfo_rec( p, iFanout, Pivot, nTfoLevMax, nFanMax );
+        Acb_ObjMarkTfo_rec( p, iFanout, nTfoLevMax, nFanMax );
 }
 void Acb_ObjMarkTfo( Acb_Ntk_t * p, Vec_Int_t * vDivs, int Pivot, int nTfoLevMax, int nFanMax )
 {
@@ -417,7 +431,7 @@ void Acb_ObjMarkTfo( Acb_Ntk_t * p, Vec_Int_t * vDivs, int Pivot, int nTfoLevMax
     Acb_NtkIncTravId( p );
     Acb_ObjSetTravIdCur( p, Pivot );
     Vec_IntForEachEntry( vDivs, iObj, i )
-        Acb_ObjMarkTfo_rec( p, iObj, Pivot, nTfoLevMax, nFanMax );
+        Acb_ObjMarkTfo_rec( p, iObj, nTfoLevMax, nFanMax );
 }
 
 /**Function*************************************************************
@@ -767,7 +781,7 @@ static inline void Acb_ObjUpdateFanoutCount( Acb_Ntk_t * p, int iObj, int AddOn
         Acb_ObjFanoutVec(p, iFanin)->nSize += AddOn;
 }
 
-int Acb_NtkCollectTaboo( Acb_Ntk_t * p, int Pivot, int nTabooMax, int * pTaboo )
+int Acb_NtkCollectTaboo( Acb_Ntk_t * p, int Pivot, int Next, int nTabooMax, int * pTaboo )
 {
     int i, k, iFanin, * pFanins, nTaboo = 0;
     if ( nTabooMax == 0 ) // delay optimization
@@ -780,9 +794,15 @@ int Acb_NtkCollectTaboo( Acb_Ntk_t * p, int Pivot, int nTabooMax, int * pTaboo )
     else // area optimization
     {
         // check if the node has any area critical fanins
+//        Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
+//            if ( !Acb_ObjIsCi(p, iFanin) && Acb_ObjFanoutNum(p, iFanin) == 1 )
+//                break;
+        // collect this critical fanin
+        assert( Next > 0 && !Acb_ObjIsCio(p, Next) && Acb_ObjFanoutNum(p, Next) == 1 );
         Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
-            if ( !Acb_ObjIsCi(p, iFanin) && Acb_ObjFanoutNum(p, iFanin) == 1 )
+            if ( iFanin == Next )
                 break;
+        assert( k < Acb_ObjFaninNum(p, Pivot) );
         if ( k < Acb_ObjFaninNum(p, Pivot) ) // there is fanin
         {
             // mark pivot
@@ -886,72 +906,169 @@ Vec_Int_t * Acb_NtkFindSupp( Acb_Ntk_t * p, sat_solver * pSat2, int nVars, int n
     return vSupp;
 }
 
-void Acb_NtkOptNode( Acb_Ntk_t * p, int Pivot, int nTabooMax, int nDivMax, int nTfoLevs, int nFanMax, int nLutSize, int fVerbose )
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+typedef struct Acb_Mfs_t_ Acb_Mfs_t;
+struct Acb_Mfs_t_
 {
-    Cnf_Dat_t * pCnf;
+    Acb_Ntk_t *     pNtk;        // network
+    Acb_Par_t *     pPars;       // parameters
+    sat_solver *    pSat[3];     // SAT solvers
+    int             nOvers;      // overflows
+    int             nNodes;      // nodes
+    int             nWins;       // windows
+    int             nWinsAll;    // windows
+    int             nDivsAll;    // windows
+    int             nChanges[3]; // changes
+    abctime         timeTotal;
+    abctime         timeCnf;
+    abctime         timeSol;
+    abctime         timeWin;
+    abctime         timeSat;
+    abctime         timeSatU;
+    abctime         timeSatS;
+};
+Acb_Mfs_t * Acb_MfsStart( Acb_Ntk_t * pNtk, Acb_Par_t * pPars )
+{
+    Acb_Mfs_t * p = ABC_CALLOC( Acb_Mfs_t, 1 );
+    p->pNtk       = pNtk;
+    p->pPars      = pPars;
+    p->timeTotal  = Abc_Clock();
+    p->pSat[0]    = sat_solver_new();
+    p->pSat[1]    = sat_solver_new();
+    p->pSat[2]    = sat_solver_new();
+    return p;
+}
+void Acb_MfsStop( Acb_Mfs_t * p )
+{
+    sat_solver_delete( p->pSat[0] );
+    sat_solver_delete( p->pSat[1] );
+    sat_solver_delete( p->pSat[2] );
+    ABC_FREE( p );
+}
+int Acb_NtkOptNode( Acb_Mfs_t * p, int Pivot, int Next )
+{
+    Cnf_Dat_t * pCnf; abctime clk;
     Vec_Int_t * vWin, * vSupp = NULL;
-    sat_solver * pSat1 = NULL, * pSat2 = NULL, * pSat3 = NULL;
-    int c, PivotVar, nDivs = 0; word uTruth;
-    int pTaboo[16], nTaboo = Acb_NtkCollectTaboo( p, Pivot, nTabooMax, pTaboo );
+    int c, PivotVar, nDivs = 0, RetValue = 0; word uTruth;
+    int pTaboo[16], nTaboo = Acb_NtkCollectTaboo( p->pNtk, Pivot, Next, p->pPars->nTabooMax, pTaboo );
     if ( nTaboo == 0 )
-        return;
-    assert( nTabooMax == 0 || nTaboo <= nTabooMax );
+        return RetValue;
+    p->nWins++;
+    assert( p->pPars->nTabooMax == 0 || nTaboo <= p->pPars->nTabooMax );
     assert( nTaboo <= 16 );
+    //printf( "Trying node %d with fanin %d\n", Pivot, Next );
 
     // compute divisors and window for this target node with these taboo nodes
-    vWin = Acb_NtkWindow( p, Pivot, pTaboo, nTaboo, nDivMax, nTfoLevs, nFanMax, &nDivs );
+    clk = Abc_Clock();
+    vWin = Acb_NtkWindow( p->pNtk, Pivot, pTaboo, nTaboo, p->pPars->nDivMax, p->pPars->nTfoLevMax, p->pPars->nFanoutMax, &nDivs );
+    p->nWinsAll += Vec_IntSize(vWin);
+    p->nDivsAll += nDivs;
+    p->timeWin  += Abc_Clock() - clk;
     PivotVar = Vec_IntFind( vWin, Abc_Var2Lit(Pivot, 0) );
-    if ( fVerbose )
-    printf( "Node %d: Window contains %d objects and %d divisors.  ", Vec_IntEntry(&p->vArray2, Pivot), Vec_IntSize(vWin), nDivs );
+    if ( p->pPars->fVerbose )
+    printf( "Node %d: Window contains %d objects and %d divisors.  ", Vec_IntEntry(&p->pNtk->vArray2, Pivot), Vec_IntSize(vWin), nDivs );
 //    Acb_WinPrint( p, vWin, Pivot, nDivs );
 //    return;
+    if ( nDivs >= 2 * p->pPars->nDivMax )
+    {
+        p->nOvers++;
+        if ( p->pPars->fVerbose )
+            printf( "Too many divisors.\n" );
+        Vec_IntFree( vWin );
+        return RetValue;
+    }
 
-    // derive CNF and SAT solvers
-    pCnf  = Acb_NtkWindow2Cnf( p, vWin, Pivot );
-    pSat1 = Acb_NtkWindow2Solver( pCnf, PivotVar, nDivs, 1 );
+    // derive CNF 
+    clk = Abc_Clock();
+    pCnf  = Acb_NtkWindow2Cnf( p->pNtk, vWin, Pivot );
+    p->timeCnf += Abc_Clock() - clk;
+    // derive SAT solver
+    clk = Abc_Clock();
+    Acb_NtkWindow2Solver( p->pSat[0], pCnf, PivotVar, nDivs, 1 );
+    p->timeSol += Abc_Clock() - clk;
     // check constants
     for ( c = 0; c < 2; c++ )
     {
         int Lit = Abc_Var2Lit( PivotVar, c );
-        int status = sat_solver_solve( pSat1, &Lit, &Lit + 1, 0, 0, 0, 0 );
+        int status = sat_solver_solve( p->pSat[0], &Lit, &Lit + 1, 0, 0, 0, 0 );
         if ( status == l_False )
         {
-            if ( fVerbose )
+            p->nChanges[0]++;
+            if ( p->pPars->fVerbose )
             printf( "Found constant %d.\n", c );
-            Acb_NtkUpdateNode( p, Pivot, c ? ~(word)0 : 0, NULL );
+            Acb_NtkUpdateNode( p->pNtk, Pivot, c ? ~(word)0 : 0, NULL );
+            RetValue = 1;
             goto cleanup;
         }
         assert( status == l_True );
     }
 
+    // derive SAT solver
+    clk = Abc_Clock();
+    Acb_NtkWindow2Solver( p->pSat[1], pCnf, PivotVar, nDivs, 2 );
+    p->timeSol += Abc_Clock() - clk;
     // check for one-node implementation
-    pSat2 = Acb_NtkWindow2Solver( pCnf, PivotVar, nDivs, 2 );
-    vSupp = Acb_NtkFindSupp( p, pSat2, pCnf->nVars, nDivs );
-    if ( Vec_IntSize(vSupp) <= nLutSize )
+    clk = Abc_Clock();
+    vSupp = Acb_NtkFindSupp( p->pNtk, p->pSat[1], pCnf->nVars, nDivs );
+    p->timeSat += Abc_Clock() - clk;
+    if ( Vec_IntSize(vSupp) <= p->pPars->nLutSize )
     {
-        if ( fVerbose )
+        p->nChanges[1]++;
+        if ( p->pPars->fVerbose )
         printf( "Found %d inputs: ", Vec_IntSize(vSupp) );
-        uTruth = Acb_ComputeFunction( pSat1, PivotVar, sat_solver_nvars(pSat1)-1, vSupp );
-        if ( fVerbose )
+        uTruth = Acb_ComputeFunction( p->pSat[1], PivotVar, sat_solver_nvars(p->pSat[1])-1, vSupp );
+        if ( p->pPars->fVerbose )
         Extra_PrintHex( stdout, (unsigned *)&uTruth, Vec_IntSize(vSupp) ); 
-        if ( fVerbose )
+        if ( p->pPars->fVerbose )
         printf( "\n" );
         // create support in terms of nodes
         Vec_IntRemap( vSupp, vWin );
         Vec_IntLits2Vars( vSupp, 0 );
-        Acb_NtkUpdateNode( p, Pivot, uTruth, vSupp );
+        Acb_NtkUpdateNode( p->pNtk, Pivot, uTruth, vSupp );
+        RetValue = 1;
         goto cleanup;
     }
-    if ( fVerbose )
+    if ( p->pPars->fVerbose )
     printf( "\n" );
 
 cleanup:
-    if ( pSat1 ) sat_solver_delete( pSat1 );
-    if ( pSat2 ) sat_solver_delete( pSat2 );
-    if ( pSat3 ) sat_solver_delete( pSat3 );
+    sat_solver_restart( p->pSat[0] );
+    sat_solver_restart( p->pSat[1] );
+    sat_solver_restart( p->pSat[2] );
     Cnf_DataFree( pCnf );
     Vec_IntFree( vWin );
     Vec_IntFreeP( &vSupp );
+    return RetValue;
+}
+void Acb_NtkOptNodeTop( Acb_Mfs_t * p, int Pivot )
+{
+    if ( p->pPars->fArea )
+    {
+        p->nNodes++;
+        while ( 1 )
+        {
+            int k, iFanin, * pFanins;
+            Acb_ObjForEachFaninFast( p->pNtk, Pivot, pFanins, iFanin, k )
+                if ( !Acb_ObjIsCi(p->pNtk, iFanin) && Acb_ObjFanoutNum(p->pNtk, iFanin) == 1 && Acb_NtkOptNode(p, Pivot, iFanin) )
+                    break;
+            if ( k == Acb_ObjFaninNum(p->pNtk, Pivot) ) // no change
+                break;
+        }
+    }
+    else
+    {
+        assert( 0 );
+    }
 }
 
 
@@ -966,36 +1083,54 @@ cleanup:
   SeeAlso     []
 
 ***********************************************************************/
-void Acb_NtkOpt( Acb_Ntk_t * p, Acb_Par_t * pPars )
-{
-    if ( pPars->fVerbose )
-        printf( "Performing %s-oriented optimization with DivMax = %d. TfoLev = %d. LutSize = %d.\n", 
-            pPars->fArea ? "area" : "delay", pPars->nDivMax, pPars->nTfoLevMax, pPars->nLutSize );
-    Acb_NtkCreateFanout( p );  // fanout data structure
-    Acb_NtkCleanObjFuncs( p ); // SAT variables
-    Acb_NtkCleanObjCnfs( p );  // CNF representations
-    if ( pPars->fArea )
+void Acb_NtkOpt( Acb_Ntk_t * pNtk, Acb_Par_t * pPars )
+{
+    Acb_Mfs_t * pMan = Acb_MfsStart( pNtk, pPars );
+    //if ( pPars->fVerbose )
+        printf( "%s-optimization parameters: TabooMax(M) = %d  DivMax(D) = %d  TfoLev(O) = %d  LutSize = %d\n", 
+            pMan->pPars->fArea ? "Area" : "Delay", pMan->pPars->nTabooMax, pMan->pPars->nDivMax, pMan->pPars->nTfoLevMax, pMan->pPars->nLutSize );
+    Acb_NtkCreateFanout( pMan->pNtk );  // fanout data structure
+    Acb_NtkCleanObjFuncs( pMan->pNtk ); // SAT variables
+    Acb_NtkCleanObjCnfs( pMan->pNtk );  // CNF representations
+    if ( pMan->pPars->fArea )
     {
         int iObj;
-        Acb_NtkUpdateLevelD( p, -1 ); // compute forward logic level
-        Acb_NtkForEachNode( p, iObj )
+        Acb_NtkUpdateLevelD( pMan->pNtk, -1 ); // compute forward logic level
+        Acb_NtkForEachNode( pMan->pNtk, iObj )
         {
             //if ( iObj != 433 )
             //    continue;
-            Acb_NtkOptNode( p, iObj, pPars->nTabooMax, pPars->nDivMax, pPars->nTfoLevMax, pPars->nFanoutMax, pPars->nLutSize, pPars->fVerbose );
+            Acb_NtkOptNodeTop( pMan, iObj );
         }
     }
     else
     {
-        Acb_NtkUpdateTiming( p, -1 ); // compute delay information
-        while ( Vec_QueTopPriority(p->vQue) > 0 )
+        Acb_NtkUpdateTiming( pMan->pNtk, -1 ); // compute delay information
+        while ( Vec_QueTopPriority(pMan->pNtk->vQue) > 0 )
         {
-            int iObj = Vec_QuePop(p->vQue);
+            int iObj = Vec_QuePop(pMan->pNtk->vQue);
             //if ( iObj != 28 )
             //    continue;
-            Acb_NtkOptNode( p, iObj, 0, pPars->nDivMax, pPars->nTfoLevMax, pPars->nFanoutMax, pPars->nLutSize, pPars->fVerbose ); 
+            Acb_NtkOptNodeTop( pMan, iObj ); 
         }
     }
+    //if ( pPars->fVerbose )
+    {
+        pMan->timeTotal = Abc_Clock() - pMan->timeTotal;
+        printf( "Node = %d  Win = %d (Ave = %d)  DivAve = %d   Change = %d  Const = %d  Node1 = %d  Node2 = %d   Over = %d\n", 
+            pMan->nNodes, pMan->nWins, pMan->nWinsAll/Abc_MaxInt(1, pMan->nWins), pMan->nDivsAll/Abc_MaxInt(1, pMan->nWins),
+            pMan->nChanges[0] + pMan->nChanges[1] + pMan->nChanges[2],
+            pMan->nChanges[0], pMan->nChanges[1], pMan->nChanges[2], pMan->nOvers );
+        ABC_PRTP( "Windowing  ", pMan->timeWin,    pMan->timeTotal );
+        ABC_PRTP( "CNF compute", pMan->timeCnf,    pMan->timeTotal );
+        ABC_PRTP( "Make solver", pMan->timeSol,    pMan->timeTotal );
+        ABC_PRTP( "SAT solving", pMan->timeSat,    pMan->timeTotal );
+//        ABC_PRTP( "  unsat    ", pMan->timeSatU,   pMan->timeTotal );
+//        ABC_PRTP( "  sat      ", pMan->timeSatS,   pMan->timeTotal );
+        ABC_PRTP( "TOTAL      ", pMan->timeTotal,  pMan->timeTotal );
+        fflush( stdout );
+    }
+    Acb_MfsStop( pMan );
 }
 
 ////////////////////////////////////////////////////////////////////////
-- 
cgit v1.2.3


From 3898ba5486adc01e38199b5385d501e4ca58ddec Mon Sep 17 00:00:00 2001
From: Alan Mishchenko <alanmi@berkeley.edu>
Date: Fri, 31 Mar 2017 21:24:19 -0700
Subject: Experiments with don't-cares.

---
 src/base/acb/acbMfs.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/base')

diff --git a/src/base/acb/acbMfs.c b/src/base/acb/acbMfs.c
index f13ab9f5..64a74798 100644
--- a/src/base/acb/acbMfs.c
+++ b/src/base/acb/acbMfs.c
@@ -894,7 +894,7 @@ void Acb_WinPrint( Acb_Ntk_t * p, Vec_Int_t * vWin, int Pivot, int nDivs )
     printf( "\n" );
 }
 
-Vec_Int_t * Acb_NtkFindSupp( Acb_Ntk_t * p, sat_solver * pSat2, int nVars, int nDivs )
+Vec_Int_t * Acb_NtkFindSupp2( Acb_Ntk_t * p, sat_solver * pSat2, int nVars, int nDivs )
 {
     int nSuppNew;
     Vec_Int_t * vSupp = Vec_IntStartNatural( nDivs );
@@ -1019,7 +1019,7 @@ int Acb_NtkOptNode( Acb_Mfs_t * p, int Pivot, int Next )
     p->timeSol += Abc_Clock() - clk;
     // check for one-node implementation
     clk = Abc_Clock();
-    vSupp = Acb_NtkFindSupp( p->pNtk, p->pSat[1], pCnf->nVars, nDivs );
+    vSupp = Acb_NtkFindSupp2( p->pNtk, p->pSat[1], pCnf->nVars, nDivs );
     p->timeSat += Abc_Clock() - clk;
     if ( Vec_IntSize(vSupp) <= p->pPars->nLutSize )
     {
-- 
cgit v1.2.3


From f765e666ca4608f8dfe3ab2ecbacaf9966d25129 Mon Sep 17 00:00:00 2001
From: Alan Mishchenko <alanmi@berkeley.edu>
Date: Sun, 2 Apr 2017 21:51:47 -0700
Subject: Experiments with don't-cares.

---
 src/base/abci/abc.c    |  32 +-
 src/base/acb/acb.h     |   5 +-
 src/base/acb/acbAbc.c  |   5 +-
 src/base/acb/acbMfs.c  | 844 +++++++++++++++++++++++++++++++------------------
 src/base/acb/acbPar.h  |   3 +-
 src/base/acb/acbUtil.c |  30 +-
 6 files changed, 595 insertions(+), 324 deletions(-)

(limited to 'src/base')

diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c
index 4b03cf87..8e2c449c 100644
--- a/src/base/abci/abc.c
+++ b/src/base/abci/abc.c
@@ -5676,41 +5676,41 @@ int Abc_CommandMfse( Abc_Frame_t * pAbc, int argc, char ** argv )
     Acb_Par_t Pars, * pPars = &Pars; int c;
     Acb_ParSetDefault( pPars );
     Extra_UtilGetoptReset();
-    while ( ( c = Extra_UtilGetopt( argc, argv, "MDOFLCavwh" ) ) != EOF )
+    while ( ( c = Extra_UtilGetopt( argc, argv, "IOWFLCavwh" ) ) != EOF )
     {
         switch ( c )
         {
-        case 'M':
+        case 'I':
             if ( globalUtilOptind >= argc )
             {
-                Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
                 goto usage;
             }
-            pPars->nTabooMax = atoi(argv[globalUtilOptind]);
+            pPars->nTfiLevMax = atoi(argv[globalUtilOptind]);
             globalUtilOptind++;
-            if ( pPars->nTabooMax < 0 )
+            if ( pPars->nTfiLevMax < 0 )
                 goto usage;
             break;
-        case 'D':
+        case 'O':
             if ( globalUtilOptind >= argc )
             {
-                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" );
                 goto usage;
             }
-            pPars->nDivMax = atoi(argv[globalUtilOptind]);
+            pPars->nTfoLevMax = atoi(argv[globalUtilOptind]);
             globalUtilOptind++;
-            if ( pPars->nDivMax < 0 )
+            if ( pPars->nTfoLevMax < 0 )
                 goto usage;
             break;
-        case 'O':
+        case 'W':
             if ( globalUtilOptind >= argc )
             {
-                Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" );
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
                 goto usage;
             }
-            pPars->nTfoLevMax = atoi(argv[globalUtilOptind]);
+            pPars->nWinNodeMax = atoi(argv[globalUtilOptind]);
             globalUtilOptind++;
-            if ( pPars->nTfoLevMax < 0 )
+            if ( pPars->nWinNodeMax < 0 )
                 goto usage;
             break;
         case 'F':
@@ -5788,11 +5788,11 @@ int Abc_CommandMfse( Abc_Frame_t * pAbc, int argc, char ** argv )
     return 0;
 
 usage:
-    Abc_Print( -2, "usage: mfse [-MDOFLC <num>] [-avwh]\n" );
+    Abc_Print( -2, "usage: mfse [-IOWFLC <num>] [-avwh]\n" );
     Abc_Print( -2, "\t           performs don't-care-based optimization of logic networks\n" );
-    Abc_Print( -2, "\t-M <num> : the max number of fanin nodes to skip (num >= 1) [default = %d]\n",            pPars->nTabooMax );
-    Abc_Print( -2, "\t-D <num> : the max number of divisors [default = %d]\n",                                  pPars->nDivMax );
+    Abc_Print( -2, "\t-I <num> : the number of levels in the TFI cone (2 <= num) [default = %d]\n",             pPars->nTfiLevMax );
     Abc_Print( -2, "\t-O <num> : the number of levels in the TFO cone (0 <= num) [default = %d]\n",             pPars->nTfoLevMax );
+    Abc_Print( -2, "\t-W <num> : the max number of nodes in the window (1 <= num) [default = %d]\n",            pPars->nWinNodeMax );
     Abc_Print( -2, "\t-F <num> : the max number of fanouts to skip (1 <= num) [default = %d]\n",                pPars->nFanoutMax );
     Abc_Print( -2, "\t-L <num> : the max increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel );
     Abc_Print( -2, "\t-C <num> : the max number of conflicts in one SAT run (0 = no limit) [default = %d]\n",   pPars->nBTLimit );
diff --git a/src/base/acb/acb.h b/src/base/acb/acb.h
index 6954010b..f12fa482 100644
--- a/src/base/acb/acb.h
+++ b/src/base/acb/acb.h
@@ -503,7 +503,10 @@ static inline void Acb_ObjRemoveFaninFanout( Acb_Ntk_t * p, int iObj )
 {
     int k, iFanin, * pFanins; 
     Acb_ObjForEachFaninFast( p, iObj, pFanins, iFanin, k )
-        Vec_IntRemove( Vec_WecEntry(&p->vFanouts, iFanin), iObj );
+    {
+        int RetValue = Vec_IntRemove( Vec_WecEntry(&p->vFanouts, iFanin), iObj );
+        assert( RetValue );
+    }
 }
 static inline void Acb_NtkCreateFanout( Acb_Ntk_t * p )
 {
diff --git a/src/base/acb/acbAbc.c b/src/base/acb/acbAbc.c
index dd97816c..d3c511ff 100644
--- a/src/base/acb/acbAbc.c
+++ b/src/base/acb/acbAbc.c
@@ -210,10 +210,9 @@ void Acb_ParSetDefault( Acb_Par_t * pPars )
     memset( pPars, 0, sizeof(Acb_Par_t) );
     pPars->nLutSize     =    4;    // LUT size
     pPars->nTfoLevMax   =    2;    // the maximum fanout levels
-    pPars->nTfiLevMax   =    2;    // the maximum fanin levels
+    pPars->nTfiLevMax   =    3;    // the maximum fanin levels
     pPars->nFanoutMax   =   20;    // the maximum number of fanouts
-    pPars->nDivMax      =   24;    // the maximum divisor count
-    pPars->nTabooMax    =    1;    // the minimum MFFC size
+    pPars->nWinNodeMax  =  100;    // the maximum number of nodes in the window
     pPars->nGrowthLevel =    0;    // the maximum allowed growth in level
     pPars->nBTLimit     =    0;    // the maximum number of conflicts in one SAT run
     pPars->nNodesMax    =    0;    // the maximum number of nodes to try
diff --git a/src/base/acb/acbMfs.c b/src/base/acb/acbMfs.c
index 64a74798..7d69bf9d 100644
--- a/src/base/acb/acbMfs.c
+++ b/src/base/acb/acbMfs.c
@@ -31,6 +31,8 @@ ABC_NAMESPACE_IMPL_START
 ///                        DECLARATIONS                              ///
 ////////////////////////////////////////////////////////////////////////
 
+static inline int Acb_ObjIsCritFanin( Acb_Ntk_t * p, int i, int f )  { return !Acb_ObjIsCi(p, f) && Acb_ObjLevelR(p, i) + Acb_ObjLevelD(p, f) == p->LevelMax; }
+
 ////////////////////////////////////////////////////////////////////////
 ///                     FUNCTION DEFINITIONS                         ///
 ////////////////////////////////////////////////////////////////////////
@@ -164,10 +166,7 @@ Cnf_Dat_t * Acb_NtkWindow2Cnf( Acb_Ntk_t * p, Vec_Int_t * vWinObjs, int Pivot )
     Vec_Int_t * vLits = Vec_IntAlloc( 1000 );
     // mark new SAT variables
     Vec_IntForEachEntry( vWinObjs, iObj, i )
-    {
         Acb_ObjSetFunc( p, Abc_Lit2Var(iObj), i );
-//printf( "Node %d -> SAT var %d\n", Vec_IntEntry(&p->vArray2, Abc_Lit2Var(iObj)), i );
-    }
     // add clauses for all nodes
     Vec_IntPush( vClas, Vec_IntSize(vLits) );
     Vec_IntForEachEntry( vWinObjs, iObjLit, i )
@@ -224,9 +223,6 @@ Cnf_Dat_t * Acb_NtkWindow2Cnf( Acb_Ntk_t * p, Vec_Int_t * vWinObjs, int Pivot )
         assert( nVars == nVarsAll );
     }
     Vec_IntFree( vFaninVars );
-    // undo SAT variables
-    Vec_IntForEachEntry( vWinObjs, iObj, i )
-        Vec_IntWriteEntry( &p->vObjFunc, Abc_Lit2Var(iObj), -1 );
     // create CNF structure
     pCnf = ABC_CALLOC( Cnf_Dat_t, 1 );
     pCnf->nVars     = nVarsAll;
@@ -242,7 +238,15 @@ Cnf_Dat_t * Acb_NtkWindow2Cnf( Acb_Ntk_t * p, Vec_Int_t * vWinObjs, int Pivot )
     //Cnf_DataPrint( pCnf, 1 );
     return pCnf;
 }
-
+void Acb_NtkWindowUndo( Acb_Ntk_t * p, Vec_Int_t * vWin )
+{
+    int i, iObj;
+    Vec_IntForEachEntry( vWin, iObj, i )
+    {
+        assert( Vec_IntEntry(&p->vObjFunc, Abc_Lit2Var(iObj)) != -1 );
+        Vec_IntWriteEntry( &p->vObjFunc, Abc_Lit2Var(iObj), -1 );
+    }
+}
 
 /**Function*************************************************************
 
@@ -255,33 +259,29 @@ Cnf_Dat_t * Acb_NtkWindow2Cnf( Acb_Ntk_t * p, Vec_Int_t * vWinObjs, int Pivot )
   SeeAlso     []
 
 ***********************************************************************/
-int Acb_NtkWindow2Solver( sat_solver * pSat, Cnf_Dat_t * pCnf, int PivotVar, int nDivs, int nTimes )
+int Acb_NtkWindow2Solver( sat_solver * pSat, Cnf_Dat_t * pCnf, Vec_Int_t * vFlip, int PivotVar, int nDivs, int nTimes )
 {
-    int n, i, RetValue, nRounds = nTimes <= 2 ? nTimes-1 : 2;
-    Vec_Int_t * vFlips = Cnf_DataCollectFlipLits( pCnf, PivotVar );
-    sat_solver_setnvars( pSat, nTimes * pCnf->nVars + nRounds * nDivs + 1 );
+    int n, i, RetValue, Test = pCnf->pClauses[0][0];
+    int nGroups = nTimes <= 2 ? nTimes-1 : 2;
+    int nRounds = nTimes <= 2 ? nTimes-1 : nTimes;
+    assert( sat_solver_nvars(pSat) == 0 );
+    sat_solver_setnvars( pSat, nTimes * pCnf->nVars + nGroups * nDivs + 1 );
     assert( nTimes == 1 || nTimes == 2 || nTimes == 6 );
     for ( n = 0; n < nTimes; n++ )
     {
         if ( n & 1 )
-            Cnf_DataLiftAndFlipLits( pCnf, -pCnf->nVars, vFlips );
+            Cnf_DataLiftAndFlipLits( pCnf, -pCnf->nVars, vFlip );
         for ( i = 0; i < pCnf->nClauses; i++ )
-        {
             if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
-            {
-                Vec_IntFree( vFlips );
-                sat_solver_delete( pSat );
-                return 0;
-            }
-        }
+                printf( "Error: SAT solver became UNSAT at a wrong place.\n" );
         if ( n & 1 )
-            Cnf_DataLiftAndFlipLits( pCnf, pCnf->nVars, vFlips );
+            Cnf_DataLiftAndFlipLits( pCnf, pCnf->nVars, vFlip );
         if ( n < nTimes - 1 )
             Cnf_DataLift( pCnf, pCnf->nVars );
         else if ( n ) // if ( n == nTimes - 1 )
             Cnf_DataLift( pCnf, -(nTimes - 1) * pCnf->nVars );
     }
-    Vec_IntFree( vFlips );
+    assert( Test == pCnf->pClauses[0][0] );
     // add conditional buffers
     for ( n = 0; n < nRounds; n++ )
     {
@@ -293,17 +293,87 @@ int Acb_NtkWindow2Solver( sat_solver * pSat, Cnf_Dat_t * pCnf, int PivotVar, int
     }
     // finalize
     RetValue = sat_solver_simplify( pSat );
-    if ( RetValue == 0 )
+    if ( !RetValue ) printf( "Error: SAT solver became UNSAT at a wrong place.\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes function of the node]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word Acb_ComputeFunction( sat_solver * pSat, int PivotVar, int FreeVar, Vec_Int_t * vDivVars )
+{
+    int fExpand = 0;
+    word uCube, uTruth = 0;
+    Vec_Int_t * vTempLits = Vec_IntAlloc( 100 );
+    int status, i, iVar, iLit, nFinal, * pFinal, pLits[2];
+    assert( FreeVar < sat_solver_nvars(pSat) );
+    pLits[0] = Abc_Var2Lit( PivotVar, 0 ); // F = 1
+    pLits[1] = Abc_Var2Lit( FreeVar, 0 );  // iNewLit
+    while ( 1 ) 
     {
-        sat_solver_delete( pSat );
-        return 0;    
+        // find onset minterm
+        status = sat_solver_solve( pSat, pLits, pLits + 2, 0, 0, 0, 0 );
+        if ( status == l_False )
+        {
+            Vec_IntFree( vTempLits );
+            return uTruth;
+        }
+        assert( status == l_True );
+        if ( fExpand )
+        {
+            // collect divisor literals
+            Vec_IntFill( vTempLits, 1, Abc_LitNot(pLits[0]) ); // F = 0
+            Vec_IntForEachEntry( vDivVars, iVar, i )
+                Vec_IntPush( vTempLits, sat_solver_var_literal(pSat, iVar) );
+            // check against offset
+            status = sat_solver_solve( pSat, Vec_IntArray(vTempLits), Vec_IntLimit(vTempLits), 0, 0, 0, 0 );
+            if ( status != l_False )
+                printf( "Failed internal check during function comptutation.\n" );
+            assert( status == l_False );
+            // compute cube and add clause
+            nFinal = sat_solver_final( pSat, &pFinal );
+            Vec_IntFill( vTempLits, 1, Abc_LitNot(pLits[1]) ); // NOT(iNewLit)
+            for ( i = 0; i < nFinal; i++ )
+                if ( pFinal[i] != pLits[0] )
+                    Vec_IntPush( vTempLits, pFinal[i] );
+        }
+        else
+        {
+            // collect divisor literals
+            Vec_IntFill( vTempLits, 1, Abc_LitNot(pLits[1]) );// NOT(iNewLit)
+            Vec_IntForEachEntry( vDivVars, iVar, i )
+                Vec_IntPush( vTempLits, Abc_LitNot(sat_solver_var_literal(pSat, iVar)) );
+        }
+        uCube = ~(word)0;
+        Vec_IntForEachEntryStart( vTempLits, iLit, i, 1 )
+        {
+            iVar = Vec_IntFind( vDivVars, Abc_Lit2Var(iLit) );   assert( iVar >= 0 );
+            uCube &= Abc_LitIsCompl(iLit) ? s_Truths6[iVar] : ~s_Truths6[iVar];
+        }
+        uTruth |= uCube;
+        status = sat_solver_addclause( pSat, Vec_IntArray(vTempLits), Vec_IntLimit(vTempLits) );
+        if ( status == 0 )
+        {
+            Vec_IntFree( vTempLits );
+            return uTruth;
+        }
     }
-    return 1;
+    assert( 0 ); 
+    return ~(word)0;
 }
 
 
 
 
+
 /**Function*************************************************************
 
   Synopsis    []
@@ -339,6 +409,14 @@ void Acb_NtkPrintVec2( Acb_Ntk_t * p, Vec_Int_t * vVec, char * pName )
         Acb_NtkPrintNode( p, vVec->pArray[i] );
     printf( "\n" );
 }
+void Acb_NtkPrintVecWin( Acb_Ntk_t * p, Vec_Int_t * vVec, char * pName )
+{
+    int i;
+    printf( "%s: \n", pName );
+    for ( i = 0; i < vVec->nSize; i++ )
+        Acb_NtkPrintNode( p, Abc_Lit2Var(vVec->pArray[i]) );
+    printf( "\n" );
+}
 
 /**Function*************************************************************
 
@@ -351,56 +429,46 @@ void Acb_NtkPrintVec2( Acb_Ntk_t * p, Vec_Int_t * vVec, char * pName )
   SeeAlso     []
 
 ***********************************************************************/
-Vec_Int_t * Acb_NtkDivisors( Acb_Ntk_t * p, int Pivot, int * pTaboo, int nTaboo, int nDivsMax )
+void Acb_NtkDivisors_rec( Acb_Ntk_t * p, int iObj, int nTfiLevMin, Vec_Int_t * vDivs )
+{
+    int k, iFanin, * pFanins;
+//    if ( !Acb_ObjIsCi(p, iObj) && Acb_ObjLevelD(p, iObj) < nTfiLevMin )
+    if ( !Acb_ObjIsCi(p, iObj) && nTfiLevMin < 0 )
+        return;
+    if ( Acb_ObjSetTravIdCur(p, iObj) )
+        return;
+    Acb_ObjForEachFaninFast( p, iObj, pFanins, iFanin, k )
+        Acb_NtkDivisors_rec( p, iFanin, nTfiLevMin-1, vDivs );
+    Vec_IntPush( vDivs, iObj );
+}
+Vec_Int_t * Acb_NtkDivisors( Acb_Ntk_t * p, int Pivot, int nTfiLevMin, int fDelay )
 {
+    int k, iFanin, * pFanins;
     Vec_Int_t * vDivs = Vec_IntAlloc( 100 );
-    Vec_Int_t * vFront = Vec_IntAlloc( 100 );
-    int i, k, iFanin, * pFanins;
-    // mark taboo nodes
     Acb_NtkIncTravId( p );
-    assert( !Acb_ObjIsCio(p, Pivot) );
-    Acb_ObjSetTravIdCur( p, Pivot );
-    for ( i = 0; i < nTaboo; i++ )
+    if ( fDelay ) // delay-oriented
     {
-        assert( !Acb_ObjIsCio(p, pTaboo[i]) );
-        if ( Acb_ObjSetTravIdCur( p, pTaboo[i] ) )
-            assert( 0 );
+        // start from critical fanins
+        assert( Acb_ObjLevelD( p, Pivot ) > 1 );
+        Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
+            if ( Acb_ObjIsCritFanin( p, Pivot, iFanin ) )
+                Acb_NtkDivisors_rec( p, iFanin, nTfiLevMin, vDivs );
+        // add non-critical fanins
+        Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
+            if ( !Acb_ObjIsCritFanin( p, Pivot, iFanin ) )
+                if ( !Acb_ObjSetTravIdCur(p, iFanin) )
+                    Vec_IntPush( vDivs, iFanin );
     }
-    // collect non-taboo fanins of pivot but do not use them as frontier
-    Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
-        if ( !Acb_ObjSetTravIdCur( p, iFanin ) )
-            Vec_IntPush( vDivs, iFanin );
-    // collect non-taboo fanins of taboo nodes and use them as frontier
-    for ( i = 0; i < nTaboo; i++ )
-        Acb_ObjForEachFaninFast( p, pTaboo[i], pFanins, iFanin, k )
-            if ( !Acb_ObjSetTravIdCur( p, iFanin ) )
-            {
-                Vec_IntPush( vDivs, iFanin );
-                if ( !Acb_ObjIsCio(p, iFanin) )
-                    Vec_IntPush( vFront, iFanin );
-            }
-    // select divisors incrementally
-    while ( Vec_IntSize(vFront) > 0 && Vec_IntSize(vDivs) < nDivsMax )
+    else
     {
-        // select the topmost
-        int iObj, iObjMax = -1, LevelMax = -1;
-        Vec_IntForEachEntry( vFront, iObj, k )
-            if ( LevelMax < Acb_ObjLevelD(p, iObj) )
-                LevelMax = Acb_ObjLevelD(p, (iObjMax = iObj));
-        assert( iObjMax > 0 );
-        Vec_IntRemove( vFront, iObjMax );
-        // expand the topmost
-        Acb_ObjForEachFaninFast( p, iObjMax, pFanins, iFanin, k )
-            if ( !Acb_ObjSetTravIdCur( p, iFanin ) )
-            {
+        Acb_NtkDivisors_rec( p, Pivot, nTfiLevMin, vDivs );
+        assert( Vec_IntEntryLast(vDivs) == Pivot );
+        Vec_IntPop( vDivs );
+        // add remaining fanins of the node
+        Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
+            if ( !Acb_ObjSetTravIdCur(p, iFanin) )
                 Vec_IntPush( vDivs, iFanin );
-                if ( !Acb_ObjIsCio(p, iFanin) )
-                    Vec_IntPush( vFront, iFanin );
-            }
     }
-    Vec_IntFree( vFront );
-    // sort them by level
-    Vec_IntSelectSortCost( Vec_IntArray(vDivs), Vec_IntSize(vDivs), &p->vLevelD );
     return vDivs;
 }
 
@@ -445,7 +513,7 @@ void Acb_ObjMarkTfo( Acb_Ntk_t * p, Vec_Int_t * vDivs, int Pivot, int nTfoLevMax
   SeeAlso     []
 
 ***********************************************************************/
-int Acb_ObjLabelTfo_rec( Acb_Ntk_t * p, int iObj, int nTfoLevMax, int nFanMax )
+int Acb_ObjLabelTfo_rec( Acb_Ntk_t * p, int iObj, int nTfoLevMax, int nFanMax, int fFirst )
 {
     int iFanout, i, Diff, fHasNone = 0;
 //printf( "Visiting %d\n", Vec_IntEntry(&p->vArray2, iObj) );
@@ -454,27 +522,28 @@ int Acb_ObjLabelTfo_rec( Acb_Ntk_t * p, int iObj, int nTfoLevMax, int nFanMax )
     Acb_ObjSetTravIdDiff( p, iObj, 2 );
     if ( Acb_ObjIsCo(p, iObj) || Acb_ObjLevelD(p, iObj) > nTfoLevMax )
         return 2;
-    if ( Acb_ObjLevelD(p, iObj) == nTfoLevMax || Acb_ObjFanoutNum(p, iObj) >= nFanMax )
+    if ( Acb_ObjLevelD(p, iObj) == nTfoLevMax || Acb_ObjFanoutNum(p, iObj) > nFanMax )
     {
         if ( Diff == 3 )  // belongs to TFO of TFI
             Acb_ObjSetTravIdDiff( p, iObj, 1 ); // root
         return Acb_ObjTravIdDiff(p, iObj);
     }
     Acb_ObjForEachFanout( p, iObj, iFanout, i )
-        fHasNone |= 2 == Acb_ObjLabelTfo_rec( p, iFanout, nTfoLevMax, nFanMax );
+        if ( !fFirst || Acb_ObjIsCritFanin(p, iFanout, iObj) )
+            fHasNone |= 2 == Acb_ObjLabelTfo_rec( p, iFanout, nTfoLevMax, nFanMax, 0 );
     if ( fHasNone && Diff == 3 )  // belongs to TFO of TFI
         Acb_ObjSetTravIdDiff( p, iObj, 1 ); // root
     else if ( !fHasNone )
         Acb_ObjSetTravIdDiff( p, iObj, 0 ); // inner
     return Acb_ObjTravIdDiff(p, iObj);
 }
-int Acb_ObjLabelTfo( Acb_Ntk_t * p, int Root, int nTfoLevMax, int nFanMax )
+int Acb_ObjLabelTfo( Acb_Ntk_t * p, int Root, int nTfoLevMax, int nFanMax, int fDelay )
 {
     Acb_NtkIncTravId( p ); // none  (2)    marked (3)  unmarked (4)
     Acb_NtkIncTravId( p ); // root  (1)
     Acb_NtkIncTravId( p ); // inner (0)
     assert( Acb_ObjTravIdDiff(p, Root) > 2 );
-    return Acb_ObjLabelTfo_rec( p, Root, nTfoLevMax, nFanMax );
+    return Acb_ObjLabelTfo_rec( p, Root, nTfoLevMax, nFanMax, fDelay );
 }
 
 /**Function*************************************************************
@@ -488,7 +557,7 @@ int Acb_ObjLabelTfo( Acb_Ntk_t * p, int Root, int nTfoLevMax, int nFanMax )
   SeeAlso     []
 
 ***********************************************************************/
-void Acb_ObjDeriveTfo_rec( Acb_Ntk_t * p, int iObj, Vec_Int_t * vTfo, Vec_Int_t * vRoots )
+void Acb_ObjDeriveTfo_rec( Acb_Ntk_t * p, int iObj, Vec_Int_t * vTfo, Vec_Int_t * vRoots, int fFirst )
 {
     int iFanout, i, Diff = Acb_ObjTravIdDiff(p, iObj);
     if ( Acb_ObjSetTravIdCur(p, iObj) )
@@ -501,18 +570,19 @@ void Acb_ObjDeriveTfo_rec( Acb_Ntk_t * p, int iObj, Vec_Int_t * vTfo, Vec_Int_t
     }
     assert( Diff == 1 );
     Acb_ObjForEachFanout( p, iObj, iFanout, i )
-        Acb_ObjDeriveTfo_rec( p, iFanout, vTfo, vRoots );
+        if ( !fFirst || Acb_ObjIsCritFanin(p, iFanout, iObj) )
+            Acb_ObjDeriveTfo_rec( p, iFanout, vTfo, vRoots, 0 );
     Vec_IntPush( vTfo, iObj );
 }
-void Acb_ObjDeriveTfo( Acb_Ntk_t * p, int Pivot, int nTfoLevMax, int nFanMax, Vec_Int_t ** pvTfo, Vec_Int_t ** pvRoots )
+void Acb_ObjDeriveTfo( Acb_Ntk_t * p, int Pivot, int nTfoLevMax, int nFanMax, Vec_Int_t ** pvTfo, Vec_Int_t ** pvRoots, int fDelay )
 {
-    int Res = Acb_ObjLabelTfo( p, Pivot, nTfoLevMax, nFanMax );
+    int Res = Acb_ObjLabelTfo( p, Pivot, nTfoLevMax, nFanMax, fDelay );
     Vec_Int_t * vTfo   = *pvTfo   = Vec_IntAlloc( 10 );
     Vec_Int_t * vRoots = *pvRoots = Vec_IntAlloc( 10 );
     if ( Res ) // none or root
         return;
     Acb_NtkIncTravId( p ); // root (2)   inner (1)  visited (0)
-    Acb_ObjDeriveTfo_rec( p, Pivot, vTfo, vRoots );
+    Acb_ObjDeriveTfo_rec( p, Pivot, vTfo, vRoots, fDelay );
     assert( Vec_IntEntryLast(vTfo) == Pivot );
     Vec_IntPop( vTfo );
     assert( Vec_IntEntryLast(vRoots) != Pivot );
@@ -586,15 +656,22 @@ Vec_Int_t * Acb_NtkCollectNewTfi( Acb_Ntk_t * p, int Pivot, Vec_Int_t * vDivs, V
     Vec_Int_t * vTfiNew  = Vec_IntAlloc( 100 );
     int i, Node;
     Acb_NtkIncTravId( p );
-//Acb_NtkPrintVec( p, vDivs, "vDivs" );
+    //Acb_NtkPrintVec( p, vDivs, "vDivs" );
     Vec_IntForEachEntry( vDivs, Node, i )
         Acb_NtkCollectNewTfi1_rec( p, Node, vTfiNew );
-    *pnDivs = Vec_IntSize(vTfiNew);
 //Acb_NtkPrintVec( p, vTfiNew, "vTfiNew" );
     Acb_NtkCollectNewTfi1_rec( p, Pivot, vTfiNew );
 //Acb_NtkPrintVec( p, vTfiNew, "vTfiNew" );
     assert( Vec_IntEntryLast(vTfiNew) == Pivot );
     Vec_IntPop( vTfiNew );
+/*
+    Vec_IntForEachEntry( vDivs, Node, i )
+    {
+        Acb_ObjSetTravIdCur( p, Node );
+        Vec_IntPush( vTfiNew, Node );
+    }
+*/
+    *pnDivs = Vec_IntSize(vTfiNew);
     Vec_IntForEachEntry( vSide, Node, i )
         Acb_NtkCollectNewTfi2_rec( p, Node, vTfiNew );
     Vec_IntPush( vTfiNew, Pivot );
@@ -654,18 +731,19 @@ Vec_Int_t * Acb_NtkCollectWindow( Acb_Ntk_t * p, int Pivot, Vec_Int_t * vTfi, Ve
   SeeAlso     []
 
 ***********************************************************************/
-Vec_Int_t * Acb_NtkWindow( Acb_Ntk_t * p, int Pivot, int * pTaboo, int nTaboo, int nDivsMax, int nTfoLevs, int nFanMax, int * pnDivs )
+Vec_Int_t * Acb_NtkWindow( Acb_Ntk_t * p, int Pivot, int nTfiLevs, int nTfoLevs, int nFanMax, int fDelay, int * pnDivs )
 {
     int fVerbose = 0;
+    //int nTfiLevMin = Acb_ObjLevelD(p, Pivot) - nTfiLevs;
     int nTfoLevMax = Acb_ObjLevelD(p, Pivot) + nTfoLevs;
     Vec_Int_t * vWin, * vDivs, * vTfo, * vRoots, * vSide, * vTfi;
     // collect divisors by traversing limited TFI
-    vDivs = Acb_NtkDivisors( p, Pivot, pTaboo, nTaboo, nDivsMax );
+    vDivs = Acb_NtkDivisors( p, Pivot, nTfiLevs, fDelay );
     if ( fVerbose ) Acb_NtkPrintVec( p, vDivs, "vDivs" );
     // mark limited TFO of the divisors
     Acb_ObjMarkTfo( p, vDivs, Pivot, nTfoLevMax, nFanMax );
     // collect TFO and roots
-    Acb_ObjDeriveTfo( p, Pivot, nTfoLevMax, nFanMax, &vTfo, &vRoots );
+    Acb_ObjDeriveTfo( p, Pivot, nTfoLevMax, nFanMax, &vTfo, &vRoots, fDelay );
     if ( fVerbose ) Acb_NtkPrintVec( p, vTfo, "vTfo" );
     if ( fVerbose ) Acb_NtkPrintVec( p, vRoots, "vRoots" );
     // collect side inputs of the TFO
@@ -689,159 +767,6 @@ Vec_Int_t * Acb_NtkWindow( Acb_Ntk_t * p, int Pivot, int * pTaboo, int nTaboo, i
 
 
 
-/**Function*************************************************************
-
-  Synopsis    [Computes function of the node]
-
-  Description []
-               
-  SideEffects []
-
-  SeeAlso     []
-
-***********************************************************************/
-word Acb_ComputeFunction( sat_solver * pSat, int PivotVar, int FreeVar, Vec_Int_t * vDivVars )
-{
-    int fExpand = 1;
-    word uCube, uTruth = 0;
-    Vec_Int_t * vTempLits = Vec_IntAlloc( 100 );
-    int status, i, iVar, iLit, nFinal, * pFinal, pLits[2];
-    assert( FreeVar < sat_solver_nvars(pSat) );
-    pLits[0] = Abc_Var2Lit( PivotVar, 0 ); // F = 1
-    pLits[1] = Abc_Var2Lit( FreeVar, 0 );  // iNewLit
-    while ( 1 ) 
-    {
-        // find onset minterm
-        status = sat_solver_solve( pSat, pLits, pLits + 2, 0, 0, 0, 0 );
-        if ( status == l_False )
-        {
-            Vec_IntFree( vTempLits );
-            return uTruth;
-        }
-        assert( status == l_True );
-        if ( fExpand )
-        {
-            // collect divisor literals
-            Vec_IntFill( vTempLits, 1, Abc_LitNot(pLits[0]) ); // F = 0
-            Vec_IntForEachEntry( vDivVars, iVar, i )
-                Vec_IntPush( vTempLits, sat_solver_var_literal(pSat, iVar) );
-            // check against offset
-            status = sat_solver_solve( pSat, Vec_IntArray(vTempLits), Vec_IntLimit(vTempLits), 0, 0, 0, 0 );
-            assert( status == l_False );
-            // compute cube and add clause
-            nFinal = sat_solver_final( pSat, &pFinal );
-            Vec_IntFill( vTempLits, 1, Abc_LitNot(pLits[1]) ); // NOT(iNewLit)
-            for ( i = 0; i < nFinal; i++ )
-                if ( pFinal[i] != pLits[0] )
-                    Vec_IntPush( vTempLits, pFinal[i] );
-        }
-        else
-        {
-            // collect divisor literals
-            Vec_IntFill( vTempLits, 1, Abc_LitNot(pLits[1]) );// NOT(iNewLit)
-            Vec_IntForEachEntry( vDivVars, iVar, i )
-                Vec_IntPush( vTempLits, Abc_LitNot(sat_solver_var_literal(pSat, iVar)) );
-        }
-        uCube = ~(word)0;
-        Vec_IntForEachEntryStart( vTempLits, iLit, i, 1 )
-        {
-            iVar = Vec_IntFind( vDivVars, Abc_Lit2Var(iLit) );   assert( iVar >= 0 );
-            uCube &= Abc_LitIsCompl(iLit) ? s_Truths6[iVar] : ~s_Truths6[iVar];
-        }
-        uTruth |= uCube;
-        status = sat_solver_addclause( pSat, Vec_IntArray(vTempLits), Vec_IntLimit(vTempLits) );
-        if ( status == 0 )
-        {
-            Vec_IntFree( vTempLits );
-            return uTruth;
-        }
-    }
-    assert( 0 ); 
-    return ~(word)0;
-}
-
-
-/**Function*************************************************************
-
-  Synopsis    [Collects the taboo nodes (nodes that cannot be divisors).]
-
-  Description []
-               
-  SideEffects []
-
-  SeeAlso     []
-
-***********************************************************************/
-static inline int Acb_ObjIsCritFanin( Acb_Ntk_t * p, int i, int f )  { return Acb_ObjLevelR(p, i) + Acb_ObjLevelD(p, f) == p->LevelMax; }
-
-static inline void Acb_ObjUpdateFanoutCount( Acb_Ntk_t * p, int iObj, int AddOn )
-{
-    int k, iFanin, * pFanins;
-    Acb_ObjForEachFaninFast( p, iObj, pFanins, iFanin, k )
-        Acb_ObjFanoutVec(p, iFanin)->nSize += AddOn;
-}
-
-int Acb_NtkCollectTaboo( Acb_Ntk_t * p, int Pivot, int Next, int nTabooMax, int * pTaboo )
-{
-    int i, k, iFanin, * pFanins, nTaboo = 0;
-    if ( nTabooMax == 0 ) // delay optimization
-    {
-        // collect delay critical fanins of the pivot node
-        Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
-            if ( !Acb_ObjIsCi(p, iFanin) && Acb_ObjIsCritFanin( p, Pivot, iFanin ) )
-                pTaboo[ nTaboo++ ] = iFanin;
-    }
-    else // area optimization
-    {
-        // check if the node has any area critical fanins
-//        Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
-//            if ( !Acb_ObjIsCi(p, iFanin) && Acb_ObjFanoutNum(p, iFanin) == 1 )
-//                break;
-        // collect this critical fanin
-        assert( Next > 0 && !Acb_ObjIsCio(p, Next) && Acb_ObjFanoutNum(p, Next) == 1 );
-        Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
-            if ( iFanin == Next )
-                break;
-        assert( k < Acb_ObjFaninNum(p, Pivot) );
-        if ( k < Acb_ObjFaninNum(p, Pivot) ) // there is fanin
-        {
-            // mark pivot
-            Acb_NtkIncTravId( p );
-            Acb_ObjSetTravIdCur( p, Pivot );
-            Acb_ObjUpdateFanoutCount( p, Pivot, -1 );
-            // add the first taboo node
-            assert( Acb_ObjFanoutNum(p, iFanin) == 0 );
-            pTaboo[ nTaboo++ ] = iFanin;
-            Acb_ObjSetTravIdCur( p, iFanin );
-            Acb_ObjUpdateFanoutCount( p, iFanin, -1 );
-            while ( nTaboo < nTabooMax )
-            {
-                // select the first unrefed fanin
-                for ( i = 0; i < nTaboo; i++ )
-                {
-                    Acb_ObjForEachFaninFast( p, pTaboo[i], pFanins, iFanin, k )
-                        if ( !Acb_ObjIsCi(p, iFanin) && !Acb_ObjIsTravIdCur(p, iFanin) && Acb_ObjFanoutNum(p, iFanin) == 0 )
-                        {
-                            pTaboo[ nTaboo++ ] = iFanin;
-                            Acb_ObjSetTravIdCur( p, iFanin );
-                            Acb_ObjUpdateFanoutCount( p, iFanin, -1 );
-                            break;
-                        }
-                    if ( k < Acb_ObjFaninNum(p, pTaboo[i]) )
-                        break;
-                }
-                if ( i == nTaboo ) // no change
-                    break;
-            }
-            // reference nodes back
-            Acb_ObjUpdateFanoutCount( p, Pivot, 1 );
-            for ( i = 0; i < nTaboo; i++ )
-                Acb_ObjUpdateFanoutCount( p, pTaboo[i], 1 );
-        }
-    }
-    return nTaboo;
-}
-
 /**Function*************************************************************
 
   Synopsis    []
@@ -894,18 +819,280 @@ void Acb_WinPrint( Acb_Ntk_t * p, Vec_Int_t * vWin, int Pivot, int nDivs )
     printf( "\n" );
 }
 
-Vec_Int_t * Acb_NtkFindSupp2( Acb_Ntk_t * p, sat_solver * pSat2, int nVars, int nDivs )
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Acb_NtkReorderFanins( Acb_Ntk_t * p, int Pivot, Vec_Int_t * vSupp, int nDivs, Vec_Int_t * vWin )
 {
-    int nSuppNew;
-    Vec_Int_t * vSupp = Vec_IntStartNatural( nDivs );
-    Vec_IntReverseOrder( vSupp );
+    Vec_Int_t * vDivs = &p->vCover;
+    int * pArrayS = Vec_IntArray( vSupp );
+    int * pArrayD = NULL;
+    int k, j, iFanin, * pFanins, iThis = 0, iThat = -1;
+    // collect divisors
+    Vec_IntClear( vDivs );
+    for ( k = nDivs - 1; k >= 0; k-- )
+        Vec_IntPush( vDivs, Abc_Lit2Var(Vec_IntEntry(vWin, k)) );
+    pArrayD = Vec_IntArray( vDivs );
+    // reorder divisors
+    //Vec_IntPrint( vSupp );
+    Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
+        if ( (iThat = Vec_IntFind(vDivs, iFanin)) >= 0 )
+        {
+            assert( iThis <= iThat );
+            for ( j = iThat; j > iThis; j-- )
+            {
+                ABC_SWAP( int, pArrayS[j], pArrayS[j-1] );
+                ABC_SWAP( int, pArrayD[j], pArrayD[j-1] );
+            }
+            iThis++;
+        }
+    return;
+    Vec_IntPrint( vSupp );
+    Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
+        printf( "%d ", iFanin );
+    printf( "    " );
+    Vec_IntForEachEntryStop( vSupp, iThat, k, Acb_ObjFaninNum(p, Pivot) )
+        printf( "%d ", Abc_Lit2Var(Vec_IntEntry(vWin, iThat)) );
+    printf( "\n" );
+}
+
+int Acb_NtkFindSupp1( Acb_Ntk_t * p, int Pivot, sat_solver * pSat, int nVars, int nDivs, Vec_Int_t * vWin, Vec_Int_t * vSupp )
+{
+    int nSuppNew, status, k, iFanin, * pFanins;
+    Vec_IntClear( vSupp );
+    Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
+    {
+        int iVar = Acb_ObjFunc(p, iFanin);
+        assert( iVar >= 0 && iVar < nDivs );
+        Vec_IntPush( vSupp, iVar );
+    }
+    //Acb_NtkReorderFanins( p, Pivot, vSupp, nDivs, vWin );
     Vec_IntVars2Lits( vSupp, 2*nVars, 0 );
-    nSuppNew = sat_solver_minimize_assumptions( pSat2, Vec_IntArray(vSupp), Vec_IntSize(vSupp), 0 );
+    status = sat_solver_solve( pSat, Vec_IntArray(vSupp), Vec_IntLimit(vSupp), 0, 0, 0, 0 );
+    if ( status != l_False )
+        printf( "Failed internal check at node %d.\n", Pivot );
+    assert( status == l_False );
+    nSuppNew = sat_solver_minimize_assumptions( pSat, Vec_IntArray(vSupp), Vec_IntSize(vSupp), 0 );
     Vec_IntShrink( vSupp, nSuppNew );
     Vec_IntLits2Vars( vSupp, -2*nVars );
-    return vSupp;
+    return Vec_IntSize(vSupp) < Acb_ObjFaninNum(p, Pivot);
 }
 
+static int StrCount = 0;
+
+int Acb_NtkFindSupp2( Acb_Ntk_t * p, int Pivot, sat_solver * pSat, int nVars, int nDivs, Vec_Int_t * vWin, Vec_Int_t * vSupp, int nLutSize, int fDelay )
+{
+    int nSuppNew, status, k, iFanin, * pFanins, k2, iFanin2, * pFanins2;
+    Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
+        assert( Acb_ObjFunc(p, iFanin) >= 0 && Acb_ObjFunc(p, iFanin) < nDivs );
+    if ( fDelay )
+    {
+        // add non-timing-critical fanins
+        int nNonCrits, k2, iFanin2, * pFanins2;
+        assert( Acb_ObjLevelD( p, Pivot ) > 1 );
+        Vec_IntClear( vSupp );
+        Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
+            if ( !Acb_ObjIsCritFanin( p, Pivot, iFanin ) )
+                Vec_IntPush( vSupp, iFanin );
+        nNonCrits = Vec_IntSize(vSupp);
+        // add fanins of timing critical fanins
+        Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
+            if ( Acb_ObjIsCritFanin( p, Pivot, iFanin ) )
+                Acb_ObjForEachFaninFast( p, iFanin, pFanins2, iFanin2, k2 )
+                    Vec_IntPushUnique( vSupp, iFanin2 );
+        assert( nNonCrits < Vec_IntSize(vSupp) );
+        // sort additional fanins by level
+        Vec_IntSelectSortCost( Vec_IntArray(vSupp) + nNonCrits, Vec_IntSize(vSupp) - nNonCrits, &p->vLevelD );
+        // translate to SAT vars
+        Vec_IntForEachEntry( vSupp, iFanin, k )
+        {
+            assert( Acb_ObjFunc(p, iFanin2) >= 0 );
+            Vec_IntWriteEntry( vSupp, k, Acb_ObjFunc(p, iFanin) );
+        }
+        // solve for these fanins
+        Vec_IntVars2Lits( vSupp, 2*nVars, 0 );
+        status = sat_solver_solve( pSat, Vec_IntArray(vSupp), Vec_IntLimit(vSupp), 0, 0, 0, 0 );
+        if ( status != l_False )
+            printf( "Failed internal check at node %d.\n", Pivot );
+        assert( status == l_False );
+        nSuppNew = sat_solver_minimize_assumptions( pSat, Vec_IntArray(vSupp), Vec_IntSize(vSupp), 0 );
+        Vec_IntShrink( vSupp, nSuppNew );
+        Vec_IntLits2Vars( vSupp, -2*nVars );
+        return Vec_IntSize(vSupp) <= nLutSize;
+    }
+    // iterate through different fanout free cones
+    Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
+    {
+        if ( Acb_ObjIsCi(p, iFanin) || Acb_ObjFanoutNum(p, iFanin) != 1 )
+            continue;
+        // collect fanins of the root node
+        Vec_IntClear( vSupp );
+        Acb_ObjForEachFaninFast( p, Pivot, pFanins2, iFanin2, k2 )
+            if ( iFanin != iFanin2 )
+                Vec_IntPush( vSupp, iFanin2 );
+        // collect fanins fo the selected node
+        Acb_ObjForEachFaninFast( p, iFanin, pFanins2, iFanin2, k2 )
+            Vec_IntPushUnique( vSupp, iFanin2 );
+        // sort fanins by level
+        Vec_IntSelectSortCost( Vec_IntArray(vSupp), Vec_IntSize(vSupp), &p->vLevelD );
+        // translate to SAT vars
+        Vec_IntForEachEntry( vSupp, iFanin2, k2 )
+        {
+            assert( Acb_ObjFunc(p, iFanin2) >= 0 );
+            Vec_IntWriteEntry( vSupp, k2, Acb_ObjFunc(p, iFanin2) );
+        }
+        // solve for these fanins
+        Vec_IntVars2Lits( vSupp, 2*nVars, 0 );
+        status = sat_solver_solve( pSat, Vec_IntArray(vSupp), Vec_IntLimit(vSupp), 0, 0, 0, 0 );
+        if ( status != l_False )
+            printf( "Failed internal check at node %d.\n", Pivot );
+        assert( status == l_False );
+        nSuppNew = sat_solver_minimize_assumptions( pSat, Vec_IntArray(vSupp), Vec_IntSize(vSupp), 0 );
+        Vec_IntShrink( vSupp, nSuppNew );
+        Vec_IntLits2Vars( vSupp, -2*nVars );
+        if ( Vec_IntSize(vSupp) <= nLutSize )
+            return 1;
+    }
+    return 0;
+}
+
+int Acb_NtkFindSupp3( Acb_Ntk_t * p, int Pivot, sat_solver * pSat, int nVars, int nDivs, Vec_Int_t * vWin, Vec_Int_t * vSupp, int nLutSize, int fDelay )
+{
+    int nSuppNew, status, k, iFanin, * pFanins, k2, iFanin2, * pFanins2, k3, iFanin3, * pFanins3, NodeMark;
+
+    if ( fDelay )
+        return 0;
+
+    // iterate through pairs of fanins with one fanouts
+    Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
+    {
+        if ( Acb_ObjIsCi(p, iFanin) || Acb_ObjFanoutNum(p, iFanin) != 1 )
+            continue;
+        Acb_ObjForEachFaninFast( p, Pivot, pFanins2, iFanin2, k2 )
+        {
+            if ( Acb_ObjIsCi(p, iFanin2) || Acb_ObjFanoutNum(p, iFanin2) != 1 || k2 == k )
+                continue;
+            // iFanin and iFanin2 have 1 fanout
+            assert( iFanin != iFanin2 );
+
+            // collect fanins of the root node
+            Vec_IntClear( vSupp );
+            Acb_ObjForEachFaninFast( p, Pivot, pFanins3, iFanin3, k3 )
+                if ( iFanin3 != iFanin && iFanin3 != iFanin2 )
+                {
+                    assert( Acb_ObjFunc(p, iFanin3) >= 0 );
+                    Vec_IntPush( vSupp, Abc_Var2Lit(Acb_ObjFunc(p, iFanin3) + 6*nVars, 0) );
+                }
+            NodeMark = Vec_IntSize(vSupp);
+
+            // collect fanins of the second node
+            Acb_ObjForEachFaninFast( p, iFanin, pFanins3, iFanin3, k3 )
+            {
+                assert( Acb_ObjFunc(p, iFanin3) >= 0 );
+                Vec_IntPush( vSupp, Abc_Var2Lit(Acb_ObjFunc(p, iFanin3) + 6*nVars + nDivs, 0) );
+            }
+            // collect fanins of the third node
+            Acb_ObjForEachFaninFast( p, iFanin2, pFanins3, iFanin3, k3 )
+            {
+                assert( Acb_ObjFunc(p, iFanin3) >= 0 );
+                Vec_IntPushUnique( vSupp, Abc_Var2Lit(Acb_ObjFunc(p, iFanin3) + 6*nVars + nDivs, 0) );
+            }
+            assert( Vec_IntCheckUniqueSmall(vSupp) );
+
+            // sort fanins by level
+            //Vec_IntSelectSortCost( Vec_IntArray(vSupp) + NodeMark, Vec_IntSize(vSupp) - NodeMark, &p->vLevelD );
+            // solve for these fanins
+            status = sat_solver_solve( pSat, Vec_IntArray(vSupp), Vec_IntLimit(vSupp), 0, 0, 0, 0 );
+            if ( status != l_False )
+                continue;
+            assert( status == l_False );
+            nSuppNew = sat_solver_minimize_assumptions( pSat, Vec_IntArray(vSupp), Vec_IntSize(vSupp), 0 );
+            Vec_IntShrink( vSupp, nSuppNew );
+            Vec_IntLits2Vars( vSupp, -6*nVars );
+            Vec_IntSort( vSupp, 0 );
+            // count how many belong to H; the rest belong to G
+            NodeMark = 0;
+            Vec_IntForEachEntry( vSupp, iFanin3, k3 )
+                if ( iFanin3 < nDivs )
+                    NodeMark++;
+                else 
+                    Vec_IntWriteEntry( vSupp, k3, iFanin3 - nDivs );
+            //assert( NodeMark > 0 );
+            if ( Vec_IntSize(vSupp) - NodeMark <= nLutSize )
+                return NodeMark;
+        }
+    }
+
+    // iterate through fanins with one fanout and their fanins with one fanout
+    Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
+    {
+        if ( Acb_ObjIsCi(p, iFanin) || Acb_ObjFanoutNum(p, iFanin) != 1 )
+            continue;
+        Acb_ObjForEachFaninFast( p, iFanin, pFanins2, iFanin2, k2 )
+        {
+            if ( Acb_ObjIsCi(p, iFanin2) || Acb_ObjFanoutNum(p, iFanin2) != 1 )
+                continue;
+            // iFanin and iFanin2 have 1 fanout
+            assert( iFanin != iFanin2 );
+
+            // collect fanins of the root node
+            Vec_IntClear( vSupp );
+            Acb_ObjForEachFaninFast( p, Pivot, pFanins3, iFanin3, k3 )
+                if ( iFanin3 != iFanin && iFanin3 != iFanin2 )
+                    Vec_IntPush( vSupp, Abc_Var2Lit(Acb_ObjFunc(p, iFanin3) + 6*nVars, 0) );
+            NodeMark = Vec_IntSize(vSupp);
+
+            // collect fanins of the second node
+            Acb_ObjForEachFaninFast( p, iFanin, pFanins3, iFanin3, k3 )
+                if ( iFanin3 != iFanin2 )
+                    Vec_IntPush( vSupp, Abc_Var2Lit(Acb_ObjFunc(p, iFanin3) + 6*nVars + nDivs, 0) );
+            // collect fanins of the third node
+            Acb_ObjForEachFaninFast( p, iFanin2, pFanins3, iFanin3, k3 )
+            {
+                assert( Acb_ObjFunc(p, iFanin3) >= 0 );
+                Vec_IntPushUnique( vSupp, Abc_Var2Lit(Acb_ObjFunc(p, iFanin3) + 6*nVars + nDivs, 0) );
+            }
+            assert( Vec_IntCheckUniqueSmall(vSupp) );
+
+            // sort fanins by level
+            //Vec_IntSelectSortCost( Vec_IntArray(vSupp) + NodeMark, Vec_IntSize(vSupp) - NodeMark, &p->vLevelD );
+
+            //Sat_SolverWriteDimacs( pSat, NULL, Vec_IntArray(vSupp), Vec_IntLimit(vSupp), 0 );
+            // solve for these fanins
+            status = sat_solver_solve( pSat, Vec_IntArray(vSupp), Vec_IntLimit(vSupp), 0, 0, 0, 0 );
+            if ( status != l_False )
+                printf( "Failed internal check at node %d.\n", Pivot );
+            assert( status == l_False );
+            nSuppNew = sat_solver_minimize_assumptions( pSat, Vec_IntArray(vSupp), Vec_IntSize(vSupp), 0 );
+            Vec_IntShrink( vSupp, nSuppNew );
+            Vec_IntLits2Vars( vSupp, -6*nVars );
+            // sort by size
+            Vec_IntSort( vSupp, 0 );
+            // count how many belong to H; the rest belong to G
+            NodeMark = 0;
+            Vec_IntForEachEntry( vSupp, iFanin3, k3 )
+                if ( iFanin3 < nDivs )
+                    NodeMark++;
+                else 
+                    Vec_IntWriteEntry( vSupp, k3, iFanin3 - nDivs );
+            assert( NodeMark > 0 );
+            if ( Vec_IntSize(vSupp) - NodeMark <= nLutSize )
+                return NodeMark;
+        }
+    }
+
+    return 0;
+}
+
+
 /**Function*************************************************************
 
   Synopsis    []
@@ -923,12 +1110,14 @@ struct Acb_Mfs_t_
     Acb_Ntk_t *     pNtk;        // network
     Acb_Par_t *     pPars;       // parameters
     sat_solver *    pSat[3];     // SAT solvers
-    int             nOvers;      // overflows
+    Vec_Int_t *     vSupp;       // support
+    Vec_Int_t *     vFlip;       // support
     int             nNodes;      // nodes
     int             nWins;       // windows
     int             nWinsAll;    // windows
     int             nDivsAll;    // windows
-    int             nChanges[3]; // changes
+    int             nChanges[8]; // changes
+    int             nOvers;      // overflows
     abctime         timeTotal;
     abctime         timeCnf;
     abctime         timeSol;
@@ -946,55 +1135,55 @@ Acb_Mfs_t * Acb_MfsStart( Acb_Ntk_t * pNtk, Acb_Par_t * pPars )
     p->pSat[0]    = sat_solver_new();
     p->pSat[1]    = sat_solver_new();
     p->pSat[2]    = sat_solver_new();
+    p->vSupp      = Vec_IntAlloc(100);
+    p->vFlip      = Vec_IntAlloc(100);
     return p;
 }
 void Acb_MfsStop( Acb_Mfs_t * p )
 {
+    Vec_IntFree( p->vFlip );
+    Vec_IntFree( p->vSupp );
     sat_solver_delete( p->pSat[0] );
     sat_solver_delete( p->pSat[1] );
     sat_solver_delete( p->pSat[2] );
     ABC_FREE( p );
 }
-int Acb_NtkOptNode( Acb_Mfs_t * p, int Pivot, int Next )
+int Acb_NtkOptNode( Acb_Mfs_t * p, int Pivot )
 {
-    Cnf_Dat_t * pCnf; abctime clk;
-    Vec_Int_t * vWin, * vSupp = NULL;
-    int c, PivotVar, nDivs = 0, RetValue = 0; word uTruth;
-    int pTaboo[16], nTaboo = Acb_NtkCollectTaboo( p->pNtk, Pivot, Next, p->pPars->nTabooMax, pTaboo );
-    if ( nTaboo == 0 )
-        return RetValue;
+    Cnf_Dat_t * pCnf = NULL; abctime clk;
+    Vec_Int_t * vWin = NULL; word uTruth;
+    int Result, PivotVar, nDivs = 0, RetValue = 0, c;
     p->nWins++;
-    assert( p->pPars->nTabooMax == 0 || nTaboo <= p->pPars->nTabooMax );
-    assert( nTaboo <= 16 );
-    //printf( "Trying node %d with fanin %d\n", Pivot, Next );
 
     // compute divisors and window for this target node with these taboo nodes
     clk = Abc_Clock();
-    vWin = Acb_NtkWindow( p->pNtk, Pivot, pTaboo, nTaboo, p->pPars->nDivMax, p->pPars->nTfoLevMax, p->pPars->nFanoutMax, &nDivs );
+    vWin = Acb_NtkWindow( p->pNtk, Pivot, p->pPars->nTfiLevMax, p->pPars->nTfoLevMax, p->pPars->nFanoutMax, !p->pPars->fArea, &nDivs );
     p->nWinsAll += Vec_IntSize(vWin);
     p->nDivsAll += nDivs;
     p->timeWin  += Abc_Clock() - clk;
     PivotVar = Vec_IntFind( vWin, Abc_Var2Lit(Pivot, 0) );
     if ( p->pPars->fVerbose )
     printf( "Node %d: Window contains %d objects and %d divisors.  ", Vec_IntEntry(&p->pNtk->vArray2, Pivot), Vec_IntSize(vWin), nDivs );
-//    Acb_WinPrint( p, vWin, Pivot, nDivs );
-//    return;
-    if ( nDivs >= 2 * p->pPars->nDivMax )
+//    Acb_WinPrint( p->pNtk, vWin, Pivot, nDivs );
+//    Acb_NtkPrintVecWin( p->pNtk, vWin, "Win" );
+    if ( Vec_IntSize(vWin) > p->pPars->nWinNodeMax )
     {
         p->nOvers++;
         if ( p->pPars->fVerbose )
             printf( "Too many divisors.\n" );
-        Vec_IntFree( vWin );
-        return RetValue;
+        goto cleanup;
     }
 
     // derive CNF 
     clk = Abc_Clock();
-    pCnf  = Acb_NtkWindow2Cnf( p->pNtk, vWin, Pivot );
+    pCnf = Acb_NtkWindow2Cnf( p->pNtk, vWin, Pivot );
+    assert( PivotVar == Acb_ObjFunc(p->pNtk, Pivot) );
+    Cnf_DataCollectFlipLits( pCnf, PivotVar, p->vFlip );
     p->timeCnf += Abc_Clock() - clk;
+
     // derive SAT solver
     clk = Abc_Clock();
-    Acb_NtkWindow2Solver( p->pSat[0], pCnf, PivotVar, nDivs, 1 );
+    Acb_NtkWindow2Solver( p->pSat[0], pCnf, p->vFlip, PivotVar, nDivs, 1 );
     p->timeSol += Abc_Clock() - clk;
     // check constants
     for ( c = 0; c < 2; c++ )
@@ -1015,29 +1204,98 @@ int Acb_NtkOptNode( Acb_Mfs_t * p, int Pivot, int Next )
 
     // derive SAT solver
     clk = Abc_Clock();
-    Acb_NtkWindow2Solver( p->pSat[1], pCnf, PivotVar, nDivs, 2 );
+    Acb_NtkWindow2Solver( p->pSat[1], pCnf, p->vFlip, PivotVar, nDivs, 2 );
     p->timeSol += Abc_Clock() - clk;
+
+    // try to remove useless fanins
+    if ( p->pPars->fArea )
+    {
+        clk = Abc_Clock();
+        Result = Acb_NtkFindSupp1( p->pNtk, Pivot, p->pSat[1], pCnf->nVars, nDivs, vWin, p->vSupp );
+        p->timeSat += Abc_Clock() - clk;
+        if ( Result )
+        {
+            if ( Vec_IntSize(p->vSupp) == 0 )
+                p->nChanges[0]++;
+            else
+                p->nChanges[1]++;
+            assert( Vec_IntSize(p->vSupp) < p->pPars->nLutSize );
+            if ( p->pPars->fVerbose )
+            printf( "Found %d inputs: ", Vec_IntSize(p->vSupp) );
+            uTruth = Acb_ComputeFunction( p->pSat[0], PivotVar, sat_solver_nvars(p->pSat[0])-1, p->vSupp );
+            if ( p->pPars->fVerbose )
+            Extra_PrintHex( stdout, (unsigned *)&uTruth, Vec_IntSize(p->vSupp) ); 
+            if ( p->pPars->fVerbose )
+            printf( "\n" );
+            // create support in terms of nodes
+            Vec_IntRemap( p->vSupp, vWin );
+            Vec_IntLits2Vars( p->vSupp, 0 );
+            Acb_NtkUpdateNode( p->pNtk, Pivot, uTruth, p->vSupp );
+            RetValue = 1;
+            goto cleanup;
+        }
+    }
+
     // check for one-node implementation
     clk = Abc_Clock();
-    vSupp = Acb_NtkFindSupp2( p->pNtk, p->pSat[1], pCnf->nVars, nDivs );
+    Result = Acb_NtkFindSupp2( p->pNtk, Pivot, p->pSat[1], pCnf->nVars, nDivs, vWin, p->vSupp, p->pPars->nLutSize, !p->pPars->fArea );
     p->timeSat += Abc_Clock() - clk;
-    if ( Vec_IntSize(vSupp) <= p->pPars->nLutSize )
+    if ( Result )
     {
-        p->nChanges[1]++;
+        p->nChanges[2]++;
+        assert( Vec_IntSize(p->vSupp) <= p->pPars->nLutSize );
+        if ( p->pPars->fVerbose )
+        printf( "Found %d inputs: ", Vec_IntSize(p->vSupp) );
+        uTruth = Acb_ComputeFunction( p->pSat[0], PivotVar, sat_solver_nvars(p->pSat[0])-1, p->vSupp );
         if ( p->pPars->fVerbose )
-        printf( "Found %d inputs: ", Vec_IntSize(vSupp) );
+        Extra_PrintHex( stdout, (unsigned *)&uTruth, Vec_IntSize(p->vSupp) ); 
+        if ( p->pPars->fVerbose )
+        printf( "\n" );
+        // create support in terms of nodes
+        Vec_IntRemap( p->vSupp, vWin );
+        Vec_IntLits2Vars( p->vSupp, 0 );
+        Acb_NtkUpdateNode( p->pNtk, Pivot, uTruth, p->vSupp );
+        RetValue = 1;
+        goto cleanup;
+    }
+
+#if 0
+    // derive SAT solver
+    clk = Abc_Clock();
+    Acb_NtkWindow2Solver( p->pSat[2], pCnf, p->vFlip, PivotVar, nDivs, 6 );
+    p->timeSol += Abc_Clock() - clk;
+
+    // check for two-node implementation
+    clk = Abc_Clock();
+    Result = Acb_NtkFindSupp3( p->pNtk, Pivot, p->pSat[2], pCnf->nVars, nDivs, vWin, p->vSupp, p->pPars->nLutSize, !p->pPars->fArea );
+    p->timeSat += Abc_Clock() - clk;
+    if ( Result )
+    {
+        p->nChanges[3]++;
+        assert( Result                       <  p->pPars->nLutSize );
+        assert( Vec_IntSize(p->vSupp)-Result <= p->pPars->nLutSize );
+        //if ( p->pPars->fVerbose )
+        printf( "Found %d Hvars and %d Gvars: ", Result, Vec_IntSize(p->vSupp)-Result );
+
+        /*
         uTruth = Acb_ComputeFunction( p->pSat[1], PivotVar, sat_solver_nvars(p->pSat[1])-1, vSupp );
         if ( p->pPars->fVerbose )
-        Extra_PrintHex( stdout, (unsigned *)&uTruth, Vec_IntSize(vSupp) ); 
+        Extra_PrintHex( stdout, (unsigned *)&uTruth, Vec_IntSize(p->vSupp) ); 
         if ( p->pPars->fVerbose )
         printf( "\n" );
         // create support in terms of nodes
-        Vec_IntRemap( vSupp, vWin );
+        Vec_IntRemap( p->vSupp, vWin );
         Vec_IntLits2Vars( vSupp, 0 );
-        Acb_NtkUpdateNode( p->pNtk, Pivot, uTruth, vSupp );
+        Acb_NtkUpdateNode( p->pNtk, Pivot, uTruth, p->vSupp );
         RetValue = 1;
+        */
+
+        //if ( p->pPars->fVerbose )
+        printf( "\n" );
         goto cleanup;
     }
+#endif
+
     if ( p->pPars->fVerbose )
     printf( "\n" );
 
@@ -1045,30 +1303,13 @@ cleanup:
     sat_solver_restart( p->pSat[0] );
     sat_solver_restart( p->pSat[1] );
     sat_solver_restart( p->pSat[2] );
-    Cnf_DataFree( pCnf );
-    Vec_IntFree( vWin );
-    Vec_IntFreeP( &vSupp );
-    return RetValue;
-}
-void Acb_NtkOptNodeTop( Acb_Mfs_t * p, int Pivot )
-{
-    if ( p->pPars->fArea )
-    {
-        p->nNodes++;
-        while ( 1 )
-        {
-            int k, iFanin, * pFanins;
-            Acb_ObjForEachFaninFast( p->pNtk, Pivot, pFanins, iFanin, k )
-                if ( !Acb_ObjIsCi(p->pNtk, iFanin) && Acb_ObjFanoutNum(p->pNtk, iFanin) == 1 && Acb_NtkOptNode(p, Pivot, iFanin) )
-                    break;
-            if ( k == Acb_ObjFaninNum(p->pNtk, Pivot) ) // no change
-                break;
-        }
-    }
-    else
+    if ( pCnf ) 
     {
-        assert( 0 );
+        Cnf_DataFree( pCnf );
+        Acb_NtkWindowUndo( p->pNtk, vWin );
     }
+    Vec_IntFreeP( &vWin );
+    return RetValue;
 }
 
 
@@ -1087,8 +1328,8 @@ void Acb_NtkOpt( Acb_Ntk_t * pNtk, Acb_Par_t * pPars )
 {
     Acb_Mfs_t * pMan = Acb_MfsStart( pNtk, pPars );
     //if ( pPars->fVerbose )
-        printf( "%s-optimization parameters: TabooMax(M) = %d  DivMax(D) = %d  TfoLev(O) = %d  LutSize = %d\n", 
-            pMan->pPars->fArea ? "Area" : "Delay", pMan->pPars->nTabooMax, pMan->pPars->nDivMax, pMan->pPars->nTfoLevMax, pMan->pPars->nLutSize );
+        printf( "%s-optimization parameters: TfiLev(I) = %d  TfoLev(O) = %d  WinMax(W) = %d  LutSize = %d\n", 
+            pMan->pPars->fArea ? "Area" : "Delay", pMan->pPars->nTfiLevMax, pMan->pPars->nTfoLevMax, pMan->pPars->nWinNodeMax, pMan->pPars->nLutSize );
     Acb_NtkCreateFanout( pMan->pNtk );  // fanout data structure
     Acb_NtkCleanObjFuncs( pMan->pNtk ); // SAT variables
     Acb_NtkCleanObjCnfs( pMan->pNtk );  // CNF representations
@@ -1098,9 +1339,12 @@ void Acb_NtkOpt( Acb_Ntk_t * pNtk, Acb_Par_t * pPars )
         Acb_NtkUpdateLevelD( pMan->pNtk, -1 ); // compute forward logic level
         Acb_NtkForEachNode( pMan->pNtk, iObj )
         {
-            //if ( iObj != 433 )
+            pMan->nNodes++;
+            assert( Acb_ObjFanoutNum(pMan->pNtk, iObj) > 0 );
+            //if ( iObj != 7 )
             //    continue;
-            Acb_NtkOptNodeTop( pMan, iObj );
+            while ( Acb_NtkOptNode(pMan, iObj) && Acb_ObjFaninNum(pMan->pNtk, iObj) );
+//            Acb_NtkOptNode( pMan, iObj );
         }
     }
     else
@@ -1109,18 +1353,20 @@ void Acb_NtkOpt( Acb_Ntk_t * pNtk, Acb_Par_t * pPars )
         while ( Vec_QueTopPriority(pMan->pNtk->vQue) > 0 )
         {
             int iObj = Vec_QuePop(pMan->pNtk->vQue);
+            if ( Acb_ObjLevelD(pMan->pNtk, iObj) == 1 )
+                continue;
             //if ( iObj != 28 )
             //    continue;
-            Acb_NtkOptNodeTop( pMan, iObj ); 
+            Acb_NtkOptNode( pMan, iObj ); 
         }
     }
     //if ( pPars->fVerbose )
     {
         pMan->timeTotal = Abc_Clock() - pMan->timeTotal;
-        printf( "Node = %d  Win = %d (Ave = %d)  DivAve = %d   Change = %d  Const = %d  Node1 = %d  Node2 = %d   Over = %d\n", 
+        printf( "Node = %d  Win = %d (Ave = %d)  DivAve = %d   Change = %d  C = %d  N1 = %d  N2 = %d  N3 = %d   Over = %d  Str = %d\n", 
             pMan->nNodes, pMan->nWins, pMan->nWinsAll/Abc_MaxInt(1, pMan->nWins), pMan->nDivsAll/Abc_MaxInt(1, pMan->nWins),
-            pMan->nChanges[0] + pMan->nChanges[1] + pMan->nChanges[2],
-            pMan->nChanges[0], pMan->nChanges[1], pMan->nChanges[2], pMan->nOvers );
+            pMan->nChanges[0] + pMan->nChanges[1] + pMan->nChanges[2] + pMan->nChanges[3],
+            pMan->nChanges[0], pMan->nChanges[1], pMan->nChanges[2], pMan->nChanges[3], pMan->nOvers, StrCount );
         ABC_PRTP( "Windowing  ", pMan->timeWin,    pMan->timeTotal );
         ABC_PRTP( "CNF compute", pMan->timeCnf,    pMan->timeTotal );
         ABC_PRTP( "Make solver", pMan->timeSol,    pMan->timeTotal );
diff --git a/src/base/acb/acbPar.h b/src/base/acb/acbPar.h
index 4855170c..eb60d753 100644
--- a/src/base/acb/acbPar.h
+++ b/src/base/acb/acbPar.h
@@ -42,8 +42,7 @@ struct Acb_Par_t_
     int             nTfoLevMax;    // the maximum fanout levels
     int             nTfiLevMax;    // the maximum fanin levels
     int             nFanoutMax;    // the maximum number of fanouts
-    int             nDivMax;       // the maximum divisor count
-    int             nTabooMax;     // the minimum MFFC size
+    int             nWinNodeMax;   // the maximum number of nodes in the window
     int             nGrowthLevel;  // the maximum allowed growth in level
     int             nBTLimit;      // the maximum number of conflicts in one SAT run
     int             nNodesMax;     // the maximum number of nodes to try
diff --git a/src/base/acb/acbUtil.c b/src/base/acb/acbUtil.c
index cc8b9f11..bae9ea1a 100644
--- a/src/base/acb/acbUtil.c
+++ b/src/base/acb/acbUtil.c
@@ -308,14 +308,38 @@ void Acb_NtkCreateNode( Acb_Ntk_t * p, word uTruth, Vec_Int_t * vSupp )
     Acb_ObjAddFaninFanout( p, Pivot );
     Acb_ObjComputeLevelD( p, Pivot );
 }
-void Acb_NtkUpdateNode( Acb_Ntk_t * p, int Pivot, word uTruth, Vec_Int_t * vSupp )
+void Acb_NtkResetNode( Acb_Ntk_t * p, int Pivot, word uTruth, Vec_Int_t * vSupp )
 {
+    // remember old fanins
+    int k, iFanin, * pFanins; 
+    Vec_Int_t * vFanins = Vec_IntAlloc( 6 );
+    assert( !Acb_ObjIsCio(p, Pivot) );
+    Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
+        Vec_IntPush( vFanins, iFanin );
+    // update function
     Vec_WrdSetEntry( &p->vObjTruth, Pivot, uTruth );
     Vec_IntErase( Vec_WecEntry(&p->vCnfs, Pivot) );
+    // remove old fanins
     Acb_ObjRemoveFaninFanout( p, Pivot );
     Acb_ObjRemoveFanins( p, Pivot );
-    Acb_ObjAddFanins( p, Pivot, vSupp );
-    Acb_ObjAddFaninFanout( p, Pivot );
+    // add new fanins
+    if ( vSupp != NULL )
+    {
+        assert( Acb_ObjFanoutNum(p, Pivot) > 0 );
+        Acb_ObjAddFanins( p, Pivot, vSupp );
+        Acb_ObjAddFaninFanout( p, Pivot );
+    }
+    else if ( Acb_ObjFanoutNum(p, Pivot) == 0 )
+        Acb_ObjCleanType( p, Pivot );
+    // delete dangling fanins
+    Vec_IntForEachEntry( vFanins, iFanin, k )
+        if ( !Acb_ObjIsCio(p, iFanin) && Acb_ObjFanoutNum(p, iFanin) == 0 )
+            Acb_NtkResetNode( p, iFanin, 0, NULL );
+    Vec_IntFree( vFanins );
+}
+void Acb_NtkUpdateNode( Acb_Ntk_t * p, int Pivot, word uTruth, Vec_Int_t * vSupp )
+{
+    Acb_NtkResetNode( p, Pivot, uTruth, vSupp );
     if ( p->vQue == NULL )
         Acb_NtkUpdateLevelD( p, Pivot );
     else
-- 
cgit v1.2.3


From 44605f5af647cc6963603116091fcbe98080d660 Mon Sep 17 00:00:00 2001
From: Alan Mishchenko <alanmi@berkeley.edu>
Date: Tue, 4 Apr 2017 03:17:24 -0700
Subject: Experiments with don't-cares.

---
 src/base/acb/acb.h     |   4 +-
 src/base/acb/acbMfs.c  | 598 +++++++++++++++++++++++++++++++++++--------------
 src/base/acb/acbUtil.c |   3 +-
 3 files changed, 435 insertions(+), 170 deletions(-)

(limited to 'src/base')

diff --git a/src/base/acb/acb.h b/src/base/acb/acb.h
index f12fa482..17962dc8 100644
--- a/src/base/acb/acb.h
+++ b/src/base/acb/acb.h
@@ -91,6 +91,7 @@ struct Acb_Ntk_t_
     Vec_Flt_t       vCounts;    // priority counts
     Vec_Wec_t       vFanouts;   // fanouts
     Vec_Wec_t       vCnfs;      // CNF
+    Vec_Str_t       vCnf;       // CNF
     // other
     Vec_Que_t *     vQue;       // temporary
     Vec_Int_t       vCover;     // temporary
@@ -572,6 +573,7 @@ static inline void Acb_NtkFree( Acb_Ntk_t * p )
     Vec_FltErase( &p->vCounts );    
     Vec_WecErase( &p->vFanouts );
     Vec_WecErase( &p->vCnfs );    
+    Vec_StrErase( &p->vCnf );    
     // other
     Vec_QueFreeP( &p->vQue );
     Vec_IntErase( &p->vCover );    
@@ -970,7 +972,7 @@ extern int         Acb_NtkComputeLevelD( Acb_Ntk_t * p, Vec_Int_t * vTfo );
 extern void        Acb_NtkUpdateLevelD( Acb_Ntk_t * p, int iObj );
 extern void        Acb_NtkUpdateTiming( Acb_Ntk_t * p, int iObj );
 
-extern void        Acb_NtkCreateNode( Acb_Ntk_t * p, word uTruth, Vec_Int_t * vSupp );
+extern int         Acb_NtkCreateNode( Acb_Ntk_t * p, word uTruth, Vec_Int_t * vSupp );
 extern void        Acb_NtkUpdateNode( Acb_Ntk_t * p, int Pivot, word uTruth, Vec_Int_t * vSupp );
 
 ABC_NAMESPACE_HEADER_END
diff --git a/src/base/acb/acbMfs.c b/src/base/acb/acbMfs.c
index 7d69bf9d..eca83aa9 100644
--- a/src/base/acb/acbMfs.c
+++ b/src/base/acb/acbMfs.c
@@ -31,7 +31,9 @@ ABC_NAMESPACE_IMPL_START
 ///                        DECLARATIONS                              ///
 ////////////////////////////////////////////////////////////////////////
 
-static inline int Acb_ObjIsCritFanin( Acb_Ntk_t * p, int i, int f )  { return !Acb_ObjIsCi(p, f) && Acb_ObjLevelR(p, i) + Acb_ObjLevelD(p, f) == p->LevelMax; }
+static inline int Acb_ObjIsDelayCriticalFanin( Acb_Ntk_t * p, int i, int f )  { return !Acb_ObjIsCi(p, f) && Acb_ObjLevelR(p, i) + Acb_ObjLevelD(p, f) == p->LevelMax; }
+static inline int Acb_ObjIsAreaCritical( Acb_Ntk_t * p, int f )               { return !Acb_ObjIsCi(p, f) && Acb_ObjFanoutNum(p, f) == 1;                              }
+static inline int Acb_ObjIsCritical( Acb_Ntk_t * p, int i, int f, int fDel )  { return fDel ? Acb_ObjIsDelayCriticalFanin(p, i, f) : Acb_ObjIsAreaCritical(p, f);      }
 
 ////////////////////////////////////////////////////////////////////////
 ///                     FUNCTION DEFINITIONS                         ///
@@ -87,10 +89,22 @@ int Acb_DeriveCnfFromTruth( word Truth, int nVars, Vec_Int_t * vCover, Vec_Str_t
         return nCubes;
     }
 }
+
+void Acb_DeriveCnfForWindowOne( Acb_Ntk_t * p, int iObj )
+{
+    Vec_Wec_t * vCnfs = &p->vCnfs;
+    Vec_Str_t * vCnfBase = Acb_ObjCnfs( p, iObj );
+    assert( Vec_StrSize(vCnfBase) == 0 ); // unassigned
+    assert( Vec_WecSize(vCnfs) == Acb_NtkObjNumMax(p) );
+    Acb_DeriveCnfFromTruth( Acb_ObjTruth(p, iObj), Acb_ObjFaninNum(p, iObj), &p->vCover, &p->vCnf );
+    Vec_StrGrow( vCnfBase, Vec_StrSize(&p->vCnf) );
+    memcpy( Vec_StrArray(vCnfBase), Vec_StrArray(&p->vCnf), Vec_StrSize(&p->vCnf) );
+    vCnfBase->nSize = Vec_StrSize(&p->vCnf);
+}
 Vec_Wec_t * Acb_DeriveCnfForWindow( Acb_Ntk_t * p, Vec_Int_t * vWin, int PivotVar )
 {
     Vec_Wec_t * vCnfs = &p->vCnfs;
-    Vec_Str_t * vCnfBase, * vCnf = NULL; int i, iObj;
+    Vec_Str_t * vCnfBase; int i, iObj;
     assert( Vec_WecSize(vCnfs) == Acb_NtkObjNumMax(p) );
     Vec_IntForEachEntry( vWin, iObj, i )
     {
@@ -100,14 +114,8 @@ Vec_Wec_t * Acb_DeriveCnfForWindow( Acb_Ntk_t * p, Vec_Int_t * vWin, int PivotVa
         vCnfBase = Acb_ObjCnfs( p, iObj );
         if ( Vec_StrSize(vCnfBase) > 0 )
             continue;
-        if ( vCnf == NULL )
-            vCnf = Vec_StrAlloc( 1000 );
-        Acb_DeriveCnfFromTruth( Acb_ObjTruth(p, iObj), Acb_ObjFaninNum(p, iObj), &p->vCover, vCnf );
-        Vec_StrGrow( vCnfBase, Vec_StrSize(vCnf) );
-        memcpy( Vec_StrArray(vCnfBase), Vec_StrArray(vCnf), Vec_StrSize(vCnf) );
-        vCnfBase->nSize = Vec_StrSize(vCnf);
+        Acb_DeriveCnfForWindowOne( p, iObj );
     }
-    Vec_StrFreeP( &vCnf );
     return vCnfs;
 }
 
@@ -151,6 +159,34 @@ int Acb_NtkCountRoots( Vec_Int_t * vWinObjs, int PivotVar )
         nRoots += Abc_LitIsCompl(iObjLit);
     return nRoots;
 }
+void Acb_DeriveCnfForNode( Acb_Ntk_t * p, int iObj, sat_solver * pSat, int OutVar )
+{
+    Vec_Wec_t * vCnfs = &p->vCnfs;
+    Vec_Int_t * vFaninVars = &p->vCover;
+    Vec_Int_t * vClas = Vec_IntAlloc( 100 );
+    Vec_Int_t * vLits = Vec_IntAlloc( 100 );
+    int k, iFanin, * pFanins, Prev, This;
+    // collect SAT variables
+    Vec_IntClear( vFaninVars );
+    Acb_ObjForEachFaninFast( p, iObj, pFanins, iFanin, k )
+    {
+        assert( Acb_ObjFunc(p, iFanin) >= 0 );
+        Vec_IntPush( vFaninVars, Acb_ObjFunc(p, iFanin) );
+    }
+    Vec_IntPush( vFaninVars, OutVar );
+    // derive CNF for the node
+    Acb_TranslateCnf( vClas, vLits, (Vec_Str_t *)Vec_WecEntry(vCnfs, iObj), vFaninVars, -1 );
+    // add clauses
+    Prev = 0;
+    Vec_IntForEachEntry( vClas, This, k )
+    {
+        if ( !sat_solver_addclause( pSat, Vec_IntArray(vLits) + Prev, Vec_IntArray(vLits) + This ) )
+            printf( "Error: SAT solver became UNSAT at a wrong place (while adding new CNF).\n" );
+        Prev = This;
+    }
+    Vec_IntFree( vClas );
+    Vec_IntFree( vLits );
+}
 Cnf_Dat_t * Acb_NtkWindow2Cnf( Acb_Ntk_t * p, Vec_Int_t * vWinObjs, int Pivot )
 {
     Cnf_Dat_t * pCnf;
@@ -265,7 +301,7 @@ int Acb_NtkWindow2Solver( sat_solver * pSat, Cnf_Dat_t * pCnf, Vec_Int_t * vFlip
     int nGroups = nTimes <= 2 ? nTimes-1 : 2;
     int nRounds = nTimes <= 2 ? nTimes-1 : nTimes;
     assert( sat_solver_nvars(pSat) == 0 );
-    sat_solver_setnvars( pSat, nTimes * pCnf->nVars + nGroups * nDivs + 1 );
+    sat_solver_setnvars( pSat, nTimes * pCnf->nVars + nGroups * nDivs + 2 );
     assert( nTimes == 1 || nTimes == 2 || nTimes == 6 );
     for ( n = 0; n < nTimes; n++ )
     {
@@ -308,14 +344,17 @@ int Acb_NtkWindow2Solver( sat_solver * pSat, Cnf_Dat_t * pCnf, Vec_Int_t * vFlip
   SeeAlso     []
 
 ***********************************************************************/
-word Acb_ComputeFunction( sat_solver * pSat, int PivotVar, int FreeVar, Vec_Int_t * vDivVars )
+word Acb_ComputeFunction( sat_solver * pSat, int PivotVar, int FreeVar, Vec_Int_t * vDivVars, int fCompl )
 {
     int fExpand = 0;
     word uCube, uTruth = 0;
     Vec_Int_t * vTempLits = Vec_IntAlloc( 100 );
     int status, i, iVar, iLit, nFinal, * pFinal, pLits[2];
     assert( FreeVar < sat_solver_nvars(pSat) );
-    pLits[0] = Abc_Var2Lit( PivotVar, 0 ); // F = 1
+//    if ( fCompl )
+//        pLits[0] = Abc_Var2Lit( sat_solver_nvars(pSat)-2, 0 ); // F = 1
+//    else
+        pLits[0] = Abc_Var2Lit( PivotVar, fCompl ); // F = 1
     pLits[1] = Abc_Var2Lit( FreeVar, 0 );  // iNewLit
     while ( 1 ) 
     {
@@ -366,6 +405,7 @@ word Acb_ComputeFunction( sat_solver * pSat, int PivotVar, int FreeVar, Vec_Int_
             return uTruth;
         }
     }
+    Vec_IntFree( vTempLits );
     assert( 0 ); 
     return ~(word)0;
 }
@@ -451,11 +491,11 @@ Vec_Int_t * Acb_NtkDivisors( Acb_Ntk_t * p, int Pivot, int nTfiLevMin, int fDela
         // start from critical fanins
         assert( Acb_ObjLevelD( p, Pivot ) > 1 );
         Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
-            if ( Acb_ObjIsCritFanin( p, Pivot, iFanin ) )
+            if ( Acb_ObjIsDelayCriticalFanin( p, Pivot, iFanin ) )
                 Acb_NtkDivisors_rec( p, iFanin, nTfiLevMin, vDivs );
         // add non-critical fanins
         Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
-            if ( !Acb_ObjIsCritFanin( p, Pivot, iFanin ) )
+            if ( !Acb_ObjIsDelayCriticalFanin( p, Pivot, iFanin ) )
                 if ( !Acb_ObjSetTravIdCur(p, iFanin) )
                     Vec_IntPush( vDivs, iFanin );
     }
@@ -468,6 +508,18 @@ Vec_Int_t * Acb_NtkDivisors( Acb_Ntk_t * p, int Pivot, int nTfiLevMin, int fDela
         Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
             if ( !Acb_ObjSetTravIdCur(p, iFanin) )
                 Vec_IntPush( vDivs, iFanin );
+/*
+        // start from critical fanins
+        assert( Acb_ObjLevelD( p, Pivot ) > 1 );
+        Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
+            if ( Acb_ObjIsAreaCritical( p, iFanin ) )
+                Acb_NtkDivisors_rec( p, iFanin, nTfiLevMin, vDivs );
+        // add non-critical fanins
+        Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
+            if ( !Acb_ObjIsAreaCritical( p, iFanin ) )
+                if ( !Acb_ObjSetTravIdCur(p, iFanin) )
+                    Vec_IntPush( vDivs, iFanin );
+*/
     }
     return vDivs;
 }
@@ -483,23 +535,34 @@ Vec_Int_t * Acb_NtkDivisors( Acb_Ntk_t * p, int Pivot, int nTfiLevMin, int fDela
   SeeAlso     []
 
 ***********************************************************************/
-void Acb_ObjMarkTfo_rec( Acb_Ntk_t * p, int iObj, int nTfoLevMax, int nFanMax )
+void Acb_ObjMarkTfo_rec( Acb_Ntk_t * p, int iObj, int nTfoLevMax, int nFanMax, Vec_Int_t * vMarked )
 {
     int iFanout, i;
     if ( Acb_ObjSetTravIdCur(p, iObj) )
         return;
+    Vec_IntPush( vMarked, iObj );
     if ( Acb_ObjLevelD(p, iObj) > nTfoLevMax || Acb_ObjFanoutNum(p, iObj) > nFanMax )
         return;
     Acb_ObjForEachFanout( p, iObj, iFanout, i )
-        Acb_ObjMarkTfo_rec( p, iFanout, nTfoLevMax, nFanMax );
+        Acb_ObjMarkTfo_rec( p, iFanout, nTfoLevMax, nFanMax, vMarked );
 }
-void Acb_ObjMarkTfo( Acb_Ntk_t * p, Vec_Int_t * vDivs, int Pivot, int nTfoLevMax, int nFanMax )
+Vec_Int_t * Acb_ObjMarkTfo( Acb_Ntk_t * p, Vec_Int_t * vDivs, int Pivot, int nTfoLevMax, int nFanMax )
 {
+    Vec_Int_t * vMarked = Vec_IntAlloc( 1000 );
     int i, iObj;
     Acb_NtkIncTravId( p );
     Acb_ObjSetTravIdCur( p, Pivot );
+    Vec_IntPush( vMarked, Pivot );
     Vec_IntForEachEntry( vDivs, iObj, i )
-        Acb_ObjMarkTfo_rec( p, iObj, nTfoLevMax, nFanMax );
+        Acb_ObjMarkTfo_rec( p, iObj, nTfoLevMax, nFanMax, vMarked );
+    return vMarked;
+}
+void Acb_ObjMarkTfo2( Acb_Ntk_t * p, Vec_Int_t * vMarked )
+{
+    int i, Node;
+    Acb_NtkIncTravId( p );
+    Vec_IntForEachEntry( vMarked, Node, i )
+        Acb_ObjSetTravIdCur( p, Node );
 }
 
 /**Function*************************************************************
@@ -529,7 +592,7 @@ int Acb_ObjLabelTfo_rec( Acb_Ntk_t * p, int iObj, int nTfoLevMax, int nFanMax, i
         return Acb_ObjTravIdDiff(p, iObj);
     }
     Acb_ObjForEachFanout( p, iObj, iFanout, i )
-        if ( !fFirst || Acb_ObjIsCritFanin(p, iFanout, iObj) )
+        if ( !fFirst || Acb_ObjIsDelayCriticalFanin(p, iFanout, iObj) )
             fHasNone |= 2 == Acb_ObjLabelTfo_rec( p, iFanout, nTfoLevMax, nFanMax, 0 );
     if ( fHasNone && Diff == 3 )  // belongs to TFO of TFI
         Acb_ObjSetTravIdDiff( p, iObj, 1 ); // root
@@ -570,7 +633,7 @@ void Acb_ObjDeriveTfo_rec( Acb_Ntk_t * p, int iObj, Vec_Int_t * vTfo, Vec_Int_t
     }
     assert( Diff == 1 );
     Acb_ObjForEachFanout( p, iObj, iFanout, i )
-        if ( !fFirst || Acb_ObjIsCritFanin(p, iFanout, iObj) )
+        if ( !fFirst || Acb_ObjIsDelayCriticalFanin(p, iFanout, iObj) )
             Acb_ObjDeriveTfo_rec( p, iFanout, vTfo, vRoots, 0 );
     Vec_IntPush( vTfo, iObj );
 }
@@ -736,12 +799,12 @@ Vec_Int_t * Acb_NtkWindow( Acb_Ntk_t * p, int Pivot, int nTfiLevs, int nTfoLevs,
     int fVerbose = 0;
     //int nTfiLevMin = Acb_ObjLevelD(p, Pivot) - nTfiLevs;
     int nTfoLevMax = Acb_ObjLevelD(p, Pivot) + nTfoLevs;
-    Vec_Int_t * vWin, * vDivs, * vTfo, * vRoots, * vSide, * vTfi;
+    Vec_Int_t * vWin, * vDivs, * vMarked, * vTfo, * vRoots, * vSide, * vTfi;
     // collect divisors by traversing limited TFI
     vDivs = Acb_NtkDivisors( p, Pivot, nTfiLevs, fDelay );
     if ( fVerbose ) Acb_NtkPrintVec( p, vDivs, "vDivs" );
     // mark limited TFO of the divisors
-    Acb_ObjMarkTfo( p, vDivs, Pivot, nTfoLevMax, nFanMax );
+    vMarked = Acb_ObjMarkTfo( p, vDivs, Pivot, nTfoLevMax, nFanMax );
     // collect TFO and roots
     Acb_ObjDeriveTfo( p, Pivot, nTfoLevMax, nFanMax, &vTfo, &vRoots, fDelay );
     if ( fVerbose ) Acb_NtkPrintVec( p, vTfo, "vTfo" );
@@ -750,7 +813,9 @@ Vec_Int_t * Acb_NtkWindow( Acb_Ntk_t * p, int Pivot, int nTfiLevs, int nTfoLevs,
     vSide = Acb_NtkCollectTfoSideInputs( p, Pivot, vTfo );
     if ( fVerbose ) Acb_NtkPrintVec( p, vSide, "vSide" );
     // mark limited TFO of the divisors
-    Acb_ObjMarkTfo( p, vDivs, Pivot, nTfoLevMax, nFanMax );
+    //Acb_ObjMarkTfo( p, vDivs, Pivot, nTfoLevMax, nFanMax );
+    Acb_ObjMarkTfo2( p, vMarked );
+    Vec_IntFree( vMarked );
     // collect new TFI
     vTfi = Acb_NtkCollectNewTfi( p, Pivot, vDivs, vSide, pnDivs );
     if ( fVerbose ) Acb_NtkPrintVec( p, vTfi, "vTfi" );
@@ -803,7 +868,7 @@ static inline void Vec_IntRemap( Vec_Int_t * p, Vec_Int_t * vMap )
         p->pArray[i] = Vec_IntEntry(vMap, p->pArray[i]);
 }
 
-void Acb_WinPrint( Acb_Ntk_t * p, Vec_Int_t * vWin, int Pivot, int nDivs )
+static inline void Acb_WinPrint( Acb_Ntk_t * p, Vec_Int_t * vWin, int Pivot, int nDivs )
 {
     int i, Node;
     printf( "Window for node %d with %d divisors:\n", Vec_IntEntry(&p->vArray2, Pivot), nDivs );
@@ -819,6 +884,30 @@ void Acb_WinPrint( Acb_Ntk_t * p, Vec_Int_t * vWin, int Pivot, int nDivs )
     printf( "\n" );
 }
 
+static inline void Acb_NtkOrderByRefCount( Acb_Ntk_t * p, Vec_Int_t * vSupp )
+{
+    int i, j, best_i, nSize = Vec_IntSize(vSupp);
+    int * pArray = Vec_IntArray(vSupp);
+    for ( i = 0; i < nSize-1; i++ )
+    {
+        best_i = i;
+        for ( j = i+1; j < nSize; j++ )
+            if ( Acb_ObjFanoutNum(p, pArray[j]) > Acb_ObjFanoutNum(p, pArray[best_i]) )
+                best_i = j;
+        ABC_SWAP( int, pArray[i], pArray[best_i] );
+    }
+}
+
+static inline void Acb_NtkRemapIntoSatVariables( Acb_Ntk_t * p, Vec_Int_t * vSupp )
+{
+    int k, iFanin;
+    Vec_IntForEachEntry( vSupp, iFanin, k )
+    {
+        assert( Acb_ObjFunc(p, iFanin) >= 0 );
+        Vec_IntWriteEntry( vSupp, k, Acb_ObjFunc(p, iFanin) );
+    }
+}
+
 /**Function*************************************************************
 
   Synopsis    []
@@ -830,51 +919,14 @@ void Acb_WinPrint( Acb_Ntk_t * p, Vec_Int_t * vWin, int Pivot, int nDivs )
   SeeAlso     []
 
 ***********************************************************************/
-void Acb_NtkReorderFanins( Acb_Ntk_t * p, int Pivot, Vec_Int_t * vSupp, int nDivs, Vec_Int_t * vWin )
-{
-    Vec_Int_t * vDivs = &p->vCover;
-    int * pArrayS = Vec_IntArray( vSupp );
-    int * pArrayD = NULL;
-    int k, j, iFanin, * pFanins, iThis = 0, iThat = -1;
-    // collect divisors
-    Vec_IntClear( vDivs );
-    for ( k = nDivs - 1; k >= 0; k-- )
-        Vec_IntPush( vDivs, Abc_Lit2Var(Vec_IntEntry(vWin, k)) );
-    pArrayD = Vec_IntArray( vDivs );
-    // reorder divisors
-    //Vec_IntPrint( vSupp );
-    Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
-        if ( (iThat = Vec_IntFind(vDivs, iFanin)) >= 0 )
-        {
-            assert( iThis <= iThat );
-            for ( j = iThat; j > iThis; j-- )
-            {
-                ABC_SWAP( int, pArrayS[j], pArrayS[j-1] );
-                ABC_SWAP( int, pArrayD[j], pArrayD[j-1] );
-            }
-            iThis++;
-        }
-    return;
-    Vec_IntPrint( vSupp );
-    Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
-        printf( "%d ", iFanin );
-    printf( "    " );
-    Vec_IntForEachEntryStop( vSupp, iThat, k, Acb_ObjFaninNum(p, Pivot) )
-        printf( "%d ", Abc_Lit2Var(Vec_IntEntry(vWin, iThat)) );
-    printf( "\n" );
-}
-
 int Acb_NtkFindSupp1( Acb_Ntk_t * p, int Pivot, sat_solver * pSat, int nVars, int nDivs, Vec_Int_t * vWin, Vec_Int_t * vSupp )
 {
     int nSuppNew, status, k, iFanin, * pFanins;
     Vec_IntClear( vSupp );
     Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
-    {
-        int iVar = Acb_ObjFunc(p, iFanin);
-        assert( iVar >= 0 && iVar < nDivs );
-        Vec_IntPush( vSupp, iVar );
-    }
-    //Acb_NtkReorderFanins( p, Pivot, vSupp, nDivs, vWin );
+        Vec_IntPush( vSupp, iFanin );
+    Acb_NtkOrderByRefCount( p, vSupp );
+    Acb_NtkRemapIntoSatVariables( p, vSupp );
     Vec_IntVars2Lits( vSupp, 2*nVars, 0 );
     status = sat_solver_solve( pSat, Vec_IntArray(vSupp), Vec_IntLimit(vSupp), 0, 0, 0, 0 );
     if ( status != l_False )
@@ -896,16 +948,16 @@ int Acb_NtkFindSupp2( Acb_Ntk_t * p, int Pivot, sat_solver * pSat, int nVars, in
     if ( fDelay )
     {
         // add non-timing-critical fanins
-        int nNonCrits, k2, iFanin2, * pFanins2;
+        int nNonCrits, k2, iFanin2 = 0, * pFanins2;
         assert( Acb_ObjLevelD( p, Pivot ) > 1 );
         Vec_IntClear( vSupp );
         Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
-            if ( !Acb_ObjIsCritFanin( p, Pivot, iFanin ) )
+            if ( !Acb_ObjIsDelayCriticalFanin( p, Pivot, iFanin ) )
                 Vec_IntPush( vSupp, iFanin );
         nNonCrits = Vec_IntSize(vSupp);
         // add fanins of timing critical fanins
         Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
-            if ( Acb_ObjIsCritFanin( p, Pivot, iFanin ) )
+            if ( Acb_ObjIsDelayCriticalFanin( p, Pivot, iFanin ) )
                 Acb_ObjForEachFaninFast( p, iFanin, pFanins2, iFanin2, k2 )
                     Vec_IntPushUnique( vSupp, iFanin2 );
         assert( nNonCrits < Vec_IntSize(vSupp) );
@@ -914,7 +966,7 @@ int Acb_NtkFindSupp2( Acb_Ntk_t * p, int Pivot, sat_solver * pSat, int nVars, in
         // translate to SAT vars
         Vec_IntForEachEntry( vSupp, iFanin, k )
         {
-            assert( Acb_ObjFunc(p, iFanin2) >= 0 );
+            assert( Acb_ObjFunc(p, iFanin) >= 0 );
             Vec_IntWriteEntry( vSupp, k, Acb_ObjFunc(p, iFanin) );
         }
         // solve for these fanins
@@ -931,24 +983,20 @@ int Acb_NtkFindSupp2( Acb_Ntk_t * p, int Pivot, sat_solver * pSat, int nVars, in
     // iterate through different fanout free cones
     Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
     {
-        if ( Acb_ObjIsCi(p, iFanin) || Acb_ObjFanoutNum(p, iFanin) != 1 )
+        if ( !Acb_ObjIsAreaCritical(p, iFanin) )
             continue;
         // collect fanins of the root node
         Vec_IntClear( vSupp );
         Acb_ObjForEachFaninFast( p, Pivot, pFanins2, iFanin2, k2 )
             if ( iFanin != iFanin2 )
                 Vec_IntPush( vSupp, iFanin2 );
-        // collect fanins fo the selected node
+        // collect fanins of the selected node
         Acb_ObjForEachFaninFast( p, iFanin, pFanins2, iFanin2, k2 )
             Vec_IntPushUnique( vSupp, iFanin2 );
         // sort fanins by level
         Vec_IntSelectSortCost( Vec_IntArray(vSupp), Vec_IntSize(vSupp), &p->vLevelD );
-        // translate to SAT vars
-        Vec_IntForEachEntry( vSupp, iFanin2, k2 )
-        {
-            assert( Acb_ObjFunc(p, iFanin2) >= 0 );
-            Vec_IntWriteEntry( vSupp, k2, Acb_ObjFunc(p, iFanin2) );
-        }
+        //Acb_NtkOrderByRefCount( p, vSupp );
+        Acb_NtkRemapIntoSatVariables( p, vSupp );
         // solve for these fanins
         Vec_IntVars2Lits( vSupp, 2*nVars, 0 );
         status = sat_solver_solve( pSat, Vec_IntArray(vSupp), Vec_IntLimit(vSupp), 0, 0, 0, 0 );
@@ -974,11 +1022,11 @@ int Acb_NtkFindSupp3( Acb_Ntk_t * p, int Pivot, sat_solver * pSat, int nVars, in
     // iterate through pairs of fanins with one fanouts
     Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
     {
-        if ( Acb_ObjIsCi(p, iFanin) || Acb_ObjFanoutNum(p, iFanin) != 1 )
+        if ( !Acb_ObjIsAreaCritical(p, iFanin) )
             continue;
         Acb_ObjForEachFaninFast( p, Pivot, pFanins2, iFanin2, k2 )
         {
-            if ( Acb_ObjIsCi(p, iFanin2) || Acb_ObjFanoutNum(p, iFanin2) != 1 || k2 == k )
+            if ( !Acb_ObjIsAreaCritical(p, iFanin2) || k2 == k )
                 continue;
             // iFanin and iFanin2 have 1 fanout
             assert( iFanin != iFanin2 );
@@ -1017,15 +1065,20 @@ int Acb_NtkFindSupp3( Acb_Ntk_t * p, int Pivot, sat_solver * pSat, int nVars, in
             nSuppNew = sat_solver_minimize_assumptions( pSat, Vec_IntArray(vSupp), Vec_IntSize(vSupp), 0 );
             Vec_IntShrink( vSupp, nSuppNew );
             Vec_IntLits2Vars( vSupp, -6*nVars );
-            Vec_IntSort( vSupp, 0 );
+            Vec_IntSort( vSupp, 1 );
             // count how many belong to H; the rest belong to G
             NodeMark = 0;
             Vec_IntForEachEntry( vSupp, iFanin3, k3 )
-                if ( iFanin3 < nDivs )
-                    NodeMark++;
-                else 
+                if ( iFanin3 >= nDivs )
                     Vec_IntWriteEntry( vSupp, k3, iFanin3 - nDivs );
-            //assert( NodeMark > 0 );
+                else 
+                    NodeMark++;
+            if ( NodeMark == 0 )
+            {
+                //printf( "Obj %d: Special case 1 (vars = %d)\n", Pivot, Vec_IntSize(vSupp) );
+                continue;
+            }
+            assert( NodeMark > 0 );
             if ( Vec_IntSize(vSupp) - NodeMark <= nLutSize )
                 return NodeMark;
         }
@@ -1034,11 +1087,11 @@ int Acb_NtkFindSupp3( Acb_Ntk_t * p, int Pivot, sat_solver * pSat, int nVars, in
     // iterate through fanins with one fanout and their fanins with one fanout
     Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k )
     {
-        if ( Acb_ObjIsCi(p, iFanin) || Acb_ObjFanoutNum(p, iFanin) != 1 )
+        if ( !Acb_ObjIsAreaCritical(p, iFanin) )
             continue;
         Acb_ObjForEachFaninFast( p, iFanin, pFanins2, iFanin2, k2 )
         {
-            if ( Acb_ObjIsCi(p, iFanin2) || Acb_ObjFanoutNum(p, iFanin2) != 1 )
+            if ( !Acb_ObjIsAreaCritical(p, iFanin2) )
                 continue;
             // iFanin and iFanin2 have 1 fanout
             assert( iFanin != iFanin2 );
@@ -1064,7 +1117,6 @@ int Acb_NtkFindSupp3( Acb_Ntk_t * p, int Pivot, sat_solver * pSat, int nVars, in
 
             // sort fanins by level
             //Vec_IntSelectSortCost( Vec_IntArray(vSupp) + NodeMark, Vec_IntSize(vSupp) - NodeMark, &p->vLevelD );
-
             //Sat_SolverWriteDimacs( pSat, NULL, Vec_IntArray(vSupp), Vec_IntLimit(vSupp), 0 );
             // solve for these fanins
             status = sat_solver_solve( pSat, Vec_IntArray(vSupp), Vec_IntLimit(vSupp), 0, 0, 0, 0 );
@@ -1074,15 +1126,19 @@ int Acb_NtkFindSupp3( Acb_Ntk_t * p, int Pivot, sat_solver * pSat, int nVars, in
             nSuppNew = sat_solver_minimize_assumptions( pSat, Vec_IntArray(vSupp), Vec_IntSize(vSupp), 0 );
             Vec_IntShrink( vSupp, nSuppNew );
             Vec_IntLits2Vars( vSupp, -6*nVars );
-            // sort by size
-            Vec_IntSort( vSupp, 0 );
+            Vec_IntSort( vSupp, 1 );
             // count how many belong to H; the rest belong to G
             NodeMark = 0;
             Vec_IntForEachEntry( vSupp, iFanin3, k3 )
-                if ( iFanin3 < nDivs )
-                    NodeMark++;
-                else 
+                if ( iFanin3 >= nDivs )
                     Vec_IntWriteEntry( vSupp, k3, iFanin3 - nDivs );
+                else 
+                    NodeMark++;
+            if ( NodeMark == 0 )
+            {
+                //printf( "Obj %d: Special case 2 (vars = %d)\n", Pivot, Vec_IntSize(vSupp) );
+                continue;
+            }
             assert( NodeMark > 0 );
             if ( Vec_IntSize(vSupp) - NodeMark <= nLutSize )
                 return NodeMark;
@@ -1092,7 +1148,6 @@ int Acb_NtkFindSupp3( Acb_Ntk_t * p, int Pivot, sat_solver * pSat, int nVars, in
     return 0;
 }
 
-
 /**Function*************************************************************
 
   Synopsis    []
@@ -1112,12 +1167,14 @@ struct Acb_Mfs_t_
     sat_solver *    pSat[3];     // SAT solvers
     Vec_Int_t *     vSupp;       // support
     Vec_Int_t *     vFlip;       // support
+    Vec_Int_t *     vValues;     // support
     int             nNodes;      // nodes
     int             nWins;       // windows
     int             nWinsAll;    // windows
     int             nDivsAll;    // windows
     int             nChanges[8]; // changes
     int             nOvers;      // overflows
+    int             nTwoNodes;   // two nodes
     abctime         timeTotal;
     abctime         timeCnf;
     abctime         timeSol;
@@ -1137,22 +1194,118 @@ Acb_Mfs_t * Acb_MfsStart( Acb_Ntk_t * pNtk, Acb_Par_t * pPars )
     p->pSat[2]    = sat_solver_new();
     p->vSupp      = Vec_IntAlloc(100);
     p->vFlip      = Vec_IntAlloc(100);
+    p->vValues    = Vec_IntAlloc(100);
     return p;
 }
 void Acb_MfsStop( Acb_Mfs_t * p )
 {
     Vec_IntFree( p->vFlip );
     Vec_IntFree( p->vSupp );
+    Vec_IntFree( p->vValues );
     sat_solver_delete( p->pSat[0] );
     sat_solver_delete( p->pSat[1] );
     sat_solver_delete( p->pSat[2] );
     ABC_FREE( p );
 }
+static inline int Acb_NtkObjMffcEstimate( Acb_Ntk_t * pNtk, int iObj )
+{
+    int k, iFanin, * pFanins, Count = 0, iFaninCrit = -1;
+    Acb_ObjForEachFaninFast( pNtk, iObj, pFanins, iFanin, k )
+        if ( Acb_ObjIsAreaCritical(pNtk, iFanin) )
+            iFaninCrit = iFanin, Count++;
+    if ( Count != 1 )
+        return Count;
+    Acb_ObjForEachFaninFast( pNtk, iFaninCrit, pFanins, iFanin, k )
+        if ( Acb_ObjIsAreaCritical(pNtk, iFanin) )
+            Count++;
+    return Count;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Acb_NtkOptNodeAnalyze( Acb_Mfs_t * p, int PivotVar, int nDivs, int nValues, int * pValues, Vec_Int_t * vSupp )
+{
+    word OnSet[64] = {0};
+    word OffSet[64] = {0};
+    word Diffs[64] = {0};
+    int s, nScope = 1 + 2*nDivs, d, i;
+    int f, nFrames = nValues / nScope;
+    int start = nDivs < 64 ? 0 : nDivs - 64;
+    int stop  = nDivs < 64 ? nDivs : 64;
+    assert( nValues % nScope == 0 );
+    assert( nFrames <= 16 );
+    for ( f = 0; f < nFrames; f++ )
+    {
+        int * pStart  = pValues + f * nScope;
+        int * pOnSet  = pStart + 1 + (pStart[0] ? 0 : nDivs);
+        int * pOffSet = pStart + 1 + (pStart[0] ? nDivs : 0);
+
+        printf( "%2d:", f );
+        for ( s = start; s < stop; s++ )
+            printf( "%d", pOnSet[s] );
+        printf( "\n" );
+
+        printf( "%2d:", f );
+        for ( s = start; s < stop; s++ )
+            printf( "%d", pOffSet[s] );
+        printf( "\n" );
+
+        for ( s = start; s < stop; s++ )
+        {
+            if ( pOnSet[s] )   OnSet[f]  |= (((word)1) << (s-start));
+            if ( pOffSet[s] )  OffSet[f] |= (((word)1) << (s-start));
+        }
+    }
+    d = 0;
+    for ( f = 0; f < nFrames; f++ )
+    for ( s = 0; s < nFrames; s++ )
+    {
+        for ( i = 0; i < d; i++ )
+            if ( Diffs[i] == (OnSet[f] ^ OffSet[s]) )
+                break;
+        if ( i < d )
+            continue;
+        if ( d < 64 )
+            Diffs[d++] = OnSet[f] ^ OffSet[s];
+    }
+
+    printf( "Divisors = %d.  Frames = %d.  Patterns = %d.\n", nDivs, nFrames, d );
+    printf( "   " );
+    for ( s = start; s < stop; s++ )
+        printf( "%d", s / 10 );
+    printf( "\n" );
+    printf( "   " );
+    for ( s = start; s < stop; s++ )
+        printf( "%d", s % 10 );
+    printf( "\n" );
+    printf( "   " );
+    for ( s = start; s < stop; s++ )
+        printf( "%c", Vec_IntFind(vSupp, s) >= 0 ? 'a' + Vec_IntFind(vSupp, s) : ' ' );
+    printf( "\n" );
+    for ( s = 0; s < d; s++ )
+    {
+        printf( "%2d:", s );
+        for ( f = 0; f < stop; f++ )
+            printf( "%c", ((Diffs[s] >> f) & 1) ? '*' : ' ' );
+        printf( "\n" );
+    }
+}
+
 int Acb_NtkOptNode( Acb_Mfs_t * p, int Pivot )
 {
     Cnf_Dat_t * pCnf = NULL; abctime clk;
     Vec_Int_t * vWin = NULL; word uTruth;
     int Result, PivotVar, nDivs = 0, RetValue = 0, c;
+    assert( Acb_ObjFanoutNum(p->pNtk, Pivot) > 0 );
     p->nWins++;
 
     // compute divisors and window for this target node with these taboo nodes
@@ -1210,9 +1363,32 @@ int Acb_NtkOptNode( Acb_Mfs_t * p, int Pivot )
     // try to remove useless fanins
     if ( p->pPars->fArea )
     {
+        int fEnableProfile = 0;
+        if ( fEnableProfile )
+        {
+            // alloc
+            if ( p->pSat[1]->user_values.cap == 0 )
+                veci_new(&p->pSat[1]->user_values);
+            else
+                p->pSat[1]->user_values.size = 0;
+            if ( p->pSat[1]->user_vars.cap == 0 )
+                veci_new(&p->pSat[1]->user_vars);
+            else
+                p->pSat[1]->user_vars.size = 0;
+            // set variables
+            veci_push(&p->pSat[1]->user_vars, PivotVar);
+            for ( c = 0; c < nDivs; c++ )
+                veci_push(&p->pSat[1]->user_vars, c);
+            for ( c = 0; c < nDivs; c++ )
+                veci_push(&p->pSat[1]->user_vars, c+pCnf->nVars);
+        }
+
+        // perform solving
         clk = Abc_Clock();
         Result = Acb_NtkFindSupp1( p->pNtk, Pivot, p->pSat[1], pCnf->nVars, nDivs, vWin, p->vSupp );
         p->timeSat += Abc_Clock() - clk;
+        // undo variables
+        p->pSat[1]->user_vars.size = 0;
         if ( Result )
         {
             if ( Vec_IntSize(p->vSupp) == 0 )
@@ -1222,7 +1398,7 @@ int Acb_NtkOptNode( Acb_Mfs_t * p, int Pivot )
             assert( Vec_IntSize(p->vSupp) < p->pPars->nLutSize );
             if ( p->pPars->fVerbose )
             printf( "Found %d inputs: ", Vec_IntSize(p->vSupp) );
-            uTruth = Acb_ComputeFunction( p->pSat[0], PivotVar, sat_solver_nvars(p->pSat[0])-1, p->vSupp );
+            uTruth = Acb_ComputeFunction( p->pSat[0], PivotVar, sat_solver_nvars(p->pSat[0])-1, p->vSupp, 0 );
             if ( p->pPars->fVerbose )
             Extra_PrintHex( stdout, (unsigned *)&uTruth, Vec_IntSize(p->vSupp) ); 
             if ( p->pPars->fVerbose )
@@ -1234,67 +1410,149 @@ int Acb_NtkOptNode( Acb_Mfs_t * p, int Pivot )
             RetValue = 1;
             goto cleanup;
         }
+        if ( fEnableProfile )
+        {
+            // analyze the resulting values
+            Acb_NtkOptNodeAnalyze( p, PivotVar, nDivs, p->pSat[1]->user_values.size, p->pSat[1]->user_values.ptr, p->vSupp );
+            p->pSat[1]->user_values.size = 0;
+        }
     }
 
-    // check for one-node implementation
-    clk = Abc_Clock();
-    Result = Acb_NtkFindSupp2( p->pNtk, Pivot, p->pSat[1], pCnf->nVars, nDivs, vWin, p->vSupp, p->pPars->nLutSize, !p->pPars->fArea );
-    p->timeSat += Abc_Clock() - clk;
-    if ( Result )
+    if ( Acb_NtkObjMffcEstimate(p->pNtk, Pivot) >= 1 )
     {
-        p->nChanges[2]++;
-        assert( Vec_IntSize(p->vSupp) <= p->pPars->nLutSize );
-        if ( p->pPars->fVerbose )
-        printf( "Found %d inputs: ", Vec_IntSize(p->vSupp) );
-        uTruth = Acb_ComputeFunction( p->pSat[0], PivotVar, sat_solver_nvars(p->pSat[0])-1, p->vSupp );
-        if ( p->pPars->fVerbose )
-        Extra_PrintHex( stdout, (unsigned *)&uTruth, Vec_IntSize(p->vSupp) ); 
-        if ( p->pPars->fVerbose )
-        printf( "\n" );
-        // create support in terms of nodes
-        Vec_IntRemap( p->vSupp, vWin );
-        Vec_IntLits2Vars( p->vSupp, 0 );
-        Acb_NtkUpdateNode( p->pNtk, Pivot, uTruth, p->vSupp );
-        RetValue = 1;
-        goto cleanup;
+        // check for one-node implementation
+        clk = Abc_Clock();
+        Result = Acb_NtkFindSupp2( p->pNtk, Pivot, p->pSat[1], pCnf->nVars, nDivs, vWin, p->vSupp, p->pPars->nLutSize, !p->pPars->fArea );
+        p->timeSat += Abc_Clock() - clk;
+        if ( Result )
+        {
+            p->nChanges[2]++;
+            assert( Vec_IntSize(p->vSupp) <= p->pPars->nLutSize );
+            if ( p->pPars->fVerbose )
+            printf( "Found %d inputs: ", Vec_IntSize(p->vSupp) );
+            uTruth = Acb_ComputeFunction( p->pSat[0], PivotVar, sat_solver_nvars(p->pSat[0])-1, p->vSupp, 0 );
+            if ( p->pPars->fVerbose )
+            Extra_PrintHex( stdout, (unsigned *)&uTruth, Vec_IntSize(p->vSupp) ); 
+            if ( p->pPars->fVerbose )
+            printf( "\n" );
+            // create support in terms of nodes
+            Vec_IntRemap( p->vSupp, vWin );
+            Vec_IntLits2Vars( p->vSupp, 0 );
+            Acb_NtkUpdateNode( p->pNtk, Pivot, uTruth, p->vSupp );
+            RetValue = 1;
+            goto cleanup;
+        }
     }
 
-#if 0
-    // derive SAT solver
-    clk = Abc_Clock();
-    Acb_NtkWindow2Solver( p->pSat[2], pCnf, p->vFlip, PivotVar, nDivs, 6 );
-    p->timeSol += Abc_Clock() - clk;
-
-    // check for two-node implementation
-    clk = Abc_Clock();
-    Result = Acb_NtkFindSupp3( p->pNtk, Pivot, p->pSat[2], pCnf->nVars, nDivs, vWin, p->vSupp, p->pPars->nLutSize, !p->pPars->fArea );
-    p->timeSat += Abc_Clock() - clk;
-    if ( Result )
+//#if 0
+    if ( Acb_NtkObjMffcEstimate(p->pNtk, Pivot) >= 2 )// && Pivot != 70 )
     {
-        p->nChanges[3]++;
-        assert( Result                       <  p->pPars->nLutSize );
-        assert( Vec_IntSize(p->vSupp)-Result <= p->pPars->nLutSize );
-        //if ( p->pPars->fVerbose )
-        printf( "Found %d Hvars and %d Gvars: ", Result, Vec_IntSize(p->vSupp)-Result );
-
-        /*
-        uTruth = Acb_ComputeFunction( p->pSat[1], PivotVar, sat_solver_nvars(p->pSat[1])-1, vSupp );
-        if ( p->pPars->fVerbose )
-        Extra_PrintHex( stdout, (unsigned *)&uTruth, Vec_IntSize(p->vSupp) ); 
-        if ( p->pPars->fVerbose )
-        printf( "\n" );
-        // create support in terms of nodes
-        Vec_IntRemap( p->vSupp, vWin );
-        Vec_IntLits2Vars( vSupp, 0 );
-        Acb_NtkUpdateNode( p->pNtk, Pivot, uTruth, p->vSupp );
-        RetValue = 1;
-        */
-
-        //if ( p->pPars->fVerbose )
-        printf( "\n" );
-        goto cleanup;
+        p->nTwoNodes++;
+        // derive SAT solver
+        clk = Abc_Clock();
+        Acb_NtkWindow2Solver( p->pSat[2], pCnf, p->vFlip, PivotVar, nDivs, 6 );
+        p->timeSol += Abc_Clock() - clk;
+
+        // check for two-node implementation
+        clk = Abc_Clock();
+        Result = Acb_NtkFindSupp3( p->pNtk, Pivot, p->pSat[2], pCnf->nVars, nDivs, vWin, p->vSupp, p->pPars->nLutSize, !p->pPars->fArea );
+        p->timeSat += Abc_Clock() - clk;
+        if ( Result )
+        {
+            int fVerbose = 1;
+            int i, k, Lit, Var, Var2, status, NodeNew, fBecameUnsat = 0, fCompl = 0;
+            assert( Result                       <  p->pPars->nLutSize );
+            assert( Vec_IntSize(p->vSupp)-Result <= p->pPars->nLutSize );
+            if ( fVerbose || p->pPars->fVerbose )
+            printf( "Obj %5d: Found %d Hvars and %d Gvars: ", Pivot, Result, Vec_IntSize(p->vSupp)-Result );
+            // p->vSupp contains G variables (Vec_IntSize(p->vSupp)-Result) followed by H variables (Result)
+            //sat_solver_restart( p->pSat[1] );
+            //Acb_NtkWindow2Solver( p->pSat[1], pCnf, p->vFlip, PivotVar, nDivs, 2 );
+
+            // constrain H-variables to be equal
+            Vec_IntForEachEntryStart( p->vSupp, Var, i, Vec_IntSize(p->vSupp)-Result ) // H variables
+            {
+                assert( Var >= 0 && Var < nDivs );
+                assert( Var + 2*pCnf->nVars < sat_solver_nvars(p->pSat[1]) );
+                Lit = Abc_Var2Lit( Var + 2*pCnf->nVars, 0 ); // HVars are the same
+                if ( !sat_solver_addclause( p->pSat[1], &Lit, &Lit + 1 ) )
+                { if ( fVerbose || p->pPars->fVerbose ) printf( "Error: SAT solver became UNSAT at a wrong place (place 2).  " ); fBecameUnsat = 1; }
+            }
+            // find one satisfying assighment
+            status = sat_solver_solve( p->pSat[1], NULL, NULL, 0, 0, 0, 0 );
+            assert( status == l_True );
+            // get assignment of the function
+            fCompl = !sat_solver_var_value( p->pSat[1], PivotVar );
+            // constrain second set of G-vars to have values equal to the assignment
+            Vec_IntForEachEntryStop( p->vSupp, Var, i, Vec_IntSize(p->vSupp)-Result ) // G variables
+            {
+                // check if this is a C-var
+                Vec_IntForEachEntryStart( p->vSupp, Var2, k, Vec_IntSize(p->vSupp)-Result ) // G variables
+                    if ( Var == Var2 )
+                        break;
+                if ( k < Vec_IntSize(p->vSupp) ) // do not constrain a C-var
+                {
+                    if ( fVerbose || p->pPars->fVerbose )
+                    printf( "Found C-var in object %d.  ", Pivot );
+                    continue;
+                }
+                assert( Var >= 0 && Var < nDivs );
+                Lit = sat_solver_var_literal( p->pSat[1], Var + pCnf->nVars );
+                if ( !sat_solver_addclause( p->pSat[1], &Lit, &Lit + 1 ) )
+                { if ( fVerbose || p->pPars->fVerbose ) printf( "Error: SAT solver became UNSAT at a wrong place (place 1).  " ); fBecameUnsat = 1; }
+            }
+            if ( fBecameUnsat )
+            {
+                StrCount++;
+                if ( fVerbose || p->pPars->fVerbose )
+                printf( " Quitting.\n" );
+                goto cleanup;
+            }
+            // consider only G variables
+            p->vSupp->nSize -= Result;
+            // truth table
+            uTruth = Acb_ComputeFunction( p->pSat[1], PivotVar, sat_solver_nvars(p->pSat[1])-1, p->vSupp, fCompl );
+            if ( fVerbose || p->pPars->fVerbose )
+            Extra_PrintHex( stdout, (unsigned *)&uTruth, Vec_IntSize(p->vSupp) ); 
+            if ( uTruth == 0 || ~uTruth == 0 )
+            {
+                if ( fVerbose || p->pPars->fVerbose )
+                printf( " Quitting.\n" );
+                goto cleanup;
+            }
+            p->nChanges[3]++;
+            // create new node
+            Vec_IntRemap( p->vSupp, vWin );
+            Vec_IntLits2Vars( p->vSupp, 0 );
+            NodeNew = Acb_NtkCreateNode( p->pNtk, uTruth, p->vSupp );
+            Acb_DeriveCnfForWindowOne( p->pNtk, NodeNew );
+            Acb_DeriveCnfForNode( p->pNtk, NodeNew, p->pSat[0], sat_solver_nvars(p->pSat[0])-2 );
+            p->vSupp->nSize += Result;
+            // collect new variables
+            Vec_IntForEachEntryStart( p->vSupp, Var, i, Vec_IntSize(p->vSupp)-Result )
+                Vec_IntWriteEntry( p->vSupp, i-(Vec_IntSize(p->vSupp)-Result), Var );
+            Vec_IntShrink( p->vSupp, Result );
+            Vec_IntPush( p->vSupp, sat_solver_nvars(p->pSat[0])-2 );
+            // truth table
+            uTruth = Acb_ComputeFunction( p->pSat[0], PivotVar, sat_solver_nvars(p->pSat[0])-1, p->vSupp, 0 );
+            // create new fanins of the node
+            if ( fVerbose || p->pPars->fVerbose )
+            printf( "  " );
+            if ( fVerbose || p->pPars->fVerbose )
+            Extra_PrintHex( stdout, (unsigned *)&uTruth, Vec_IntSize(p->vSupp) ); 
+            if ( fVerbose || p->pPars->fVerbose )
+            printf( "\n" );
+            // create support in terms of nodes
+            Vec_IntPop( p->vSupp );
+            Vec_IntRemap( p->vSupp, vWin );
+            Vec_IntLits2Vars( p->vSupp, 0 );
+            Vec_IntPush( p->vSupp, NodeNew );
+            Acb_NtkUpdateNode( p->pNtk, Pivot, uTruth, p->vSupp );
+            RetValue = 2;
+            goto cleanup;
+        }
     }
-#endif
+//#endif
 
     if ( p->pPars->fVerbose )
     printf( "\n" );
@@ -1312,7 +1570,6 @@ cleanup:
     return RetValue;
 }
 
-
 /**Function*************************************************************
 
   Synopsis    []
@@ -1330,30 +1587,34 @@ void Acb_NtkOpt( Acb_Ntk_t * pNtk, Acb_Par_t * pPars )
     //if ( pPars->fVerbose )
         printf( "%s-optimization parameters: TfiLev(I) = %d  TfoLev(O) = %d  WinMax(W) = %d  LutSize = %d\n", 
             pMan->pPars->fArea ? "Area" : "Delay", pMan->pPars->nTfiLevMax, pMan->pPars->nTfoLevMax, pMan->pPars->nWinNodeMax, pMan->pPars->nLutSize );
-    Acb_NtkCreateFanout( pMan->pNtk );  // fanout data structure
-    Acb_NtkCleanObjFuncs( pMan->pNtk ); // SAT variables
-    Acb_NtkCleanObjCnfs( pMan->pNtk );  // CNF representations
+    Acb_NtkCreateFanout( pNtk );  // fanout data structure
+    Acb_NtkCleanObjFuncs( pNtk ); // SAT variables
+    Acb_NtkCleanObjCnfs( pNtk );  // CNF representations
     if ( pMan->pPars->fArea )
     {
-        int iObj;
-        Acb_NtkUpdateLevelD( pMan->pNtk, -1 ); // compute forward logic level
-        Acb_NtkForEachNode( pMan->pNtk, iObj )
-        {
-            pMan->nNodes++;
-            assert( Acb_ObjFanoutNum(pMan->pNtk, iObj) > 0 );
-            //if ( iObj != 7 )
-            //    continue;
-            while ( Acb_NtkOptNode(pMan, iObj) && Acb_ObjFaninNum(pMan->pNtk, iObj) );
-//            Acb_NtkOptNode( pMan, iObj );
-        }
+        int n = 0, iObj, RetValue, nNodes = Acb_NtkObjNumMax(pNtk);
+        Vec_Bit_t * vVisited = Vec_BitStart( Acb_NtkObjNumMax(pNtk) );
+        Acb_NtkUpdateLevelD( pNtk, -1 ); // compute forward logic level
+        for ( n = 2; n >= 0; n-- )
+            Acb_NtkForEachNode( pNtk, iObj )
+                if ( iObj < nNodes && !Vec_BitEntry(vVisited, iObj) && Acb_NtkObjMffcEstimate(pNtk, iObj) >= n )
+                {
+                    pMan->nNodes++;
+                    //if ( iObj != 7 )
+                    //    continue;
+                    //Acb_NtkOptNode( pMan, iObj );
+                    while ( (RetValue = Acb_NtkOptNode(pMan, iObj)) && Acb_ObjFaninNum(pNtk, iObj) );                    
+                    Vec_BitWriteEntry( vVisited, iObj, 1 );
+                }
+        Vec_BitFree( vVisited );
     }
     else
     {
-        Acb_NtkUpdateTiming( pMan->pNtk, -1 ); // compute delay information
-        while ( Vec_QueTopPriority(pMan->pNtk->vQue) > 0 )
+        Acb_NtkUpdateTiming( pNtk, -1 ); // compute delay information
+        while ( Vec_QueTopPriority(pNtk->vQue) > 0 )
         {
-            int iObj = Vec_QuePop(pMan->pNtk->vQue);
-            if ( Acb_ObjLevelD(pMan->pNtk, iObj) == 1 )
+            int iObj = Vec_QuePop(pNtk->vQue);
+            if ( Acb_ObjLevelD(pNtk, iObj) == 1 )
                 continue;
             //if ( iObj != 28 )
             //    continue;
@@ -1363,10 +1624,10 @@ void Acb_NtkOpt( Acb_Ntk_t * pNtk, Acb_Par_t * pPars )
     //if ( pPars->fVerbose )
     {
         pMan->timeTotal = Abc_Clock() - pMan->timeTotal;
-        printf( "Node = %d  Win = %d (Ave = %d)  DivAve = %d   Change = %d  C = %d  N1 = %d  N2 = %d  N3 = %d   Over = %d  Str = %d\n", 
+        printf( "Node = %d  Win = %d (Ave = %d)  DivAve = %d   Change = %d  C = %d  N1 = %d  N2 = %d  N3 = %d   Over = %d  Str = %d  2Node = %d.\n", 
             pMan->nNodes, pMan->nWins, pMan->nWinsAll/Abc_MaxInt(1, pMan->nWins), pMan->nDivsAll/Abc_MaxInt(1, pMan->nWins),
             pMan->nChanges[0] + pMan->nChanges[1] + pMan->nChanges[2] + pMan->nChanges[3],
-            pMan->nChanges[0], pMan->nChanges[1], pMan->nChanges[2], pMan->nChanges[3], pMan->nOvers, StrCount );
+            pMan->nChanges[0], pMan->nChanges[1], pMan->nChanges[2], pMan->nChanges[3], pMan->nOvers, StrCount, pMan->nTwoNodes );
         ABC_PRTP( "Windowing  ", pMan->timeWin,    pMan->timeTotal );
         ABC_PRTP( "CNF compute", pMan->timeCnf,    pMan->timeTotal );
         ABC_PRTP( "Make solver", pMan->timeSol,    pMan->timeTotal );
@@ -1377,6 +1638,7 @@ void Acb_NtkOpt( Acb_Ntk_t * pNtk, Acb_Par_t * pPars )
         fflush( stdout );
     }
     Acb_MfsStop( pMan );
+    StrCount = 0;
 }
 
 ////////////////////////////////////////////////////////////////////////
diff --git a/src/base/acb/acbUtil.c b/src/base/acb/acbUtil.c
index bae9ea1a..48cc9458 100644
--- a/src/base/acb/acbUtil.c
+++ b/src/base/acb/acbUtil.c
@@ -300,13 +300,14 @@ void Acb_NtkUpdateTiming( Acb_Ntk_t * p, int iObj )
   SeeAlso     []
 
 ***********************************************************************/
-void Acb_NtkCreateNode( Acb_Ntk_t * p, word uTruth, Vec_Int_t * vSupp )
+int Acb_NtkCreateNode( Acb_Ntk_t * p, word uTruth, Vec_Int_t * vSupp )
 {
     int Pivot = Acb_ObjAlloc( p, ABC_OPER_LUT, Vec_IntSize(vSupp), 0 );
     Acb_ObjSetTruth( p, Pivot, uTruth );
     Acb_ObjAddFanins( p, Pivot, vSupp );
     Acb_ObjAddFaninFanout( p, Pivot );
     Acb_ObjComputeLevelD( p, Pivot );
+    return Pivot;
 }
 void Acb_NtkResetNode( Acb_Ntk_t * p, int Pivot, word uTruth, Vec_Int_t * vSupp )
 {
-- 
cgit v1.2.3


From 304c63e8603b34909f89ae84e6939bd77147c29c Mon Sep 17 00:00:00 2001
From: Alan Mishchenko <alanmi@berkeley.edu>
Date: Tue, 4 Apr 2017 15:37:10 -0700
Subject: Experiments with don't-cares.

---
 src/base/abci/abc.c    |   9 ++-
 src/base/acb/acbAbc.c  |  46 +++++++++++----
 src/base/acb/acbMfs.c  |  19 +++----
 src/base/acb/acbPar.h  |   1 +
 src/base/acb/acbUtil.c | 151 ++++++++++++++++++++++++++++++++++++++++---------
 5 files changed, 176 insertions(+), 50 deletions(-)

(limited to 'src/base')

diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c
index 8e2c449c..d28a5abd 100644
--- a/src/base/abci/abc.c
+++ b/src/base/abci/abc.c
@@ -5676,7 +5676,7 @@ int Abc_CommandMfse( Abc_Frame_t * pAbc, int argc, char ** argv )
     Acb_Par_t Pars, * pPars = &Pars; int c;
     Acb_ParSetDefault( pPars );
     Extra_UtilGetoptReset();
-    while ( ( c = Extra_UtilGetopt( argc, argv, "IOWFLCavwh" ) ) != EOF )
+    while ( ( c = Extra_UtilGetopt( argc, argv, "IOWFLCadvwh" ) ) != EOF )
     {
         switch ( c )
         {
@@ -5749,6 +5749,9 @@ int Abc_CommandMfse( Abc_Frame_t * pAbc, int argc, char ** argv )
         case 'a':
             pPars->fArea ^= 1;
             break;
+        case 'd':
+            pPars->fUseAshen ^= 1;
+            break;
         case 'v':
             pPars->fVerbose ^= 1;
             break;
@@ -5788,7 +5791,7 @@ int Abc_CommandMfse( Abc_Frame_t * pAbc, int argc, char ** argv )
     return 0;
 
 usage:
-    Abc_Print( -2, "usage: mfse [-IOWFLC <num>] [-avwh]\n" );
+    Abc_Print( -2, "usage: mfse [-IOWFLC <num>] [-advwh]\n" );
     Abc_Print( -2, "\t           performs don't-care-based optimization of logic networks\n" );
     Abc_Print( -2, "\t-I <num> : the number of levels in the TFI cone (2 <= num) [default = %d]\n",             pPars->nTfiLevMax );
     Abc_Print( -2, "\t-O <num> : the number of levels in the TFO cone (0 <= num) [default = %d]\n",             pPars->nTfoLevMax );
@@ -5797,6 +5800,7 @@ usage:
     Abc_Print( -2, "\t-L <num> : the max increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel );
     Abc_Print( -2, "\t-C <num> : the max number of conflicts in one SAT run (0 = no limit) [default = %d]\n",   pPars->nBTLimit );
     Abc_Print( -2, "\t-a       : toggle minimizing area [default = %s]\n",                                      pPars->fArea? "area": "delay" );
+    Abc_Print( -2, "\t-d       : toggle using Ashenhurst decomposition [default = %s]\n",                       pPars->fUseAshen? "yes": "no" );
     Abc_Print( -2, "\t-v       : toggle printing optimization summary [default = %s]\n",                        pPars->fVerbose? "yes": "no" );
     Abc_Print( -2, "\t-w       : toggle printing detailed stats for each node [default = %s]\n",                pPars->fVeryVerbose? "yes": "no" );
     Abc_Print( -2, "\t-h       : print the command usage\n");
@@ -12380,6 +12384,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
 //        extern void Cba_PrsReadBlifTest();
 //        Cba_PrsReadBlifTest();
     }
+    Abc_NtkComputePaths( Abc_FrameReadNtk(pAbc) );
     return 0;
 usage:
     Abc_Print( -2, "usage: test [-CKDNM] [-aovwh] <file_name>\n" );
diff --git a/src/base/acb/acbAbc.c b/src/base/acb/acbAbc.c
index d3c511ff..2b07a202 100644
--- a/src/base/acb/acbAbc.c
+++ b/src/base/acb/acbAbc.c
@@ -44,27 +44,18 @@ ABC_NAMESPACE_IMPL_START
   SeeAlso     []
 
 ***********************************************************************/
-Acb_Ntk_t * Acb_NtkFromAbc( Abc_Ntk_t * p )
+Acb_Ntk_t * Acb_NtkFromAbc2( Abc_Ntk_t * p )
 {
-    int fTrack = 1;
     Acb_Man_t * pMan = Acb_ManAlloc( Abc_NtkSpec(p), 1, NULL, NULL, NULL, NULL );
     int i, k, NameId = Abc_NamStrFindOrAdd( pMan->pStrs, Abc_NtkName(p), NULL );
     Acb_Ntk_t * pNtk = Acb_NtkAlloc( pMan, NameId, Abc_NtkCiNum(p), Abc_NtkCoNum(p), Abc_NtkObjNum(p) );
     Abc_Obj_t * pObj, * pFanin;
     assert( Abc_NtkIsSopLogic(p) );
     pNtk->nFaninMax = 6;
-    if ( fTrack ) Vec_IntFill( &pNtk->vArray2, Abc_NtkObjNumMax(p), -1 );
     Abc_NtkForEachCi( p, pObj, i )
-    {
         pObj->iTemp = Acb_ObjAlloc( pNtk, ABC_OPER_CI, 0, 0 );
-        if ( fTrack ) Vec_IntWriteEntry( &pNtk->vArray2, pObj->iTemp, Abc_ObjId(pObj) );
-    }
     Abc_NtkForEachNode( p, pObj, i )
-    {
         pObj->iTemp = Acb_ObjAlloc( pNtk, ABC_OPER_LUT, Abc_ObjFaninNum(pObj), 0 );
-        if ( fTrack ) Vec_IntWriteEntry( &pNtk->vArray2, pObj->iTemp, Abc_ObjId(pObj) );
-//        printf( "%d -> %d\n%s", i, pObj->iTemp, (char *)pObj->pData );
-    }
     Abc_NtkForEachCo( p, pObj, i )
         pObj->iTemp = Acb_ObjAlloc( pNtk, ABC_OPER_CO, 1, 0 );
     Abc_NtkForEachNode( p, pObj, i )
@@ -79,6 +70,40 @@ Acb_Ntk_t * Acb_NtkFromAbc( Abc_Ntk_t * p )
     Acb_NtkAdd( pMan, pNtk );
     return pNtk;
 }
+Acb_Ntk_t * Acb_NtkFromAbc( Abc_Ntk_t * p )
+{
+    Acb_Man_t * pMan = Acb_ManAlloc( Abc_NtkSpec(p), 1, NULL, NULL, NULL, NULL );
+    int i, k, NameId = Abc_NamStrFindOrAdd( pMan->pStrs, Abc_NtkName(p), NULL );
+    Acb_Ntk_t * pNtk = Acb_NtkAlloc( pMan, NameId, Abc_NtkCiNum(p), Abc_NtkCoNum(p), Abc_NtkObjNumMax(p)-1 );
+    Abc_Obj_t * pObj, * pFanin;
+    assert( Abc_NtkIsSopLogic(p) );
+    pNtk->nFaninMax = 6;
+    for ( i = 1; i < Abc_NtkObjNumMax(p); i++ )
+    {
+        pObj = Abc_NtkObj( p, i );
+        if ( pObj == NULL )
+            Acb_ObjAlloc( pNtk, ABC_OPER_NONE, 0, 0 );
+        else if ( Abc_ObjIsCi(pObj) )
+            pObj->iTemp = Acb_ObjAlloc( pNtk, ABC_OPER_CI, 0, 0 );
+        else if ( Abc_ObjIsCo(pObj) )
+            pObj->iTemp = Acb_ObjAlloc( pNtk, ABC_OPER_CO, 1, 0 );
+        else if ( Abc_ObjIsNode(pObj) )
+            pObj->iTemp = Acb_ObjAlloc( pNtk, ABC_OPER_LUT, Abc_ObjFaninNum(pObj), 0 );
+        else assert( 0 );
+        assert( pObj == NULL || pObj->iTemp == (int)Abc_ObjId(pObj) );
+    }
+    Abc_NtkForEachNode( p, pObj, i )
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Acb_ObjAddFanin( pNtk, pObj->iTemp, pFanin->iTemp );
+    Abc_NtkForEachCo( p, pObj, i )
+        Acb_ObjAddFanin( pNtk, pObj->iTemp, Abc_ObjFanin(pObj, 0)->iTemp );
+    Acb_NtkCleanObjTruths( pNtk );
+    Abc_NtkForEachNode( p, pObj, i )
+        Acb_ObjSetTruth( pNtk, pObj->iTemp, Abc_SopToTruth((char *)pObj->pData, Abc_ObjFaninNum(pObj)) );
+    Acb_NtkSetRegNum( pNtk, Abc_NtkLatchNum(p) );
+    Acb_NtkAdd( pMan, pNtk );
+    return pNtk;
+}
 
 /**Function*************************************************************
 
@@ -218,6 +243,7 @@ void Acb_ParSetDefault( Acb_Par_t * pPars )
     pPars->nNodesMax    =    0;    // the maximum number of nodes to try
     pPars->iNodeOne     =    0;    // one particular node to try
     pPars->fArea        =    1;    // performs optimization for area
+    pPars->fUseAshen    =    0;    // use Ashenhurst decomposition
     pPars->fMoreEffort  =    0;    // enables using more effort
     pPars->fVerbose     =    0;    // enable basic stats
     pPars->fVeryVerbose =    0;    // enable detailed stats
diff --git a/src/base/acb/acbMfs.c b/src/base/acb/acbMfs.c
index eca83aa9..a17a179a 100644
--- a/src/base/acb/acbMfs.c
+++ b/src/base/acb/acbMfs.c
@@ -430,15 +430,15 @@ void Acb_NtkPrintVec( Acb_Ntk_t * p, Vec_Int_t * vVec, char * pName )
     int i;
     printf( "%s: ", pName );
     for ( i = 0; i < vVec->nSize; i++ )
-        printf( "%d ", Vec_IntEntry(&p->vArray2, vVec->pArray[i]) );
+        printf( "%d ", vVec->pArray[i] );
     printf( "\n" );
 }
 void Acb_NtkPrintNode( Acb_Ntk_t * p, int Node )
 {
     int k, iFanin, * pFanins;
-    printf( "Node %d : ", Vec_IntEntry(&p->vArray2, Node) );
+    printf( "Node %d : ", Node );
     Acb_ObjForEachFaninFast( p, Node, pFanins, iFanin, k )
-        printf( "%d ", Vec_IntEntry(&p->vArray2, iFanin) );
+        printf( "%d ", iFanin );
     printf( "\n" );
 }
 void Acb_NtkPrintVec2( Acb_Ntk_t * p, Vec_Int_t * vVec, char * pName )
@@ -579,7 +579,6 @@ void Acb_ObjMarkTfo2( Acb_Ntk_t * p, Vec_Int_t * vMarked )
 int Acb_ObjLabelTfo_rec( Acb_Ntk_t * p, int iObj, int nTfoLevMax, int nFanMax, int fFirst )
 {
     int iFanout, i, Diff, fHasNone = 0;
-//printf( "Visiting %d\n", Vec_IntEntry(&p->vArray2, iObj) );
     if ( (Diff = Acb_ObjTravIdDiff(p, iObj)) <= 2 )
         return Diff;
     Acb_ObjSetTravIdDiff( p, iObj, 2 );
@@ -871,15 +870,15 @@ static inline void Vec_IntRemap( Vec_Int_t * p, Vec_Int_t * vMap )
 static inline void Acb_WinPrint( Acb_Ntk_t * p, Vec_Int_t * vWin, int Pivot, int nDivs )
 {
     int i, Node;
-    printf( "Window for node %d with %d divisors:\n", Vec_IntEntry(&p->vArray2, Pivot), nDivs );
+    printf( "Window for node %d with %d divisors:\n", Pivot, nDivs );
     Vec_IntForEachEntry( vWin, Node, i )
     {
         if ( i == nDivs )
             printf( " | " );
         if ( Abc_Lit2Var(Node) == Pivot )
-            printf( "(%d) ", Vec_IntEntry(&p->vArray2, Pivot) );
+            printf( "(%d) ", Pivot );
         else
-            printf( "%s%d ", Abc_LitIsCompl(Node) ? "*":"", Vec_IntEntry(&p->vArray2, Abc_Lit2Var(Node)) );
+            printf( "%s%d ", Abc_LitIsCompl(Node) ? "*":"", Abc_Lit2Var(Node) );
     }
     printf( "\n" );
 }
@@ -1316,7 +1315,7 @@ int Acb_NtkOptNode( Acb_Mfs_t * p, int Pivot )
     p->timeWin  += Abc_Clock() - clk;
     PivotVar = Vec_IntFind( vWin, Abc_Var2Lit(Pivot, 0) );
     if ( p->pPars->fVerbose )
-    printf( "Node %d: Window contains %d objects and %d divisors.  ", Vec_IntEntry(&p->pNtk->vArray2, Pivot), Vec_IntSize(vWin), nDivs );
+    printf( "Node %d: Window contains %d objects and %d divisors.  ", Pivot, Vec_IntSize(vWin), nDivs );
 //    Acb_WinPrint( p->pNtk, vWin, Pivot, nDivs );
 //    Acb_NtkPrintVecWin( p->pNtk, vWin, "Win" );
     if ( Vec_IntSize(vWin) > p->pPars->nWinNodeMax )
@@ -1445,7 +1444,7 @@ int Acb_NtkOptNode( Acb_Mfs_t * p, int Pivot )
     }
 
 //#if 0
-    if ( Acb_NtkObjMffcEstimate(p->pNtk, Pivot) >= 2 )// && Pivot != 70 )
+    if ( p->pPars->fUseAshen && Acb_NtkObjMffcEstimate(p->pNtk, Pivot) >= 2 )// && Pivot != 70 )
     {
         p->nTwoNodes++;
         // derive SAT solver
@@ -1614,7 +1613,7 @@ void Acb_NtkOpt( Acb_Ntk_t * pNtk, Acb_Par_t * pPars )
         while ( Vec_QueTopPriority(pNtk->vQue) > 0 )
         {
             int iObj = Vec_QuePop(pNtk->vQue);
-            if ( Acb_ObjLevelD(pNtk, iObj) == 1 )
+            if ( !Acb_ObjType(pNtk, iObj) )
                 continue;
             //if ( iObj != 28 )
             //    continue;
diff --git a/src/base/acb/acbPar.h b/src/base/acb/acbPar.h
index eb60d753..a3c21e47 100644
--- a/src/base/acb/acbPar.h
+++ b/src/base/acb/acbPar.h
@@ -46,6 +46,7 @@ struct Acb_Par_t_
     int             nGrowthLevel;  // the maximum allowed growth in level
     int             nBTLimit;      // the maximum number of conflicts in one SAT run
     int             nNodesMax;     // the maximum number of nodes to try
+    int             fUseAshen;     // user Ashenhurst decomposition
     int             iNodeOne;      // one particular node to try
     int             fArea;         // performs optimization for area
     int             fMoreEffort;   // performs high-affort minimization
diff --git a/src/base/acb/acbUtil.c b/src/base/acb/acbUtil.c
index 48cc9458..4b839ec2 100644
--- a/src/base/acb/acbUtil.c
+++ b/src/base/acb/acbUtil.c
@@ -133,13 +133,14 @@ int Acb_NtkComputeLevelR( Acb_Ntk_t * p, Vec_Int_t * vTfi )
 {
     // it is assumed that vTfi contains CI nodes
     int i, iObj, Level = 0;
-    if ( !Acb_NtkHasObjLevelD( p ) )
-        Acb_NtkCleanObjLevelD( p );
+    if ( !Acb_NtkHasObjLevelR( p ) )
+        Acb_NtkCleanObjLevelR( p );
     Vec_IntForEachEntryReverse( vTfi, iObj, i )
         Acb_ObjComputeLevelR( p, iObj );
     Acb_NtkForEachCi( p, iObj, i )
         Level = Abc_MaxInt( Level, Acb_ObjLevelR(p, iObj) );
-    assert( p->LevelMax == Level );
+//    assert( p->LevelMax == Level );
+    p->LevelMax = Level;
     return Level;
 }
 
@@ -176,16 +177,38 @@ int Acb_ObjComputePathD( Acb_Ntk_t * p, int iObj )
             Path += Acb_ObjPathD(p, iFanin);
     return Acb_ObjSetPathD( p, iObj, Path );
 }
-int Acb_NtkComputePathsD( Acb_Ntk_t * p, Vec_Int_t * vTfo )
+int Acb_NtkComputePathsD( Acb_Ntk_t * p, Vec_Int_t * vTfo, int fReverse )
 {
     int i, iObj, Path = 0;
-    // it is assumed that vTfo contains CO nodes
+    //Vec_IntPrint( vTfo );
+    if ( !Acb_NtkHasObjPathD( p ) )
+        Acb_NtkCleanObjPathD( p );
+    // it is assumed that vTfo contains CI nodes
     //assert( Acb_ObjSlack(p, Vec_IntEntry(vTfo, 0)) );
-    Vec_IntForEachEntryReverse( vTfo, iObj, i )
-        if ( !Acb_ObjSlack(p, iObj) )
-            Acb_ObjComputePathD( p, iObj );
-        else
-            Acb_ObjSetPathD( p, iObj, 0 );
+    if ( fReverse )
+    {
+        Vec_IntForEachEntryReverse( vTfo, iObj, i )
+        {
+            if ( Acb_ObjIsCi(p, iObj) )
+                Acb_ObjSetPathD( p, iObj, Acb_ObjSlack(p, iObj) == 0 );
+            else if ( Acb_ObjSlack(p, iObj) )
+                Acb_ObjSetPathD( p, iObj, 0 );
+            else
+                Acb_ObjComputePathD( p, iObj );
+        }
+    }
+    else
+    {
+        Vec_IntForEachEntry( vTfo, iObj, i )
+        {
+            if ( Acb_ObjIsCi(p, iObj) )
+                Acb_ObjSetPathD( p, iObj, Acb_ObjSlack(p, iObj) == 0 );
+            else if ( Acb_ObjSlack(p, iObj) )
+                Acb_ObjSetPathD( p, iObj, 0 );
+            else
+                Acb_ObjComputePathD( p, iObj );
+        }
+    }
     Acb_NtkForEachCo( p, iObj, i )
         Path += Acb_ObjPathD(p, iObj);
     p->nPaths = Path;
@@ -201,30 +224,69 @@ int Acb_ObjComputePathR( Acb_Ntk_t * p, int iObj )
             Path += Acb_ObjPathR(p, iFanout);
     return Acb_ObjSetPathR( p, iObj, Path );
 }
-int Acb_NtkComputePathsR( Acb_Ntk_t * p, Vec_Int_t * vTfi )
+int Acb_NtkComputePathsR( Acb_Ntk_t * p, Vec_Int_t * vTfi, int fReverse )
 {
     int i, iObj, Path = 0;
-    // it is assumed that vTfi contains CI nodes
+    if ( !Acb_NtkHasObjPathR( p ) )
+        Acb_NtkCleanObjPathR( p );
+    // it is assumed that vTfi contains CO nodes
     //assert( Acb_ObjSlack(p, Vec_IntEntry(vTfi, 0)) );
-    Vec_IntForEachEntryReverse( vTfi, iObj, i )
-        if ( !Acb_ObjSlack(p, iObj) )
-            Acb_ObjComputePathR( p, iObj );
-        else
-            Acb_ObjSetPathR( p, iObj, 0 );
+    if ( fReverse )
+    {
+        Vec_IntForEachEntryReverse( vTfi, iObj, i )
+        {
+            if ( Acb_ObjIsCo(p, iObj) )
+                Acb_ObjSetPathR( p, iObj, Acb_ObjSlack(p, iObj) == 0 );
+            else if ( Acb_ObjSlack(p, iObj) )
+                Acb_ObjSetPathR( p, iObj, 0 );
+            else
+                Acb_ObjComputePathR( p, iObj );
+        }
+    }
+    else
+    {
+        Vec_IntForEachEntry( vTfi, iObj, i )
+        {
+            if ( Acb_ObjIsCo(p, iObj) )
+                Acb_ObjSetPathR( p, iObj, Acb_ObjSlack(p, iObj) == 0 );
+            else if ( Acb_ObjSlack(p, iObj) )
+                Acb_ObjSetPathR( p, iObj, 0 );
+            else
+                Acb_ObjComputePathR( p, iObj );
+        }
+    }
     Acb_NtkForEachCi( p, iObj, i )
         Path += Acb_ObjPathR(p, iObj);
-    assert( p->nPaths == Path );
+//    assert( p->nPaths == Path );
+    p->nPaths = Path;
     return Path;
 }
 
+void Acb_NtkPrintPaths( Acb_Ntk_t * p )
+{
+    int iObj;
+    Acb_NtkForEachObj( p, iObj )
+    {
+        printf( "Obj = %5d : ", iObj );
+        printf( "PathD = %5d  ", Acb_ObjPathD(p, iObj) );
+        printf( "PathR = %5d  ", Acb_ObjPathR(p, iObj) );
+        printf( "Paths = %5d  ", Acb_ObjPathD(p, iObj) + Acb_ObjPathR(p, iObj) );
+        printf( "\n" );
+    }
+}
+
 int Acb_NtkComputePaths( Acb_Ntk_t * p )
 {
+    int LevelD, LevelR;
     Vec_Int_t * vTfi = Acb_ObjCollectTfi( p, -1, 1 );
     Vec_Int_t * vTfo = Acb_ObjCollectTfo( p, -1, 1 );
-    Acb_NtkComputeLevelD( p, vTfi );
-    Acb_NtkComputeLevelR( p, vTfo );
-    Acb_NtkComputePathsD( p, vTfi );
-    Acb_NtkComputePathsR( p, vTfo );
+    Acb_NtkComputeLevelD( p, vTfo );
+    LevelD = p->LevelMax;
+    Acb_NtkComputeLevelR( p, vTfi );
+    LevelR = p->LevelMax;
+    assert( LevelD == LevelR );
+    Acb_NtkComputePathsD( p, vTfo, 1 );
+    Acb_NtkComputePathsR( p, vTfi, 1 );
     return p->nPaths;
 }
 void Abc_NtkComputePaths( Abc_Ntk_t * p )
@@ -232,7 +294,9 @@ void Abc_NtkComputePaths( Abc_Ntk_t * p )
     extern Acb_Ntk_t * Acb_NtkFromAbc( Abc_Ntk_t * p );
     Acb_Ntk_t * pNtk = Acb_NtkFromAbc( p );
     Acb_NtkCreateFanout( pNtk );
+    Acb_NtkCleanObjCounts( pNtk );
     printf( "Computed %d paths.\n", Acb_NtkComputePaths(pNtk) );
+    Acb_NtkPrintPaths( pNtk );
     Acb_ManFree( pNtk->pDesign );
 }
 
@@ -251,6 +315,8 @@ void Abc_NtkComputePaths( Abc_Ntk_t * p )
 void Acb_ObjUpdatePriority( Acb_Ntk_t * p, int iObj )
 {
     int nPaths;
+    if ( Acb_ObjIsCio(p, iObj) || Acb_ObjLevelD(p, iObj) == 1 )
+        return;
     if ( p->vQue == NULL )
     {
         Acb_NtkCleanObjCounts( p );
@@ -258,35 +324,63 @@ void Acb_ObjUpdatePriority( Acb_Ntk_t * p, int iObj )
         Vec_QueSetPriority( p->vQue, Vec_FltArrayP(&p->vCounts) );
     }
     nPaths = Acb_ObjPathD(p, iObj) + Acb_ObjPathR(p, iObj);
-    if ( nPaths == 0 )
-        return;
     Acb_ObjSetCounts( p, iObj, (float)nPaths );
     if ( Vec_QueIsMember( p->vQue, iObj ) )
+    {
+//printf( "Updating object %d with count %d\n", iObj, nPaths );
         Vec_QueUpdate( p->vQue, iObj );
-    else
+    }
+    else if ( nPaths )
+    {
+//printf( "Adding object %d with count %d\n", iObj, nPaths );
         Vec_QuePush( p->vQue, iObj );
+    }
 }
 void Acb_NtkUpdateTiming( Acb_Ntk_t * p, int iObj )
 {
     int i, Entry, LevelMax = p->LevelMax;
-    // assuming that level of the new nodes is up to date
+    int LevelD, LevelR, nPaths1, nPaths2;
+    // assuming that direct level of the new nodes (including iObj) is up to date
     Vec_Int_t * vTfi = Acb_ObjCollectTfi( p, iObj, 1 );
     Vec_Int_t * vTfo = Acb_ObjCollectTfo( p, iObj, 1 );
+    if ( iObj > 0 )
+    {
+        assert( Vec_IntEntryLast(vTfi) == iObj );
+        assert( Vec_IntEntryLast(vTfo) == iObj );
+        Vec_IntPop( vTfo );
+    }
     Acb_NtkComputeLevelD( p, vTfo );
+    LevelD = p->LevelMax;
     Acb_NtkComputeLevelR( p, vTfi );
+    LevelR = p->LevelMax;
+    assert( LevelD == LevelR );
     if ( iObj > 0 && LevelMax > p->LevelMax ) // reduced level
     {
+        iObj = -1;
         vTfi = Acb_ObjCollectTfi( p, -1, 1 );
         vTfo = Acb_ObjCollectTfo( p, -1, 1 );   
         Vec_QueClear( p->vQue );
         // add backup here
     }
-    Acb_NtkComputePathsD( p, vTfo );
-    Acb_NtkComputePathsR( p, vTfi );
+    if ( iObj > 0 )
+    Acb_NtkComputePathsD( p, vTfi, 0 );
+    Acb_NtkComputePathsD( p, vTfo, 1 );
+    nPaths1 = p->nPaths;
+    if ( iObj > 0 )
+    Acb_NtkComputePathsR( p, vTfo, 0 );
+    Acb_NtkComputePathsR( p, vTfi, 1 );
+    nPaths2 = p->nPaths;
+    assert( nPaths1 == nPaths2 );
     Vec_IntForEachEntry( vTfi, Entry, i )
         Acb_ObjUpdatePriority( p, Entry );
+    if ( iObj > 0 )
     Vec_IntForEachEntry( vTfo, Entry, i )
         Acb_ObjUpdatePriority( p, Entry );
+
+//    printf( "Updating timing for object %d.\n", iObj );
+//    Acb_NtkPrintPaths( p );
+//    while ( (Entry = (int)Vec_QueTopPriority(p->vQue)) > 0 )
+//        printf( "Obj = %5d : Prio = %d.\n", Vec_QuePop(p->vQue), Entry );
 }
 
 /**Function*************************************************************
@@ -341,6 +435,7 @@ void Acb_NtkResetNode( Acb_Ntk_t * p, int Pivot, word uTruth, Vec_Int_t * vSupp
 void Acb_NtkUpdateNode( Acb_Ntk_t * p, int Pivot, word uTruth, Vec_Int_t * vSupp )
 {
     Acb_NtkResetNode( p, Pivot, uTruth, vSupp );
+    Acb_ObjComputeLevelD( p, Pivot );
     if ( p->vQue == NULL )
         Acb_NtkUpdateLevelD( p, Pivot );
     else
-- 
cgit v1.2.3


From 2373c5b15cb81bd775362ebfb3dd8918c200f30b Mon Sep 17 00:00:00 2001
From: Alan Mishchenko <alanmi@berkeley.edu>
Date: Wed, 5 Apr 2017 22:02:05 -0700
Subject: Adding stand-alone cut computation to GIA.

---
 src/base/abci/abc.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'src/base')

diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c
index d28a5abd..b7c9e0cd 100644
--- a/src/base/abci/abc.c
+++ b/src/base/abci/abc.c
@@ -12384,7 +12384,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
 //        extern void Cba_PrsReadBlifTest();
 //        Cba_PrsReadBlifTest();
     }
-    Abc_NtkComputePaths( Abc_FrameReadNtk(pAbc) );
+//    Abc_NtkComputePaths( Abc_FrameReadNtk(pAbc) );
     return 0;
 usage:
     Abc_Print( -2, "usage: test [-CKDNM] [-aovwh] <file_name>\n" );
@@ -43491,7 +43491,7 @@ int Abc_CommandAbc9Test( Abc_Frame_t * pAbc, int argc, char ** argv )
 //    extern void Gia_ManCheckFalseTest( Gia_Man_t * p, int nSlackMax );
 //    extern void Gia_ParTest( Gia_Man_t * p, int nWords, int nProcs );
 //    extern void Gia_ManTisTest( Gia_Man_t * pInit );
-    extern void Gia_Iso3Test( Gia_Man_t * p );
+    extern void Gia_StoComputeCuts( Gia_Man_t * p );
 
     Extra_UtilGetoptReset();
     while ( ( c = Extra_UtilGetopt( argc, argv, "WPFsvh" ) ) != EOF )
@@ -43595,7 +43595,7 @@ int Abc_CommandAbc9Test( Abc_Frame_t * pAbc, int argc, char ** argv )
 //    Jf_ManTestCnf( pAbc->pGia );
 //    Gia_ManCheckFalseTest( pAbc->pGia, nFrames );
 //    Gia_ParTest( pAbc->pGia, nWords, nProcs );
-//Cec2_ManSimulateTest( pAbc->pGia );
+    Gia_StoComputeCuts( pAbc->pGia );
 //    printf( "\nThis command is currently disabled.\n\n" );
     return 0;
 usage:
-- 
cgit v1.2.3