sfmDec.c 83.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/**CFile****************************************************************

  FileName    [sfmDec.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [SAT-based optimization using internal don't-cares.]

  Synopsis    [SAT-based decomposition.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - June 20, 2005.]

  Revision    [$Id: sfmDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]

***********************************************************************/

#include "sfmInt.h"
22 23
#include "misc/st/st.h"
#include "map/mio/mio.h"
24
#include "base/abc/abc.h"
25 26
#include "misc/util/utilTruth.h"
#include "opt/dau/dau.h"
27
#include "map/mio/exp.h"
28 29
#include "map/scl/sclCon.h"
#include "base/main/main.h"
30 31 32 33 34 35 36 37 38 39 40

ABC_NAMESPACE_IMPL_START


////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

typedef struct Sfm_Dec_t_ Sfm_Dec_t;
struct Sfm_Dec_t_
{
41
    // external
42
    Sfm_Par_t *       pPars;       // parameters
43
    Sfm_Lib_t *       pLib;        // library
44
    Sfm_Tim_t *       pTim;        // timing
45
    Sfm_Mit_t *       pMit;        // timing
46
    Abc_Ntk_t *       pNtk;        // network
47 48 49 50
    // library
    Vec_Int_t         vGateSizes;  // fanin counts
    Vec_Wrd_t         vGateFuncs;  // gate truth tables
    Vec_Wec_t         vGateCnfs;   // gate CNFs
51 52 53 54 55
    Vec_Ptr_t         vGateHands;  // gate handles
    int               GateConst0;  // special gates
    int               GateConst1;  // special gates
    int               GateBuffer;  // special gates
    int               GateInvert;  // special gates
56 57
    int               GateAnd[4];  // special gates
    int               GateOr[4];   // special gates
58
    // objects
59 60
    int               nDivs;       // the number of divisors
    int               nMffc;       // the number of divisors
61
    int               AreaMffc;    // the area of gates in MFFC
62
    int               DelayMin;    // temporary min delay
63
    int               iTarget;     // target node
64
    int               iUseThis;    // next cofactoring var to try
65
    int               DeltaCrit;   // critical delta
66 67 68
    int               AreaInv;     // inverter area
    int               DelayInv;    // inverter delay
    Mio_Gate_t *      pGateInv;    // inverter
69
    word              uCareSet;    // computed careset
70
    Vec_Int_t         vObjRoots;   // roots of the window
71 72
    Vec_Int_t         vObjGates;   // functionality
    Vec_Wec_t         vObjFanins;  // fanin IDs
73 74
    Vec_Int_t         vObjMap;     // object map
    Vec_Int_t         vObjDec;     // decomposition
75 76 77 78
    Vec_Int_t         vObjMffc;    // MFFC nodes
    Vec_Int_t         vObjInMffc;  // inputs of MFFC nodes
    Vec_Wrd_t         vObjSims;    // simulation patterns
    Vec_Wrd_t         vObjSims2;   // simulation patterns
79 80
    Vec_Ptr_t         vMatchGates; // matched gates
    Vec_Ptr_t         vMatchFans;  // matched fanins
81 82 83 84 85
    // solver
    sat_solver *      pSat;        // reusable solver 
    Vec_Wec_t         vClauses;    // CNF clauses for the node
    Vec_Int_t         vImpls[2];   // onset/offset implications
    Vec_Wrd_t         vSets[2];    // onset/offset patterns
86
    int               nPats[2];    // CEX count
87
    int               nPatWords[2];// CEX words
88 89
    int               nDivWords;   // div words
    int               nDivWordsAlloc; // div words
90 91
    word              TtElems[SFM_SUPP_MAX][SFM_WORD_MAX];
    word *            pTtElems[SFM_SUPP_MAX];
92
    word *            pDivWords[SFM_SUPP_MAX];
93
    // temporary
94 95 96 97 98 99
    Vec_Int_t         vNewNodes;
    Vec_Int_t         vGateTfi;
    Vec_Int_t         vGateTfo;
    Vec_Int_t         vGateCut;
    Vec_Int_t         vGateTemp;
    Vec_Int_t         vGateMffc;
100
    Vec_Int_t         vCands;
101 102
    word              Copy[4];
    int               nSuppVars;
103
    // statistics
104
    abctime           timeLib;
105 106 107
    abctime           timeWin;
    abctime           timeCnf;
    abctime           timeSat;
108 109
    abctime           timeSatSat;
    abctime           timeSatUnsat;
110
    abctime           timeEval;
111
    abctime           timeTime;
112 113 114 115 116 117 118 119 120 121 122 123 124
    abctime           timeOther;
    abctime           timeStart;
    abctime           timeTotal;
    int               nTotalNodesBeg;
    int               nTotalEdgesBeg;
    int               nTotalNodesEnd;
    int               nTotalEdgesEnd;
    int               nNodesTried;
    int               nNodesChanged;
    int               nNodesConst0;
    int               nNodesConst1;
    int               nNodesBuf;
    int               nNodesInv;
125
    int               nNodesAndOr;
126 127
    int               nNodesResyn;
    int               nSatCalls;
128 129
    int               nSatCallsSat;
    int               nSatCallsUnsat;
130
    int               nSatCallsOver;
131 132
    int               nTimeOuts;
    int               nNoDecs;
133
    int               nEfforts;
134 135 136 137
    int               nMaxDivs;
    int               nMaxWin;
    word              nAllDivs;
    word              nAllWin;
138 139
    int               nLuckySizes[SFM_SUPP_MAX+1];
    int               nLuckyGates[SFM_SUPP_MAX+1];
140 141
};

142 143 144 145 146 147 148 149 150
#define SFM_MASK_PI     1  // supp(node) is contained in supp(TFI(pivot))
#define SFM_MASK_INPUT  2  // supp(node) does not overlap with supp(TFI(pivot))
#define SFM_MASK_FANIN  4  // the same as above (pointed to by node with SFM_MASK_PI | SFM_MASK_INPUT)
#define SFM_MASK_MFFC   8  // MFFC nodes, including the target node
#define SFM_MASK_PIVOT 16  // the target node

static inline Sfm_Dec_t * Sfm_DecMan( Abc_Obj_t * p )                        { return (Sfm_Dec_t *)p->pNtk->pData;                  }
static inline word        Sfm_DecObjSim( Sfm_Dec_t * p, Abc_Obj_t * pObj )   { return Vec_WrdEntry(&p->vObjSims, Abc_ObjId(pObj));  }
static inline word        Sfm_DecObjSim2( Sfm_Dec_t * p, Abc_Obj_t * pObj )  { return Vec_WrdEntry(&p->vObjSims2, Abc_ObjId(pObj)); }
151
static inline word *      Sfm_DecDivPats( Sfm_Dec_t * p, int d, int c )      { return Vec_WrdEntryP(&p->vSets[c], d*SFM_SIM_WORDS); }
152

153
static inline int         Sfm_ManReadObjDelay( Sfm_Dec_t * p, int Id )       { return p->pMit ? Sfm_MitReadObjDelay(p->pMit, Id) : Sfm_TimReadObjDelay(p->pTim, Id); }
154
static inline int         Sfm_ManReadNtkDelay( Sfm_Dec_t * p )               { return p->pMit ? Sfm_MitReadNtkDelay(p->pMit)     : Sfm_TimReadNtkDelay(p->pTim);     }
155
static inline int         Sfm_ManReadNtkMinSlack( Sfm_Dec_t * p )            { return p->pMit ? Sfm_MitReadNtkMinSlack(p->pMit)  : 0;                                }
156 157


158

159 160 161 162 163 164
////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

/**Function*************************************************************

165 166 167 168 169 170 171 172 173 174 175 176
  Synopsis    [Setup parameter structure.]

  Description []

  SideEffects []

  SeeAlso     []

***********************************************************************/
void Sfm_ParSetDefault3( Sfm_Par_t * pPars )
{
    memset( pPars, 0, sizeof(Sfm_Par_t) );
177 178
    pPars->nTfoLevMax   =  100;  // the maximum fanout levels
    pPars->nTfiLevMax   =  100;  // the maximum fanin levels
179
    pPars->nFanoutMax   =   10;  // the maximum number of fanouts
180
    pPars->nMffcMin     =    1;  // the maximum MFFC size
181
    pPars->nMffcMax     =    3;  // the maximum MFFC size
182
    pPars->nVarMax      =    6;  // the maximum variable count
183
    pPars->nDecMax      =    1;  // the maximum number of decompositions
184
    pPars->nWinSizeMax  =    0;  // the maximum window size
185
    pPars->nGrowthLevel =    0;  // the maximum allowed growth in level
186
    pPars->nBTLimit     =    0;  // the maximum number of conflicts in one SAT run
187
    pPars->nTimeWin     =    1;  // the size of timing window in percents
188
    pPars->DeltaCrit    =    0;  // delta delay in picoseconds
189 190
    pPars->fUseAndOr    =    0;  // enable internal detection of AND/OR gates
    pPars->fZeroCost    =    0;  // enable zero-cost replacement
191
    pPars->fMoreEffort  =    0;  // enables using more effort
192
    pPars->fUseSim      =    0;  // enable simulation
193
    pPars->fArea        =    0;  // performs optimization for area
194 195 196 197 198 199
    pPars->fVerbose     =    0;  // enable basic stats
    pPars->fVeryVerbose =    0;  // enable detailed stats
}

/**Function*************************************************************

200 201 202 203 204 205 206 207 208
  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
209
Sfm_Dec_t * Sfm_DecStart( Sfm_Par_t * pPars, Mio_Library_t * pLib, Abc_Ntk_t * pNtk )
210
{
211
    extern void Sfm_LibPreprocess( Mio_Library_t * pLib, Vec_Int_t * vGateSizes, Vec_Wrd_t * vGateFuncs, Vec_Wec_t * vGateCnfs, Vec_Ptr_t * vGateHands );
212
    Sfm_Dec_t * p = ABC_CALLOC( Sfm_Dec_t, 1 ); int i;
213
    p->timeStart = Abc_Clock();
214 215 216
    p->pPars     = pPars;
    p->pNtk      = pNtk;
    p->pSat      = sat_solver_new();
217
    p->pGateInv  = Mio_LibraryReadInv( pLib );
218 219 220
    p->AreaInv   = Scl_Flt2Int(Mio_GateReadArea(p->pGateInv));
    p->DelayInv  = Scl_Flt2Int(Mio_GateReadDelayMax(p->pGateInv));
    p->DeltaCrit = pPars->DeltaCrit ? Scl_Flt2Int((float)pPars->DeltaCrit) : 5 * Scl_Flt2Int(Mio_LibraryReadDelayInvMax(pLib)) / 2;
221
p->timeLib = Abc_Clock();
222
    p->pLib = Sfm_LibPrepare( pPars->nVarMax, 1, !pPars->fArea, pPars->fVerbose, pPars->fLibVerbose );
223
p->timeLib = Abc_Clock() - p->timeLib;
224
    if ( !pPars->fArea )
225
    {
226 227
        if ( Abc_FrameReadLibScl() )
            p->pMit = Sfm_MitStart( pLib, (SC_Lib *)Abc_FrameReadLibScl(), Scl_ConReadMan(), pNtk, p->DeltaCrit );
228
        if ( p->pMit == NULL )
229
            p->pTim = Sfm_TimStart( pLib, Scl_ConReadMan(), pNtk, p->DeltaCrit );
230
    }
231
    if ( pPars->fVeryVerbose )
232
//    if ( pPars->fVerbose )
233
        Sfm_LibPrint( p->pLib );
234 235 236 237 238 239 240 241
    pNtk->pData = p;
    // enter library
    assert( Abc_NtkIsMappedLogic(pNtk) );
    Sfm_LibPreprocess( pLib, &p->vGateSizes, &p->vGateFuncs, &p->vGateCnfs, &p->vGateHands );
    p->GateConst0 = Mio_GateReadValue( Mio_LibraryReadConst0(pLib) );
    p->GateConst1 = Mio_GateReadValue( Mio_LibraryReadConst1(pLib) );
    p->GateBuffer = Mio_GateReadValue( Mio_LibraryReadBuf(pLib) );
    p->GateInvert = Mio_GateReadValue( Mio_LibraryReadInv(pLib) );
242 243 244 245
    // elementary truth tables
    for ( i = 0; i < SFM_SUPP_MAX; i++ )
        p->pTtElems[i] = p->TtElems[i];
    Abc_TtElemInit( p->pTtElems, SFM_SUPP_MAX );
246
    p->iUseThis = -1;
247 248 249 250
    return p;
}
void Sfm_DecStop( Sfm_Dec_t * p )
{
251
    Abc_Ntk_t * pNtk = p->pNtk;
252 253 254 255
    Abc_Obj_t * pObj; int i;
    Abc_NtkForEachNode( pNtk, pObj, i )
        if ( (int)pObj->Level != Abc_ObjLevelNew(pObj) )
            printf( "Level count mismatch at node %d.\n", i );
256
    Sfm_LibStop( p->pLib );
257
    if ( p->pTim ) Sfm_TimStop( p->pTim );
258
    if ( p->pMit ) Sfm_MitStop( p->pMit );
259 260 261
    // divisors
    for ( i = 0; i < SFM_SUPP_MAX; i++ )
        ABC_FREE( p->pDivWords[i] );
262 263 264 265
    // library
    Vec_IntErase( &p->vGateSizes );
    Vec_WrdErase( &p->vGateFuncs );
    Vec_WecErase( &p->vGateCnfs );
266
    Vec_PtrErase( &p->vGateHands );
267
    // objects
268
    Vec_IntErase( &p->vObjRoots );
269 270
    Vec_IntErase( &p->vObjGates );
    Vec_WecErase( &p->vObjFanins );
271 272
    Vec_IntErase( &p->vObjMap );
    Vec_IntErase( &p->vObjDec );
273 274 275 276
    Vec_IntErase( &p->vObjMffc );
    Vec_IntErase( &p->vObjInMffc );
    Vec_WrdErase( &p->vObjSims );
    Vec_WrdErase( &p->vObjSims2 );
277 278
    Vec_PtrErase( &p->vMatchGates );
    Vec_PtrErase( &p->vMatchFans );
279 280 281 282 283 284 285 286
    // solver
    sat_solver_delete( p->pSat );
    Vec_WecErase( &p->vClauses );
    Vec_IntErase( &p->vImpls[0] );
    Vec_IntErase( &p->vImpls[1] );
    Vec_WrdErase( &p->vSets[0] );
    Vec_WrdErase( &p->vSets[1] );
    // temporary
287 288 289 290 291 292
    Vec_IntErase( &p->vNewNodes );
    Vec_IntErase( &p->vGateTfi );
    Vec_IntErase( &p->vGateTfo );
    Vec_IntErase( &p->vGateCut );
    Vec_IntErase( &p->vGateTemp );
    Vec_IntErase( &p->vGateMffc );
293
    Vec_IntErase( &p->vCands );
294
    ABC_FREE( p );
295
    pNtk->pData = NULL;
296 297 298 299 300 301 302 303 304 305 306 307 308
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
309 310 311 312 313
static inline word Sfm_ObjSimulate( Abc_Obj_t * pObj )
{
    Sfm_Dec_t * p = Sfm_DecMan( pObj );
    Vec_Int_t * vExpr = Mio_GateReadExpr( (Mio_Gate_t *)pObj->pData );
    Abc_Obj_t * pFanin; int i; word uFanins[6];
314
    assert( Abc_ObjFaninNum(pObj) <= 6 );
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
    Abc_ObjForEachFanin( pObj, pFanin, i )
        uFanins[i] = Sfm_DecObjSim( p, pFanin );
    return Exp_Truth6( Abc_ObjFaninNum(pObj), vExpr, uFanins );
}
static inline word Sfm_ObjSimulate2( Abc_Obj_t * pObj )
{
    Sfm_Dec_t * p = Sfm_DecMan( pObj );
    Vec_Int_t * vExpr = Mio_GateReadExpr( (Mio_Gate_t *)pObj->pData );
    Abc_Obj_t * pFanin; int i; word uFanins[6];
    Abc_ObjForEachFanin( pObj, pFanin, i )
        if ( (pFanin->iTemp & SFM_MASK_PIVOT) )
            uFanins[i] = Sfm_DecObjSim2( p, pFanin );
        else
            uFanins[i] = Sfm_DecObjSim( p, pFanin );
    return Exp_Truth6( Abc_ObjFaninNum(pObj), vExpr, uFanins );
}
static inline void Sfm_NtkSimulate( Abc_Ntk_t * pNtk )
{
    Vec_Ptr_t * vNodes;
    Abc_Obj_t * pObj; int i; word uTemp;
    Sfm_Dec_t * p = Sfm_DecMan( Abc_NtkPi(pNtk, 0) );
    Vec_WrdFill( &p->vObjSims,  2*Abc_NtkObjNumMax(pNtk), 0 );
    Vec_WrdFill( &p->vObjSims2, 2*Abc_NtkObjNumMax(pNtk), 0 );
    Gia_ManRandomW(1);
    assert( p->pPars->fUseSim );
    Abc_NtkForEachCi( pNtk, pObj, i )
    {
        Vec_WrdWriteEntry( &p->vObjSims, Abc_ObjId(pObj), (uTemp = Gia_ManRandomW(0)) );
        //printf( "Inpt = %5d : ", Abc_ObjId(pObj) );
        //Extra_PrintBinary( stdout, (unsigned *)&uTemp, 64 );
        //printf( "\n" );
    }
    vNodes = Abc_NtkDfs( pNtk, 1 );
    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
    {
        Vec_WrdWriteEntry( &p->vObjSims, Abc_ObjId(pObj), (uTemp = Sfm_ObjSimulate(pObj)) );
        //printf( "Obj  = %5d : ", Abc_ObjId(pObj) );
        //Extra_PrintBinary( stdout, (unsigned *)&uTemp, 64 );
        //printf( "\n" );
    }
    Vec_PtrFree( vNodes );
}
static inline void Sfm_ObjSimulateNode( Abc_Obj_t * pObj )
{
    Sfm_Dec_t * p = Sfm_DecMan( pObj );
    if ( !p->pPars->fUseSim )
        return;
    Vec_WrdWriteEntry( &p->vObjSims, Abc_ObjId(pObj), Sfm_ObjSimulate(pObj) );
    if ( (pObj->iTemp & SFM_MASK_PIVOT) )
        Vec_WrdWriteEntry( &p->vObjSims2, Abc_ObjId(pObj), Sfm_ObjSimulate2(pObj) );
}
static inline void Sfm_ObjFlipNode( Abc_Obj_t * pObj )
{
    Sfm_Dec_t * p = Sfm_DecMan( pObj );
    if ( !p->pPars->fUseSim )
        return;
    Vec_WrdWriteEntry( &p->vObjSims2, Abc_ObjId(pObj), ~Sfm_DecObjSim(p, pObj) );
}
static inline word Sfm_ObjFindCareSet( Abc_Ntk_t * pNtk, Vec_Int_t * vRoots )
{
    Sfm_Dec_t * p = Sfm_DecMan( Abc_NtkPi(pNtk, 0) );
    Abc_Obj_t * pObj; int i; word Res = 0;
    if ( !p->pPars->fUseSim )
        return 0;
    Abc_NtkForEachObjVec( vRoots, pNtk, pObj, i )
        Res |= Sfm_DecObjSim(p, pObj) ^ Sfm_DecObjSim2(p, pObj);
    return Res;
}
static inline void Sfm_ObjSetupSimInfo( Abc_Obj_t * pObj )
{
385
    Sfm_Dec_t * p = Sfm_DecMan( pObj ); int i;
386 387 388 389
    p->nPats[0]     = p->nPats[1] = 0;
    p->nPatWords[0] = p->nPatWords[1] = 0;
    Vec_WrdFill( &p->vSets[0], p->nDivs*SFM_SIM_WORDS, 0 );
    Vec_WrdFill( &p->vSets[1], p->nDivs*SFM_SIM_WORDS, 0 );
390 391 392 393 394 395 396 397 398 399
    // alloc divwords
    p->nDivWords = Abc_Bit6WordNum( 4 * p->nDivs );
    if ( p->nDivWordsAlloc < p->nDivWords )
    {
        p->nDivWordsAlloc = Abc_MaxInt( 16, p->nDivWords );
        for ( i = 0; i < SFM_SUPP_MAX; i++ )
            p->pDivWords[i] = ABC_REALLOC( word, p->pDivWords[i], p->nDivWordsAlloc );
    }
    memset( p->pDivWords[0], 0, sizeof(word) * p->nDivWords );
    // collect simulation info
400
    if ( p->pPars->fUseSim && p->uCareSet != 0 )
401
    {
402 403 404 405 406 407 408 409 410 411 412 413
        word uCareSet = p->uCareSet;
        word uValues  = Sfm_DecObjSim(p, pObj);
        int c, d, i, Indexes[2][64];
        assert( p->iTarget == pObj->iTemp );
        assert( p->pPars->fUseSim );
        // find what patterns go to on-set/off-set
        for ( i = 0; i < 64; i++ )
            if ( (uCareSet >> i) & 1 )
            {
                c = !((uValues >> i) & 1);
                Indexes[c][p->nPats[c]++] = i;
            }
414
        for ( c = 0; c < 2; c++ )
415 416 417 418 419 420 421 422 423 424 425
            p->nPatWords[c] = 1 + (p->nPats[c] >> 6);
        // write patterns
        for ( d = 0; d < p->nDivs; d++ )
        {
            word uSim = Vec_WrdEntry( &p->vObjSims, Vec_IntEntry(&p->vObjMap, d) );
            for ( c = 0; c < 2; c++ )
                for ( i = 0; i < p->nPats[c]; i++ )
                    if ( (uSim >> Indexes[c][i]) & 1 )
                        Abc_TtSetBit( Sfm_DecDivPats(p, d, c), i );
        }
        //printf( "Node %d : Onset = %d. Offset = %d.\n", pObj->Id, p->nPats[0], p->nPats[1] );
426 427 428 429 430 431 432
    }
}
static inline void Sfm_ObjSetdownSimInfo( Abc_Obj_t * pObj )
{
    int nPatKeep = 32;
    Sfm_Dec_t * p = Sfm_DecMan( pObj );
    int c, d; word uSim, uSims[2], uMask;
433 434
    if ( !p->pPars->fUseSim )
        return;
435 436 437 438 439
    for ( d = 0; d < p->nDivs; d++ )
    {
        uSim = Vec_WrdEntry( &p->vObjSims, Vec_IntEntry(&p->vObjMap, d) );
        for ( c = 0; c < 2; c++ )
        {
440 441
            uMask = Abc_Tt6Mask( Abc_MinInt(p->nPats[c], nPatKeep) );
            uSims[c] = (Sfm_DecDivPats(p, d, c)[0] & uMask) | (uSim & ~uMask);
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
            uSim >>= 32;
        }
        uSim = (uSims[0] & 0xFFFFFFFF) | (uSims[1] << 32);
        Vec_WrdWriteEntry( &p->vObjSims, Vec_IntEntry(&p->vObjMap, d), uSim );
    }
}
/*
void Sfm_ObjSetdownSimInfo( Abc_Obj_t * pObj )
{
    int nPatKeep = 32;
    Sfm_Dec_t * p = Sfm_DecMan( pObj );
    word uSim, uMaskKeep[2];
    int c, d, nKeeps[2]; 
    for ( c = 0; c < 2; c++ )
    {
        nKeeps[c] = Abc_MaxInt(p->nPats[c], nPatKeep);
        uMaskKeep[c] = Abc_Tt6Mask( nKeeps[c] );
    }
    for ( d = 0; d < p->nDivs; d++ )
    {
        uSim = Vec_WrdEntry( &p->vObjSims, Vec_IntEntry(&p->vObjMap, d) ) << (nKeeps[0] + nKeeps[1]);
        uSim |= (Vec_WrdEntry(&p->vSets[0], d) & uMaskKeep[0]) | ((Vec_WrdEntry(&p->vSets[1], d) & uMaskKeep[1]) << nKeeps[0]);
        Vec_WrdWriteEntry( &p->vObjSims, Vec_IntEntry(&p->vObjMap, d), uSim );
    }
}
*/

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
480 481
int Sfm_DecPrepareSolver( Sfm_Dec_t * p )
{
482
    Vec_Int_t * vRoots = &p->vObjRoots;
483
    Vec_Int_t * vFaninVars = &p->vGateTemp;
484
    Vec_Int_t * vLevel, * vClause;
485
    int i, k, Gate, iObj, RetValue;
486
    int nTfiSize = p->iTarget + 1; // including node
487
    int nWinSize = Vec_IntSize(&p->vObjGates);
488 489 490
    int nSatVars = 2 * nWinSize - nTfiSize;
    assert( nWinSize == Vec_IntSize(&p->vObjGates) );
    assert( p->iTarget < nWinSize );
491 492
    // create SAT solver
    sat_solver_restart( p->pSat );
493
    sat_solver_setnvars( p->pSat, nSatVars + Vec_IntSize(vRoots) );
494
    // add CNF clauses for the TFI
495
    Vec_IntForEachEntry( &p->vObjGates, Gate, i )
496
    {
497
        if ( Gate == -1 )
498 499
            continue;
        // generate CNF 
500
        vLevel = Vec_WecEntry( &p->vObjFanins, i );
501
        Vec_IntPush( vLevel, i );
502
        Sfm_TranslateCnf( &p->vClauses, (Vec_Str_t *)Vec_WecEntry(&p->vGateCnfs, Gate), vLevel, -1 );
503
        Vec_IntPop( vLevel );
504 505 506 507 508 509 510 511 512 513 514
        // add clauses
        Vec_WecForEachLevel( &p->vClauses, vClause, k )
        {
            if ( Vec_IntSize(vClause) == 0 )
                break;
            RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause) );
            if ( RetValue == 0 )
                return 0;
        }
    }
    // add CNF clauses for the TFO
515
    Vec_IntForEachEntryStart( &p->vObjGates, Gate, i, nTfiSize )
516
    {
517
        assert( Gate != -1 );
518
        vLevel = Vec_WecEntry( &p->vObjFanins, i );
519 520 521 522 523 524
        Vec_IntClear( vFaninVars );
        Vec_IntForEachEntry( vLevel, iObj, k )
            Vec_IntPush( vFaninVars, iObj <= p->iTarget ? iObj : iObj + nWinSize - nTfiSize );
        Vec_IntPush( vFaninVars, i + nWinSize - nTfiSize );
        // generate CNF 
        Sfm_TranslateCnf( &p->vClauses, (Vec_Str_t *)Vec_WecEntry(&p->vGateCnfs, Gate), vFaninVars, p->iTarget );
525 526 527 528 529 530 531 532 533 534
        // add clauses
        Vec_WecForEachLevel( &p->vClauses, vClause, k )
        {
            if ( Vec_IntSize(vClause) == 0 )
                break;
            RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause) );
            if ( RetValue == 0 )
                return 0;
        }
    }
535
    if ( nTfiSize < nWinSize )
536 537
    {
        // create XOR clauses for the roots
538
        Vec_IntClear( vFaninVars );
539
        Vec_IntForEachEntry( vRoots, iObj, i )
540
        {
541
            Vec_IntPush( vFaninVars, Abc_Var2Lit(nSatVars, 0) );
542
            sat_solver_add_xor( p->pSat, iObj, iObj + nWinSize - nTfiSize, nSatVars++, 0 );
543 544
        }
        // make OR clause for the last nRoots variables
545
        RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(vFaninVars), Vec_IntLimit(vFaninVars) );
546 547 548 549
        if ( RetValue == 0 )
            return 0;
        assert( nSatVars == sat_solver_nvars(p->pSat) );
    }
550
    else assert( Vec_IntSize(vRoots) == 1 );
551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
    // finalize
    RetValue = sat_solver_simplify( p->pSat );
    return 1;
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
567
int Sfm_DecFindCost( Sfm_Dec_t * p, int c, int iLit, word * pMask )
568
{
569 570
    word * pPats = Sfm_DecDivPats( p, Abc_Lit2Var(iLit), !c );
    return Abc_TtCountOnesVecMask( pPats, pMask, p->nPatWords[!c], Abc_LitIsCompl(iLit) );
571
}
572
void Sfm_DecPrint( Sfm_Dec_t * p, word Masks[2][SFM_SIM_WORDS] )
573
{
574 575 576 577
    int c, i, k, Entry;
    for ( c = 0; c < 2; c++ )
    {
        Vec_Int_t * vLevel = Vec_WecEntry( &p->vObjFanins, p->iTarget );
578
        printf( "%s-SET of object %d (divs = %d) with gate \"%s\" and fanins: ", 
579 580 581 582 583 584 585 586
            c ? "OFF": "ON", p->iTarget, p->nDivs, 
            Mio_GateReadName((Mio_Gate_t *)Vec_PtrEntry(&p->vGateHands, Vec_IntEntry(&p->vObjGates,p->iTarget))) );
        Vec_IntForEachEntry( vLevel, Entry, i )
            printf( "%d ", Entry );
        printf( "\n" );

        printf( "Implications: " );
        Vec_IntForEachEntry( &p->vImpls[c], Entry, i )
587
            printf( "%s%d(%d) ", Abc_LitIsCompl(Entry)? "!":"", Abc_Lit2Var(Entry), Sfm_DecFindCost(p, c, Entry, Masks[!c]) );
588 589
        printf( "\n" );
        printf( "     " );
590 591
        for ( i = 0; i < p->nDivs; i++ )
            printf( "%d", (i / 10) % 10 );
592 593
        printf( "\n" );
        printf( "     " );
594
        for ( i = 0; i < p->nDivs; i++ )
595 596 597 598 599
            printf( "%d", i % 10 );
        printf( "\n" );
        for ( k = 0; k < p->nPats[c]; k++ )
        {
            printf( "%2d : ", k );
600
            for ( i = 0; i < p->nDivs; i++ )
601
                printf( "%d", Abc_TtGetBit(Sfm_DecDivPats(p, i, c), k) );
602 603
            printf( "\n" );
        }
604
        //printf( "\n" );
605
    }
606 607 608 609
}

/**Function*************************************************************

610 611 612 613 614 615 616 617 618
  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
void Sfm_DecVarCost( Sfm_Dec_t * p, word Masks[2][SFM_SIM_WORDS], int d, int Counts[2][2] )
{
    int c; 
    for ( c = 0; c < 2; c++ )
    {
        word * pPats = Sfm_DecDivPats( p, d, c );
        int Num = Abc_TtCountOnesVec( Masks[c], p->nPatWords[c] );
        Counts[c][1] = Abc_TtCountOnesVecMask( pPats, Masks[c], p->nPatWords[c], 0 );
        Counts[c][0] = Num - Counts[c][1];
        assert( Counts[c][0] >= 0 && Counts[c][1] >= 0 );
    }
    //printf( "%5d %5d   %5d %5d \n", Counts[0][0], Counts[0][1], Counts[1][0], Counts[1][1] );
}
int Sfm_DecFindBestVar2( Sfm_Dec_t * p, word Masks[2][SFM_SIM_WORDS] )
{
    int Counts[2][2];
    int d, VarBest = -1, CostBest = ABC_INFINITY, Cost;
    for ( d = 0; d < p->nDivs; d++ )
    {
        Sfm_DecVarCost( p, Masks, d, Counts );
        if ( (Counts[0][0] < Counts[0][1]) == (Counts[1][0] < Counts[1][1]) )
            continue;
        Cost = Abc_MinInt(Counts[0][0], Counts[0][1]) + Abc_MinInt(Counts[1][0], Counts[1][1]);
        if ( CostBest > Cost )
        {
            CostBest = Cost;
            VarBest = d;
        }
    }
    return VarBest;
}
int Sfm_DecFindBestVar( Sfm_Dec_t * p, word Masks[2][SFM_SIM_WORDS] )
{
    int c, i, iLit, Var = -1, Cost, CostMin = ABC_INFINITY;
    for ( c = 0; c < 2; c++ )
    {
        Vec_IntForEachEntry( &p->vImpls[c], iLit, i )
        {
            if ( Vec_IntSize(&p->vImpls[c]) > 1 && Vec_IntFind(&p->vObjDec, Abc_Lit2Var(iLit)) >= 0 )
                continue;
            Cost = Sfm_DecFindCost( p, c, iLit, Masks[!c] );
            if ( CostMin > Cost )
            {
                CostMin = Cost;
                Var = Abc_Lit2Var(iLit);
            }
        }
    }
    return Var;
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
681 682 683 684 685
int Sfm_DecMffcArea( Abc_Ntk_t * pNtk, Vec_Int_t * vMffc )
{
    Abc_Obj_t * pObj; 
    int i, nAreaMffc = 0;
    Abc_NtkForEachObjVec( vMffc, pNtk, pObj, i )
686
        nAreaMffc += Scl_Flt2Int(Mio_GateReadArea((Mio_Gate_t *)pObj->pData));
687 688 689 690 691
    return nAreaMffc;
}
int Sfm_MffcDeref_rec( Abc_Obj_t * pObj )
{
    Abc_Obj_t * pFanin;
692
    int i, Area = Scl_Flt2Int(Mio_GateReadArea((Mio_Gate_t *)pObj->pData));
693 694 695 696 697 698 699 700
    Abc_ObjForEachFanin( pObj, pFanin, i )
    {
        assert( pFanin->vFanouts.nSize > 0 );
        if ( --pFanin->vFanouts.nSize == 0 && !Abc_ObjIsCi(pFanin) )
            Area += Sfm_MffcDeref_rec( pFanin );
    }
    return Area;
}
701
int Sfm_MffcRef_rec( Abc_Obj_t * pObj, Vec_Int_t * vMffc )
702 703
{
    Abc_Obj_t * pFanin;
704
    int i, Area = Scl_Flt2Int(Mio_GateReadArea((Mio_Gate_t *)pObj->pData));
705 706 707
    Abc_ObjForEachFanin( pObj, pFanin, i )
    {
        if ( pFanin->vFanouts.nSize++ == 0 && !Abc_ObjIsCi(pFanin) )
708
            Area += Sfm_MffcRef_rec( pFanin, vMffc );
709
    }
710 711
    if ( vMffc )
        Vec_IntPush( vMffc, Abc_ObjId(pObj) );
712 713
    return Area;
}
714
int Sfm_DecMffcAreaReal( Abc_Obj_t * pPivot, Vec_Int_t * vCut, Vec_Int_t * vMffc )
715 716 717 718 719
{
    Abc_Ntk_t * pNtk = pPivot->pNtk;
    Abc_Obj_t * pObj; 
    int i, Area1, Area2;
    assert( Abc_ObjIsNode(pPivot) );
720 721
    if ( vMffc )
        Vec_IntClear( vMffc );
722 723 724
    Abc_NtkForEachObjVec( vCut, pNtk, pObj, i )
        pObj->vFanouts.nSize++;
    Area1 = Sfm_MffcDeref_rec( pPivot );
725
    Area2 = Sfm_MffcRef_rec( pPivot, vMffc );
726 727 728 729 730 731 732 733 734 735 736 737
    Abc_NtkForEachObjVec( vCut, pNtk, pObj, i )
        pObj->vFanouts.nSize--;
    assert( Area1 == Area2 );
    return Area1;
}
void Sfm_DecPrepareVec( Vec_Int_t * vMap, int * pNodes, int nNodes, Vec_Int_t * vCut )
{
    int i;
    Vec_IntClear( vCut );
    for ( i = 0; i < nNodes; i++ )
        Vec_IntPush( vCut, Vec_IntEntry(vMap, pNodes[i]) );    
}
738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
int Sfm_DecComputeFlipInvGain( Sfm_Dec_t * p, Abc_Obj_t * pPivot, int * pfNeedInv )
{
    Abc_Obj_t * pFanout; 
    Mio_Gate_t * pGate, * pGateNew;
    int i, Handle, fNeedInv = 0, Gain = 0;
    Abc_ObjForEachFanout( pPivot, pFanout, i )
    {
        if ( !Abc_ObjIsNode(pFanout) )
        {
            fNeedInv = 1;
            continue;
        }
        pGate = (Mio_Gate_t*)pFanout->pData;
        if ( Abc_ObjFaninNum(pFanout) == 1 && Mio_GateIsInv(pGate) )
        {
            Gain += p->AreaInv;
            continue;
        }
        Handle = Sfm_LibFindComplInputGate( &p->vGateFuncs, Mio_GateReadValue(pGate), Abc_ObjFaninNum(pFanout), Abc_NodeFindFanin(pFanout, pPivot), NULL );
        if ( Handle == -1 )
        {
            fNeedInv = 1;
            continue;
        }
        pGateNew = (Mio_Gate_t *)Vec_PtrEntry( &p->vGateHands, Handle );
763
        Gain += Scl_Flt2Int(Mio_GateReadArea(pGate)) - Scl_Flt2Int(Mio_GateReadArea(pGateNew));
764 765 766 767 768 769 770
    }
    if ( fNeedInv )
        Gain -= p->AreaInv;
    if ( pfNeedInv )
        *pfNeedInv = fNeedInv;
    return Gain;
}
771 772 773 774 775 776 777 778 779 780 781 782

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
783 784 785 786 787 788 789 790 791 792 793 794
int Sfm_DecCombineDec( Sfm_Dec_t * p, word * pTruth0, word * pTruth1, int * pSupp0, int * pSupp1, int nSupp0, int nSupp1, word * pTruth, int * pSupp, int Var )
{
    Vec_Int_t vVec0 = { 2*SFM_SUPP_MAX, nSupp0, pSupp0 };
    Vec_Int_t vVec1 = { 2*SFM_SUPP_MAX, nSupp1, pSupp1 };
    Vec_Int_t vVec  = { 2*SFM_SUPP_MAX, 0,      pSupp  };
    int nWords0 = Abc_TtWordNum(nSupp0);
    int nSupp, iSuppVar;
    // check the case of equal cofactors
    if ( nSupp0 == nSupp1 && !memcmp(pSupp0, pSupp1, sizeof(int)*nSupp0) && !memcmp(pTruth0, pTruth1, sizeof(word)*nWords0) )
    {
        memcpy( pSupp,  pSupp0,  sizeof(int)*nSupp0   );
        memcpy( pTruth, pTruth0, sizeof(word)*nWords0 );
795
        Abc_TtStretch6( pTruth, nSupp0, p->pPars->nVarMax );
796 797 798 799 800 801
        return nSupp0;
    }
    // merge support variables
    Vec_IntTwoMerge2Int( &vVec0, &vVec1, &vVec );
    Vec_IntPushOrder( &vVec, Var );
    nSupp = Vec_IntSize( &vVec );
802
    if ( nSupp > p->pPars->nVarMax )
803 804 805 806 807 808 809 810 811
        return -2;
    // expand truth tables
    Abc_TtStretch6( pTruth0, nSupp0, nSupp );
    Abc_TtStretch6( pTruth1, nSupp1, nSupp );
    Abc_TtExpand( pTruth0, nSupp, pSupp0, nSupp0, pSupp, nSupp );
    Abc_TtExpand( pTruth1, nSupp, pSupp1, nSupp1, pSupp, nSupp );
    // perform operation
    iSuppVar = Vec_IntFind( &vVec, Var );
    Abc_TtMux( pTruth, p->pTtElems[iSuppVar], pTruth1, pTruth0, Abc_TtWordNum(nSupp) );
812
    Abc_TtStretch6( pTruth, nSupp, p->pPars->nVarMax );
813 814
    return nSupp;
}
815
int Sfm_DecPeformDec_rec( Sfm_Dec_t * p, word * pTruth, int * pSupp, int * pAssump, int nAssump, word Masks[2][SFM_SIM_WORDS], int fCofactor, int nSuppAdd )
816
{
817
    int nBTLimit = p->pPars->nBTLimit;
818
//    int fVerbose = p->pPars->fVeryVerbose;
819 820
    int c, i, d, iLit, status, Var = -1;
    word * pDivWords = p->pDivWords[nAssump];
821
    abctime clk;
822 823 824 825
    assert( nAssump <= SFM_SUPP_MAX );
    if ( p->pPars->fVeryVerbose )
    {
        printf( "\nObject %d\n", p->iTarget );
826
        printf( "Divs = %d.  Nodes = %d.  Mffc = %d.  Mffc area = %.2f.    ", p->nDivs, Vec_IntSize(&p->vObjGates), p->nMffc, Scl_Int2Flt(p->AreaMffc) );
827 828 829 830 831 832 833 834 835 836
        printf( "Pat0 = %d.  Pat1 = %d.    ", p->nPats[0], p->nPats[1] );
        printf( "\n" );
        if ( nAssump )
        {
            printf( "Cofactor: " );
            for ( i = 0; i < nAssump; i++ )
                printf( " %s%d", Abc_LitIsCompl(pAssump[i])? "!":"", Abc_Lit2Var(pAssump[i]) );
            printf( "\n" );
        }
    }
837 838 839
    // check constant
    for ( c = 0; c < 2; c++ )
    {
840
        if ( !Abc_TtIsConst0(Masks[c], p->nPatWords[c]) ) // there are some patterns
841 842 843
            continue;
        p->nSatCalls++;
        pAssump[nAssump] = Abc_Var2Lit( p->iTarget, c );
844
        clk = Abc_Clock();
845 846
        status = sat_solver_solve( p->pSat, pAssump, pAssump + nAssump + 1, nBTLimit, 0, 0, 0 );
        if ( status == l_Undef )
847 848
        {
            p->nTimeOuts++;
849
            return -2;
850
        }
851 852
        if ( status == l_False )
        {
853 854
            p->nSatCallsUnsat++;
            p->timeSatUnsat += Abc_Clock() - clk;
855
            Abc_TtConst( pTruth, Abc_TtWordNum(p->pPars->nVarMax), c );
856 857
            if ( p->pPars->fVeryVerbose )
                printf( "Found constant %d.\n", c );
858 859 860
            return 0;
        }
        assert( status == l_True );
861 862
        p->nSatCallsSat++;
        p->timeSatSat += Abc_Clock() - clk;
863
        if ( p->nPats[c] == 64*SFM_SIM_WORDS )
864 865 866 867
        {
            p->nSatCallsOver++;
            continue;//return -2;//continue;
        }
868
        for ( i = 0; i < p->nDivs; i++ )
869
            if ( sat_solver_var_value(p->pSat, i) )
870 871 872
                Abc_TtSetBit( Sfm_DecDivPats(p, i, c), p->nPats[c] );
        p->nPatWords[c] = 1 + (p->nPats[c] >> 6);
        Abc_TtSetBit( Masks[c], p->nPats[c]++ );
873
    }
874 875 876 877 878 879 880 881

    if ( p->iUseThis != -1 )
    {
        Var = p->iUseThis;
        p->iUseThis = -1;
        goto cofactor;
    }

882 883 884 885 886 887 888 889
    // check implications
    Vec_IntClear( &p->vImpls[0] );
    Vec_IntClear( &p->vImpls[1] );
    for ( d = 0; d < p->nDivs; d++ )
    {
        int Impls[2] = {-1, -1};
        for ( c = 0; c < 2; c++ )
        {
890 891 892 893
            word * pPats = Sfm_DecDivPats( p, d, c );
            int fHas0s = Abc_TtIntersect( pPats, Masks[c], p->nPatWords[c], 1 );
            int fHas1s = Abc_TtIntersect( pPats, Masks[c], p->nPatWords[c], 0 );
            if ( fHas0s && fHas1s )
894 895
                continue;
            pAssump[nAssump]   = Abc_Var2Lit( p->iTarget, c );
896
            pAssump[nAssump+1] = Abc_Var2Lit( d, fHas1s ); // if there are 1s, check if 0 is SAT
897
            clk = Abc_Clock();
898 899 900 901 902 903 904 905 906 907
            if ( Abc_TtGetBit( pDivWords, 4*d+2*c+fHas1s ) )
            {
                p->nSatCallsUnsat--;
                status = l_False;
            }
            else
            {
                p->nSatCalls++;
                status = sat_solver_solve( p->pSat, pAssump, pAssump + nAssump + 2, nBTLimit, 0, 0, 0 );
            }
908
            if ( status == l_Undef )
909 910
            {
                p->nTimeOuts++;
911
                return -2;
912
            }
913 914
            if ( status == l_False )
            {
915 916
                p->nSatCallsUnsat++;
                p->timeSatUnsat += Abc_Clock() - clk;
917 918
                Impls[c] = Abc_LitNot(pAssump[nAssump+1]);
                Vec_IntPush( &p->vImpls[c], Abc_LitNot(pAssump[nAssump+1]) );
919
                Abc_TtSetBit( pDivWords, 4*d+2*c+fHas1s );
920 921 922
                continue;
            }
            assert( status == l_True );
923 924
            p->nSatCallsSat++;
            p->timeSatSat += Abc_Clock() - clk;
925
            if ( p->nPats[c] == 64*SFM_SIM_WORDS )
926 927 928 929
            {
                p->nSatCallsOver++;
                continue;//return -2;//continue;
            }
930
            // record this status
931
            for ( i = 0; i < p->nDivs; i++ )
932
                if ( sat_solver_var_value(p->pSat, i) )
933 934 935
                    Abc_TtSetBit( Sfm_DecDivPats(p, i, c), p->nPats[c] );
            p->nPatWords[c] = 1 + (p->nPats[c] >> 6);
            Abc_TtSetBit( Masks[c], p->nPats[c]++ );
936
        }
937
        if ( Impls[0] == -1 || Impls[1] == -1 )
938
            continue;
939 940 941 942 943 944
        if ( Impls[0] == Impls[1] )
        {
            Vec_IntPop( &p->vImpls[0] );
            Vec_IntPop( &p->vImpls[1] );
            continue;
        }
945 946
        assert( Abc_Lit2Var(Impls[0]) == Abc_Lit2Var(Impls[1]) );
        // found buffer/inverter
947
        Abc_TtUnit( pTruth, Abc_TtWordNum(p->pPars->nVarMax), Abc_LitIsCompl(Impls[0]) );
948
        pSupp[0] = Abc_Lit2Var(Impls[0]);
949 950
        if ( p->pPars->fVeryVerbose )
            printf( "Found variable %s%d.\n", Abc_LitIsCompl(Impls[0]) ? "!":"", pSupp[0] );
951 952
        return 1;        
    }
953
    if ( nSuppAdd > p->pPars->nVarMax - 2 )
954 955 956 957 958
    {
        if ( p->pPars->fVeryVerbose )
            printf( "The number of assumption is more than MFFC size.\n" );
        return -2;
    }
959
    // try using all implications at once
960
    if ( p->pPars->fUseAndOr )
961 962 963 964 965 966 967 968 969
    for ( c = 0; c < 2; c++ )
    {
        if ( Vec_IntSize(&p->vImpls[!c]) < 2 )
            continue;
        p->nSatCalls++;
        pAssump[nAssump] = Abc_Var2Lit( p->iTarget, c );
        assert( Vec_IntSize(&p->vImpls[!c]) < SFM_WIN_MAX-10 );
        Vec_IntForEachEntry( &p->vImpls[!c], iLit, i )
            pAssump[nAssump+1+i] = iLit;
970
        clk = Abc_Clock();
971 972
        status = sat_solver_solve( p->pSat, pAssump, pAssump + nAssump+1+i, nBTLimit, 0, 0, 0 );
        if ( status == l_Undef )
973 974
        {
            p->nTimeOuts++;
975
            return -2;
976
        }
977 978 979
        if ( status == l_False )
        {
            int * pFinal, nFinal = sat_solver_final( p->pSat, &pFinal );
980 981
            p->nSatCallsUnsat++;
            p->timeSatUnsat += Abc_Clock() - clk;
982
            if ( nFinal + nSuppAdd > 6 )
983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008
                continue;
            // collect only relevant literals
            for ( i = d = 0; i < nFinal; i++ )
                if ( Vec_IntFind(&p->vImpls[!c], Abc_LitNot(pFinal[i])) >= 0 )
                    pSupp[d++] = Abc_LitNot(pFinal[i]);
            nFinal = d;
            // create AND/OR gate
            assert( nFinal <= 6 );
            if ( c )
            {
                *pTruth = ~(word)0;
                for ( i = 0; i < nFinal; i++ )
                {
                    *pTruth &= Abc_LitIsCompl(pSupp[i]) ? ~s_Truths6[i] : s_Truths6[i];
                    pSupp[i] = Abc_Lit2Var(pSupp[i]);
                }
            }
            else
            {
                *pTruth = 0;
                for ( i = 0; i < nFinal; i++ )
                {
                    *pTruth |= Abc_LitIsCompl(pSupp[i]) ? s_Truths6[i] : ~s_Truths6[i];
                    pSupp[i] = Abc_Lit2Var(pSupp[i]);
                }
            }
1009
            Abc_TtStretch6( pTruth, nFinal, p->pPars->nVarMax );
1010 1011 1012 1013 1014 1015
            p->nNodesAndOr++;
            if ( p->pPars->fVeryVerbose )
                printf( "Found %d-input AND/OR gate.\n", nFinal );
            return nFinal;
        }
        assert( status == l_True );
1016 1017
        p->nSatCallsSat++;
        p->timeSatSat += Abc_Clock() - clk;
1018
        if ( p->nPats[c] == 64*SFM_SIM_WORDS )
1019 1020 1021 1022
        {
            p->nSatCallsOver++;
            continue;//return -2;//continue;
        }
1023 1024
        for ( i = 0; i < p->nDivs; i++ )
            if ( sat_solver_var_value(p->pSat, i) )
1025 1026 1027
                Abc_TtSetBit( Sfm_DecDivPats(p, i, c), p->nPats[c] );
        p->nPatWords[c] = 1 + (p->nPats[c] >> 6);
        Abc_TtSetBit( Masks[c], p->nPats[c]++ );
1028
    }
1029

1030
    // find the best cofactoring variable
1031
//    if ( !fCofactor || Vec_IntSize(&p->vImpls[0]) + Vec_IntSize(&p->vImpls[1]) > 2 )
1032 1033 1034
    Var = Sfm_DecFindBestVar( p, Masks );
//    if ( Var == -1 )
//        Var = Sfm_DecFindBestVar2( p, Masks );
1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053

/*
    {
        int Lit0 = Vec_IntSize(&p->vImpls[0]) ? Vec_IntEntry(&p->vImpls[0], 0) : -1;
        int Lit1 = Vec_IntSize(&p->vImpls[1]) ? Vec_IntEntry(&p->vImpls[1], 0) : -1;
        if ( Lit0 == -1 && Lit1 >= 0 )
            Var = Abc_Lit2Var(Lit1);
        else if ( Lit1 == -1 && Lit0 >= 0 )
            Var = Abc_Lit2Var(Lit0);
        else if ( Lit0 >= 0 && Lit1 >= 0 )
        {
            if ( Lit0 < Lit1 )
                Var = Abc_Lit2Var(Lit0);
            else
                Var = Abc_Lit2Var(Lit1);
        }
    }
*/

1054 1055
    if ( Var == -1 && fCofactor )
    {
1056
        //for ( Var = p->nDivs - 1; Var >= 0; Var-- )
1057
        Vec_IntForEachEntryReverse( &p->vObjInMffc, Var, i )
1058 1059
            if ( Vec_IntFind(&p->vObjDec, Var) == -1 )
                break;
1060 1061
//        if ( i == Vec_IntSize(&p->vObjInMffc) )
        if ( i == -1 )
1062
            Var = -1;
1063 1064 1065
        fCofactor = 0;
    }

1066 1067 1068
    if ( p->pPars->fVeryVerbose )
    {
        Sfm_DecPrint( p, Masks );
1069
        printf( "Best var %d\n", Var );
1070 1071
        printf( "\n" );
    }
1072
cofactor:
1073 1074 1075
    // cofactor the problem
    if ( Var >= 0 )
    {
1076 1077
        word uTruth[2][SFM_WORD_MAX], MasksNext[2][SFM_SIM_WORDS];
        int w, Supp[2][2*SFM_SUPP_MAX], nSupp[2] = {0};
1078
        Vec_IntPush( &p->vObjDec, Var );
1079 1080 1081 1082
        for ( i = 0; i < 2; i++ )
        {
            for ( c = 0; c < 2; c++ )
            {
1083 1084 1085
                Abc_TtAndSharp( MasksNext[c], Masks[c], Sfm_DecDivPats(p, Var, c), p->nPatWords[c], !i );
                for ( w = p->nPatWords[c]; w < SFM_SIM_WORDS; w++ )
                    MasksNext[c][w] = 0;
1086 1087
            }
            pAssump[nAssump] = Abc_Var2Lit( Var, !i );
1088
            memcpy( p->pDivWords[nAssump+1], p->pDivWords[nAssump], sizeof(word) * p->nDivWords );
1089
            nSupp[i] = Sfm_DecPeformDec_rec( p, uTruth[i], Supp[i], pAssump, nAssump+1, MasksNext, fCofactor, (i ? nSupp[0] : 0) + nSuppAdd + 1 );
1090 1091 1092 1093
            if ( nSupp[i] == -2 )
                return -2;
        }
        // combine solutions
1094
        return Sfm_DecCombineDec( p, uTruth[0], uTruth[1], Supp[0], Supp[1], nSupp[0], nSupp[1], pTruth, pSupp, Var );
1095 1096 1097
    }
    return -2;
}
1098
int Sfm_DecPeformDec2( Sfm_Dec_t * p, Abc_Obj_t * pObj )
1099
{
1100
    word uTruth[SFM_DEC_MAX][SFM_WORD_MAX], Masks[2][SFM_SIM_WORDS];
1101 1102
    int pSupp[SFM_DEC_MAX][2*SFM_SUPP_MAX];
    int nSupp[SFM_DEC_MAX], pAssump[SFM_WIN_MAX];
1103
    int fVeryVerbose = p->pPars->fPrintDecs || p->pPars->fVeryVerbose;
1104
    int nDecs = Abc_MaxInt(p->pPars->nDecMax, 1);
1105
    //int fNeedInv, AreaGainInv = Sfm_DecComputeFlipInvGain(p, pObj, &fNeedInv);
1106
    int i, RetValue, Prev = 0, iBest = -1, AreaThis, AreaNew;//, AreaNewInv;
1107
    int GainThis, GainBest = -1, iLibObj, iLibObjBest = -1; 
1108
    assert( p->pPars->fArea == 1 );
1109
//printf( "AreaGainInv = %8.2f  ", Scl_Int2Flt(AreaGainInv) );
1110
    //Sfm_DecPrint( p, NULL );
1111 1112
    if ( fVeryVerbose )
        printf( "\nNode %4d : MFFC %2d\n", p->iTarget, p->nMffc );
1113
    assert( p->pPars->nDecMax <= SFM_DEC_MAX );
1114
    Sfm_ObjSetupSimInfo( pObj );
1115
    Vec_IntClear( &p->vObjDec );
1116
    for ( i = 0; i < nDecs; i++ )
1117
    {
1118 1119 1120 1121 1122
        // reduce the variable array
        if ( Vec_IntSize(&p->vObjDec) > Prev )
            Vec_IntShrink( &p->vObjDec, Prev );
        Prev = Vec_IntSize(&p->vObjDec) + 1;
        // perform decomposition 
1123 1124
        Abc_TtMask( Masks[0], SFM_SIM_WORDS, p->nPats[0] );
        Abc_TtMask( Masks[1], SFM_SIM_WORDS, p->nPats[1] );        
1125
        nSupp[i] = Sfm_DecPeformDec_rec( p, uTruth[i], pSupp[i], pAssump, 0, Masks, 1, 0 );
1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
        if ( nSupp[i] == -2 )
        {
            if ( fVeryVerbose )
                printf( "Dec  %d: Pat0 = %2d  Pat1 = %2d  NO DEC.\n", i, p->nPats[0], p->nPats[1] );
            continue;
        }
        if ( fVeryVerbose )
            printf( "Dec  %d: Pat0 = %2d  Pat1 = %2d  Supp = %d  ", i, p->nPats[0], p->nPats[1], nSupp[i] );
        if ( fVeryVerbose )
            Dau_DsdPrintFromTruth( uTruth[i], nSupp[i] );
1136 1137
        if ( nSupp[i] < 2 )
        {
1138 1139
            p->nSuppVars = nSupp[i];
            Abc_TtCopy( p->Copy, uTruth[i], SFM_WORD_MAX, 0 ); 
1140 1141 1142 1143 1144
            RetValue = Sfm_LibImplementSimple( p->pLib, uTruth[i], pSupp[i], nSupp[i], &p->vObjGates, &p->vObjFanins );
            assert( nSupp[i] <= p->pPars->nVarMax );
            p->nLuckySizes[nSupp[i]]++;
            assert( RetValue <= 2 );
            p->nLuckyGates[RetValue]++;
1145
            //printf( "\n" );
1146 1147
            return RetValue;
        }
1148

1149 1150
        p->nSuppVars = nSupp[i];
        Abc_TtCopy( p->Copy, uTruth[i], SFM_WORD_MAX, 0 ); 
1151
        AreaNew = Sfm_LibFindAreaMatch( p->pLib, uTruth[i], nSupp[i], &iLibObj );
1152 1153 1154 1155 1156 1157 1158
/*
        uTruth[i][0] = ~uTruth[i][0];
        AreaNewInv = Sfm_LibFindAreaMatch( p->pLib, uTruth[i], nSupp[i], NULL );
        uTruth[i][0] = ~uTruth[i][0];

        if ( AreaNew > 0 && AreaNewInv > 0 && AreaNew - AreaNewInv + AreaGainInv > 0 )
            printf( "AreaNew = %8.2f   AreaNewInv = %8.2f   Gain = %8.2f   Total = %8.2f\n", 
1159
                Scl_Int2Flt(AreaNew), Scl_Int2Flt(AreaNewInv), Scl_Int2Flt(AreaNew - AreaNewInv), Scl_Int2Flt(AreaNew - AreaNewInv + AreaGainInv) );
1160 1161 1162
        else
            printf( "\n" );
*/
1163 1164
        if ( AreaNew == -1 )
            continue;
1165 1166


1167
        // compute area savings
1168 1169
        Sfm_DecPrepareVec( &p->vObjMap, pSupp[i], nSupp[i], &p->vGateCut );
        AreaThis = Sfm_DecMffcAreaReal(pObj, &p->vGateCut, NULL);
1170 1171 1172 1173 1174 1175
        assert( p->AreaMffc <= AreaThis );
        if ( p->pPars->fZeroCost ? (AreaNew > AreaThis) : (AreaNew >= AreaThis) )
            continue;
        // find the best gain
        GainThis = AreaThis - AreaNew;
        assert( GainThis >= 0 );
1176
        if ( GainBest < GainThis )
1177 1178 1179 1180 1181
        {
            GainBest    = GainThis;
            iLibObjBest = iLibObj;
            iBest       = i;
        }
1182
    }
1183
    Sfm_ObjSetdownSimInfo( pObj );
1184 1185 1186 1187
    if ( iBest == -1 )
    {
        if ( fVeryVerbose )
            printf( "Best  : NO DEC.\n" );
1188
        p->nNoDecs++;
1189
        //printf( "\n" );
1190 1191
        return -2;
    }
1192
    if ( fVeryVerbose )
1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203
        printf( "Best %d: %d  ", iBest, nSupp[iBest] );
    if ( fVeryVerbose )
      Dau_DsdPrintFromTruth( uTruth[iBest], nSupp[iBest] );
    // implement
    assert( iLibObjBest >= 0 );
    RetValue = Sfm_LibImplementGatesArea( p->pLib, pSupp[iBest], nSupp[iBest], iLibObjBest, &p->vObjGates, &p->vObjFanins );
    assert( nSupp[iBest] <= p->pPars->nVarMax );
    p->nLuckySizes[nSupp[iBest]]++;
    assert( RetValue <= 2 );
    p->nLuckyGates[RetValue]++;
    return 1;
1204
}
1205 1206
int Sfm_DecPeformDec3( Sfm_Dec_t * p, Abc_Obj_t * pObj )
{
1207
    word uTruth[SFM_DEC_MAX][SFM_WORD_MAX], Masks[2][SFM_SIM_WORDS];
1208 1209 1210 1211
    int pSupp[SFM_DEC_MAX][2*SFM_SUPP_MAX];
    int nSupp[SFM_DEC_MAX], pAssump[SFM_WIN_MAX];
    int fVeryVerbose = p->pPars->fPrintDecs || p->pPars->fVeryVerbose;
    int nDecs = Abc_MaxInt(p->pPars->nDecMax, 1);
1212
    int i, k, DelayOrig = 0, DelayMin, GainMax, AreaMffc, nMatches, iBest = -1, RetValue, Prev = 0; 
1213 1214 1215
    Mio_Gate_t * pGate1Best = NULL, * pGate2Best = NULL; 
    char * pFans1Best = NULL, * pFans2Best = NULL;
    assert( p->pPars->fArea == 0 );
1216
    p->DelayMin = 0;
1217 1218 1219
    //Sfm_DecPrint( p, NULL );
    if ( fVeryVerbose )
        printf( "\nNode %4d : MFFC %2d\n", p->iTarget, p->nMffc );
1220
    // set limit on search for decompositions in delay-model
1221
    assert( p->pPars->nDecMax <= SFM_DEC_MAX );
1222
    Sfm_ObjSetupSimInfo( pObj );
1223
    Vec_IntClear( &p->vObjDec );
1224 1225
    for ( i = 0; i < nDecs; i++ )
    {
1226
        GainMax = 0;
1227
        DelayMin = DelayOrig = Sfm_ManReadObjDelay( p, Abc_ObjId(pObj) );
1228 1229 1230 1231 1232
        // reduce the variable array
        if ( Vec_IntSize(&p->vObjDec) > Prev )
            Vec_IntShrink( &p->vObjDec, Prev );
        Prev = Vec_IntSize(&p->vObjDec) + 1;
        // perform decomposition 
1233 1234
        Abc_TtMask( Masks[0], SFM_SIM_WORDS, p->nPats[0] );
        Abc_TtMask( Masks[1], SFM_SIM_WORDS, p->nPats[1] );        
1235
        nSupp[i] = Sfm_DecPeformDec_rec( p, uTruth[i], pSupp[i], pAssump, 0, Masks, 1, 0 );
1236 1237 1238 1239 1240 1241 1242 1243 1244 1245
        if ( nSupp[i] == -2 )
        {
            if ( fVeryVerbose )
                printf( "Dec  %d: Pat0 = %2d  Pat1 = %2d  NO DEC.\n", i, p->nPats[0], p->nPats[1] );
            continue;
        }
        if ( fVeryVerbose )
            printf( "Dec  %d: Pat0 = %2d  Pat1 = %2d  Supp = %d  ", i, p->nPats[0], p->nPats[1], nSupp[i] );
        if ( fVeryVerbose )
            Dau_DsdPrintFromTruth( uTruth[i], nSupp[i] );
1246 1247 1248 1249 1250 1251 1252
        if ( p->pTim && nSupp[i] == 1 && uTruth[i][0] == ABC_CONST(0x5555555555555555) && DelayMin <= p->DelayInv + Sfm_ManReadObjDelay(p, Vec_IntEntry(&p->vObjMap, pSupp[i][0])) )
        {
            if ( fVeryVerbose )
                printf( "Dec  %d: Pat0 = %2d  Pat1 = %2d  NO DEC.\n", i, p->nPats[0], p->nPats[1] );
            continue;
        }
        if ( p->pMit && nSupp[i] == 1 && uTruth[i][0] == ABC_CONST(0x5555555555555555) )
1253 1254 1255 1256 1257
        {
            if ( fVeryVerbose )
                printf( "Dec  %d: Pat0 = %2d  Pat1 = %2d  NO DEC.\n", i, p->nPats[0], p->nPats[1] );
            continue;
        }
1258
        if ( nSupp[i] < 2 )
1259
        {
1260 1261
            p->nSuppVars = nSupp[i];
            Abc_TtCopy( p->Copy, uTruth[i], SFM_WORD_MAX, 0 ); 
1262 1263 1264
            RetValue = Sfm_LibImplementSimple( p->pLib, uTruth[i], pSupp[i], nSupp[i], &p->vObjGates, &p->vObjFanins );
            assert( nSupp[i] <= p->pPars->nVarMax );
            p->nLuckySizes[nSupp[i]]++;
1265
            assert( RetValue <= 2 );
1266
            p->nLuckyGates[RetValue]++;
1267 1268
            return RetValue;
        }
1269

1270
        // get MFFC
1271 1272
        Sfm_DecPrepareVec( &p->vObjMap, pSupp[i], nSupp[i], &p->vGateCut ); // returns cut in p->vGateCut
        AreaMffc = Sfm_DecMffcAreaReal(pObj, &p->vGateCut, &p->vGateMffc ); // returns MFFC in p->vGateMffc
1273

1274
        // try the delay
1275 1276
        p->nSuppVars = nSupp[i];
        Abc_TtCopy( p->Copy, uTruth[i], SFM_WORD_MAX, 0 ); 
1277
        nMatches = Sfm_LibFindDelayMatches( p->pLib, uTruth[i], pSupp[i], nSupp[i], &p->vMatchGates, &p->vMatchFans );
1278 1279
        for ( k = 0; k < nMatches; k++ )
        {
1280
            abctime clk = Abc_Clock();
1281 1282
            Mio_Gate_t * pGate1 = (Mio_Gate_t *)Vec_PtrEntry( &p->vMatchGates, 2*k+0 );
            Mio_Gate_t * pGate2 = (Mio_Gate_t *)Vec_PtrEntry( &p->vMatchGates, 2*k+1 );
1283
            int AreaNew = Scl_Flt2Int( Mio_GateReadArea(pGate1) + (pGate2 ? Mio_GateReadArea(pGate2) : 0.0) );
1284 1285 1286
            char * pFans1 = (char *)Vec_PtrEntry( &p->vMatchFans, 2*k+0 );
            char * pFans2 = (char *)Vec_PtrEntry( &p->vMatchFans, 2*k+1 );
            Vec_Int_t vFanins = { nSupp[i], nSupp[i], pSupp[i] };
1287 1288 1289
            // skip identical gate
            //if ( pGate2 == NULL && pGate1 == (Mio_Gate_t *)pObj->pData )
            //    continue;
1290
            if ( p->pMit )
1291
            {
1292 1293 1294
                int Gain = Sfm_MitEvalRemapping( p->pMit, &p->vGateMffc, pObj, &vFanins, &p->vObjMap, pGate1, pFans1, pGate2, pFans2 );
                if ( p->pPars->DelAreaRatio && AreaNew > AreaMffc && (Gain / (AreaNew - AreaMffc)) < p->pPars->DelAreaRatio )
                    continue;
1295
                if ( GainMax < Gain )
1296
                {
1297
                    GainMax    = Gain;
1298 1299 1300 1301 1302 1303 1304
                    pGate1Best = pGate1;
                    pGate2Best = pGate2;
                    pFans1Best = pFans1;
                    pFans2Best = pFans2;
                    iBest      = i;
                }
            }
1305
            else
1306
            {
1307
                int Delay = Sfm_TimEvalRemapping( p->pTim, &vFanins, &p->vObjMap, pGate1, pFans1, pGate2, pFans2 );
1308 1309
                if ( p->pPars->DelAreaRatio && AreaNew > AreaMffc && (Delay / (AreaNew - AreaMffc)) < p->pPars->DelAreaRatio )
                    continue;
1310 1311 1312 1313 1314 1315 1316 1317 1318
                if ( DelayMin > Delay )
                {
                    DelayMin   = Delay;
                    pGate1Best = pGate1;
                    pGate2Best = pGate2;
                    pFans1Best = pFans1;
                    pFans2Best = pFans2;
                    iBest      = i;
                }
1319
            }
1320
            p->timeEval += Abc_Clock() - clk;
1321 1322
        }
    }
1323
//printf( "Gain max = %d.\n", GainMax );
1324
    Sfm_ObjSetdownSimInfo( pObj );
1325 1326 1327 1328 1329 1330 1331 1332
    if ( iBest == -1 )
    {
        if ( fVeryVerbose )
            printf( "Best  : NO DEC.\n" );
        p->nNoDecs++;
        return -2;
    }
    if ( fVeryVerbose )
1333 1334 1335
        printf( "Best %d: %d  ", iBest, nSupp[iBest] );
//    if ( fVeryVerbose )
//        Dau_DsdPrintFromTruth( uTruth[iBest], nSupp[iBest] );
1336
    RetValue = Sfm_LibImplementGatesDelay( p->pLib, pSupp[iBest], pGate1Best, pGate2Best, pFans1Best, pFans2Best, &p->vObjGates, &p->vObjFanins );
1337
    assert( nSupp[iBest] <= p->pPars->nVarMax );
1338
    p->nLuckySizes[nSupp[iBest]]++;
1339
    assert( RetValue <= 2 );
1340 1341
    p->nLuckyGates[RetValue]++;
    p->DelayMin = DelayMin;
1342 1343
    return 1;
}
1344 1345 1346

/**Function*************************************************************

1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359
  Synopsis    [Incremental level update.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Abc_NtkUpdateIncLevel_rec( Abc_Obj_t * pObj )
{
    Abc_Obj_t * pFanout;
    int i, LevelNew = Abc_ObjLevelNew(pObj);
1360
    if ( LevelNew == Abc_ObjLevel(pObj) && Abc_ObjIsNode(pObj) && Abc_ObjFaninNum(pObj) > 0 )
1361 1362
        return;
    pObj->Level = LevelNew;
1363
    if ( !Abc_ObjIsCo(pObj) )
1364 1365
        Abc_ObjForEachFanout( pObj, pFanout, i )
            Abc_NtkUpdateIncLevel_rec( pFanout );
1366 1367 1368 1369
}

/**Function*************************************************************

1370
  Synopsis    []
1371 1372 1373 1374 1375 1376 1377 1378

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
int Abc_NtkDfsCheck_rec( Abc_Obj_t * pObj, Abc_Obj_t * pPivot )
{
    Abc_Obj_t * pFanin; int i;
    if ( pObj == pPivot )
        return 0;
    if ( Abc_NodeIsTravIdCurrent( pObj ) )
        return 1;
    Abc_NodeSetTravIdCurrent( pObj );
    if ( Abc_ObjIsCi(pObj) )
        return 1;
    assert( Abc_ObjIsNode(pObj) );
    Abc_ObjForEachFanin( pObj, pFanin, i )
        if ( !Abc_NtkDfsCheck_rec(pFanin, pPivot) )
            return 0;
    return 1;
}
1395
void Abc_NtkDfsReverseOne_rec( Abc_Obj_t * pObj, Vec_Int_t * vTfo, int nLevelMax, int nFanoutMax )
1396 1397
{
    Abc_Obj_t * pFanout; int i;
1398
    if ( Abc_NodeIsTravIdCurrent( pObj ) )
1399
        return;
1400 1401
    Abc_NodeSetTravIdCurrent( pObj );
    if ( Abc_ObjIsCo(pObj) || Abc_ObjLevel(pObj) > nLevelMax )
1402
        return;
1403 1404 1405 1406
    assert( Abc_ObjIsNode( pObj ) );
    if ( Abc_ObjFanoutNum(pObj) <= nFanoutMax )
    {
        Abc_ObjForEachFanout( pObj, pFanout, i )
1407
            if ( Abc_ObjIsCo(pFanout) || Abc_ObjLevel(pFanout) > nLevelMax )
1408 1409 1410 1411
                break;
        if ( i == Abc_ObjFanoutNum(pObj) )
            Abc_ObjForEachFanout( pObj, pFanout, i )
                Abc_NtkDfsReverseOne_rec( pFanout, vTfo, nLevelMax, nFanoutMax );
1412
    }
1413 1414
    Vec_IntPush( vTfo, Abc_ObjId(pObj) );
    pObj->iTemp = 0;
1415
}
1416
int Abc_NtkDfsOne_rec( Abc_Obj_t * pObj, Vec_Int_t * vTfi, int nLevelMin, int CiLabel )
1417
{
1418
    Abc_Obj_t * pFanin; int i;
1419 1420 1421
    if ( Abc_NodeIsTravIdCurrent( pObj ) )
        return pObj->iTemp;
    Abc_NodeSetTravIdCurrent( pObj );
1422
    if ( Abc_ObjIsCi(pObj) || (Abc_ObjLevel(pObj) < nLevelMin && Abc_ObjFaninNum(pObj) > 0) )
1423
    {
1424 1425
        Vec_IntPush( vTfi, Abc_ObjId(pObj) );
        return (pObj->iTemp = CiLabel);
1426
    }
1427
    assert( Abc_ObjIsNode(pObj) );
1428
    pObj->iTemp = Abc_ObjFaninNum(pObj) ? 0 : CiLabel;
1429
    Abc_ObjForEachFanin( pObj, pFanin, i )
1430
        pObj->iTemp |= Abc_NtkDfsOne_rec( pFanin, vTfi, nLevelMin, CiLabel );
1431
    Vec_IntPush( vTfi, Abc_ObjId(pObj) );
1432 1433
    Sfm_ObjSimulateNode( pObj );
    return pObj->iTemp;
1434 1435 1436 1437 1438 1439 1440 1441 1442
}
void Sfm_DecAddNode( Abc_Obj_t * pObj, Vec_Int_t * vMap, Vec_Int_t * vGates, int fSkip, int fVeryVerbose )
{
    if ( fVeryVerbose )
        printf( "%d:%d(%d) ", Vec_IntSize(vMap), Abc_ObjId(pObj), pObj->iTemp );
    if ( fVeryVerbose )
        Abc_ObjPrint( stdout, pObj );
    Vec_IntPush( vMap, Abc_ObjId(pObj) );
    Vec_IntPush( vGates, fSkip ? -1 : Mio_GateReadValue((Mio_Gate_t *)pObj->pData) );
1443
}
1444
static inline int Sfm_DecNodeIsMffc( Abc_Obj_t * p, int nLevelMin )
1445
{
1446 1447
    return Abc_ObjIsNode(p) && Abc_ObjFanoutNum(p) == 1 && Abc_NodeIsTravIdCurrent(p) && (Abc_ObjLevel(p) >= nLevelMin || Abc_ObjFaninNum(p) == 0);
}
1448 1449
static inline int Sfm_DecNodeIsMffcInput( Abc_Obj_t * p, int nLevelMin, Sfm_Tim_t * pTim, Abc_Obj_t * pPivot )
{
1450
    return Abc_NodeIsTravIdCurrent(p) && Sfm_TimNodeIsNonCritical(pTim, pPivot, p);
1451
}
1452 1453 1454 1455 1456
static inline int Sfm_DecNodeIsMffcInput2( Abc_Obj_t * p, int nLevelMin, Sfm_Mit_t * pMit, Abc_Obj_t * pPivot )
{
    return Abc_NodeIsTravIdCurrent(p) && Sfm_MitNodeIsNonCritical(pMit, pPivot, p);
}
void Sfm_DecMarkMffc( Abc_Obj_t * pPivot, int nLevelMin, int nMffcMax, int fVeryVerbose, Vec_Int_t * vMffc, Vec_Int_t * vInMffc, Sfm_Tim_t * pTim, Sfm_Mit_t * pMit )
1457 1458 1459 1460
{
    Abc_Obj_t * pFanin, * pFanin2, * pFanin3, * pObj; int i, k, n;
    assert( nMffcMax > 0 );
    Vec_IntFill( vMffc, 1, Abc_ObjId(pPivot) );
1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480
    if ( pMit != NULL )
    {
        pPivot->iTemp |= SFM_MASK_MFFC;
        pPivot->iTemp |= SFM_MASK_PIVOT;
        // collect MFFC inputs (these are low-delay nodes close to the pivot)
        Vec_IntClear(vInMffc);
        Abc_ObjForEachFanin( pPivot, pFanin, i )
            if ( Sfm_DecNodeIsMffcInput2(pFanin, nLevelMin, pMit, pPivot) )
                Vec_IntPushUnique( vInMffc, Abc_ObjId(pFanin) );
        Abc_ObjForEachFanin( pPivot, pFanin, i )
            Abc_ObjForEachFanin( pFanin, pFanin2, k )
                if ( Sfm_DecNodeIsMffcInput2(pFanin2, nLevelMin, pMit, pPivot) )
                    Vec_IntPushUnique( vInMffc, Abc_ObjId(pFanin2) );
        Abc_ObjForEachFanin( pPivot, pFanin, i )
            Abc_ObjForEachFanin( pFanin, pFanin2, k )
                Abc_ObjForEachFanin( pFanin2, pFanin3, n )
                    if ( Sfm_DecNodeIsMffcInput2(pFanin3, nLevelMin, pMit, pPivot) )
                        Vec_IntPushUnique( vInMffc, Abc_ObjId(pFanin3) );
    }
    else if ( pTim != NULL )
1481 1482 1483 1484 1485 1486 1487
    {
        pPivot->iTemp |= SFM_MASK_MFFC;
        pPivot->iTemp |= SFM_MASK_PIVOT;
        // collect MFFC inputs (these are low-delay nodes close to the pivot)
        Vec_IntClear(vInMffc);
        Abc_ObjForEachFanin( pPivot, pFanin, i )
            if ( Sfm_DecNodeIsMffcInput(pFanin, nLevelMin, pTim, pPivot) )
1488
                Vec_IntPushUnique( vInMffc, Abc_ObjId(pFanin) );
1489
        Abc_ObjForEachFanin( pPivot, pFanin, i )
1490 1491 1492
            Abc_ObjForEachFanin( pFanin, pFanin2, k )
                if ( Sfm_DecNodeIsMffcInput(pFanin2, nLevelMin, pTim, pPivot) )
                    Vec_IntPushUnique( vInMffc, Abc_ObjId(pFanin2) );
1493
        Abc_ObjForEachFanin( pPivot, pFanin, i )
1494 1495 1496 1497
            Abc_ObjForEachFanin( pFanin, pFanin2, k )
                Abc_ObjForEachFanin( pFanin2, pFanin3, n )
                    if ( Sfm_DecNodeIsMffcInput(pFanin3, nLevelMin, pTim, pPivot) )
                        Vec_IntPushUnique( vInMffc, Abc_ObjId(pFanin3) );
1498

1499
/*
1500
        printf( "Node %d: (%.2f)  ", pPivot->Id, Scl_Int2Flt(Sfm_ManReadObjDelay(p, Abc_ObjId(pPivot)))  );
1501
        Abc_ObjForEachFanin( pPivot, pFanin, i )
1502
            printf( "%d: %.2f  ", Abc_ObjLevel(pFanin), Scl_Int2Flt(Sfm_ManReadObjDelay(p, Abc_ObjId(pFanin))) );
1503 1504 1505 1506
        printf( "\n" );

        printf( "Node %d: ", pPivot->Id );
        Abc_NtkForEachObjVec( vInMffc, pPivot->pNtk, pObj, i )
1507
            printf( "%d: %.2f  ", Abc_ObjLevel(pObj), Scl_Int2Flt(Sfm_ManReadObjDelay(p, Abc_ObjId(pObj))) );
1508 1509
        printf( "\n" );
*/
1510 1511 1512
    }
    else
    {
1513

1514 1515 1516
        // collect MFFC
        Abc_ObjForEachFanin( pPivot, pFanin, i )
            if ( Sfm_DecNodeIsMffc(pFanin, nLevelMin) && Vec_IntSize(vMffc) < nMffcMax )
1517
                Vec_IntPushUnique( vMffc, Abc_ObjId(pFanin) );
1518 1519 1520 1521
        Abc_ObjForEachFanin( pPivot, pFanin, i )
            if ( Sfm_DecNodeIsMffc(pFanin, nLevelMin) && Vec_IntSize(vMffc) < nMffcMax )
                Abc_ObjForEachFanin( pFanin, pFanin2, k )
                    if ( Sfm_DecNodeIsMffc(pFanin2, nLevelMin) && Vec_IntSize(vMffc) < nMffcMax )
1522
                        Vec_IntPushUnique( vMffc, Abc_ObjId(pFanin2) );
1523 1524 1525 1526 1527 1528
        Abc_ObjForEachFanin( pPivot, pFanin, i )
            if ( Sfm_DecNodeIsMffc(pFanin, nLevelMin) && Vec_IntSize(vMffc) < nMffcMax )
                Abc_ObjForEachFanin( pFanin, pFanin2, k )
                    if ( Sfm_DecNodeIsMffc(pFanin2, nLevelMin) && Vec_IntSize(vMffc) < nMffcMax )
                        Abc_ObjForEachFanin( pFanin2, pFanin3, n )
                            if ( Sfm_DecNodeIsMffc(pFanin3, nLevelMin) && Vec_IntSize(vMffc) < nMffcMax )
1529
                                Vec_IntPushUnique( vMffc, Abc_ObjId(pFanin3) );
1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540
        // mark MFFC
        assert( Vec_IntSize(vMffc) <= nMffcMax );
        Abc_NtkForEachObjVec( vMffc, pPivot->pNtk, pObj, i )
            pObj->iTemp |= SFM_MASK_MFFC;
        pPivot->iTemp |= SFM_MASK_PIVOT;
        // collect MFFC inputs
        Vec_IntClear(vInMffc);
        Abc_NtkForEachObjVec( vMffc, pPivot->pNtk, pObj, i )
            Abc_ObjForEachFanin( pObj, pFanin, k )
                if ( Abc_NodeIsTravIdCurrent(pFanin) && pFanin->iTemp == SFM_MASK_PI )
                    Vec_IntPushUnique( vInMffc, Abc_ObjId(pFanin) );
1541 1542 1543 1544 1545 1546 1547 1548 1549 1550

//        printf( "Node %d: ", pPivot->Id );
//        Abc_ObjForEachFanin( pPivot, pFanin, i )
//            printf( "%d ", Abc_ObjFanoutNum(pFanin) );
//        printf( "\n" );

//        Abc_NtkForEachObjVec( vInMffc, pPivot->pNtk, pObj, i )
//            printf( "%d ", Abc_ObjFanoutNum(pObj) );
//        printf( "\n" );

1551
    }
1552
}
1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
1565
int Sfm_DecExtract( Abc_Ntk_t * pNtk, Sfm_Par_t * pPars, Abc_Obj_t * pPivot, Vec_Int_t * vRoots, Vec_Int_t * vGates, Vec_Wec_t * vFanins, Vec_Int_t * vMap, Vec_Int_t * vTfi, Vec_Int_t * vTfo, Vec_Int_t * vMffc, Vec_Int_t * vInMffc, Sfm_Tim_t * pTim, Sfm_Mit_t * pMit )
1566
{
1567
    int fVeryVerbose = 0;//pPars->fVeryVerbose;
1568
    Vec_Int_t * vLevel;
1569 1570 1571 1572 1573
    Abc_Obj_t * pObj, * pFanin;
    int nLevelMax = pPivot->Level + pPars->nTfoLevMax;
    int nLevelMin = pPivot->Level - pPars->nTfiLevMax;
    int i, k, nTfiSize, nDivs = -1;
    assert( Abc_ObjIsNode(pPivot) );
1574
if ( fVeryVerbose )
1575 1576
printf( "\n\nTarget %d\n", Abc_ObjId(pPivot) );
    // collect TFO nodes
1577
    Vec_IntClear( vTfo );
1578
    Abc_NtkIncrementTravId( pNtk );
1579 1580 1581 1582 1583
    Abc_NtkDfsReverseOne_rec( pPivot, vTfo, nLevelMax, pPars->nFanoutMax );
    // count internal fanouts
    Abc_NtkForEachObjVec( vTfo, pNtk, pObj, i )
        Abc_ObjForEachFanin( pObj, pFanin, k )
            pFanin->iTemp++;
1584
    // compute roots
1585 1586 1587 1588 1589 1590 1591
    Vec_IntClear( vRoots );
    Abc_NtkForEachObjVec( vTfo, pNtk, pObj, i )
        if ( pObj->iTemp != Abc_ObjFanoutNum(pObj) )
            Vec_IntPush( vRoots, Abc_ObjId(pObj) );
    assert( Vec_IntSize(vRoots) > 0 );
    // collect TFI and mark nodes
    Vec_IntClear( vTfi );
1592
    Abc_NtkIncrementTravId( pNtk );
1593 1594
    Abc_NtkDfsOne_rec( pPivot, vTfi, nLevelMin, SFM_MASK_PI );
    nTfiSize = Vec_IntSize(vTfi);
1595
    Sfm_ObjFlipNode( pPivot );
1596
    // additinally mark MFFC
1597
    Sfm_DecMarkMffc( pPivot, nLevelMin, pPars->nMffcMax, fVeryVerbose, vMffc, vInMffc, pTim, pMit );
1598
    assert( Vec_IntSize(vMffc) <= pPars->nMffcMax );
1599
if ( fVeryVerbose )
1600
printf( "Mffc size = %d. Mffc area = %.2f. InMffc size = %d.\n", Vec_IntSize(vMffc), Scl_Int2Flt(Sfm_DecMffcArea(pNtk, vMffc)), Vec_IntSize(vInMffc) );
1601
    // collect TFI(TFO)
1602
    Abc_NtkForEachObjVec( vRoots, pNtk, pObj, i )
1603 1604 1605 1606 1607 1608 1609 1610
        Abc_NtkDfsOne_rec( pObj, vTfi, nLevelMin, SFM_MASK_INPUT );
    // mark input-only nodes pointed to by mixed nodes
    Abc_NtkForEachObjVecStart( vTfi, pNtk, pObj, i, nTfiSize )
        if ( pObj->iTemp != SFM_MASK_INPUT )
            Abc_ObjForEachFanin( pObj, pFanin, k )
                if ( pFanin->iTemp == SFM_MASK_INPUT )
                    pFanin->iTemp = SFM_MASK_FANIN;
    // collect nodes supported only on TFI fanins and not MFFC
1611
if ( fVeryVerbose )
1612
printf( "\nDivs:\n" );
1613
    Vec_IntClear( vMap );
1614
    Vec_IntClear( vGates );
1615 1616
    Abc_NtkForEachObjVec( vTfi, pNtk, pObj, i )
        if ( pObj->iTemp == SFM_MASK_PI )
1617
            Sfm_DecAddNode( pObj, vMap, vGates, Abc_ObjIsCi(pObj) || (Abc_ObjLevel(pObj) < nLevelMin && Abc_ObjFaninNum(pObj) > 0), fVeryVerbose );
1618 1619
    nDivs = Vec_IntSize(vMap);
    // add other nodes that are not in TFO and not in MFFC
1620
if ( fVeryVerbose )
1621
printf( "\nSides:\n" );
1622
    Abc_NtkForEachObjVec( vTfi, pNtk, pObj, i )
1623
        if ( pObj->iTemp == (SFM_MASK_PI | SFM_MASK_INPUT) || pObj->iTemp == SFM_MASK_FANIN )
1624
            Sfm_DecAddNode( pObj, vMap, vGates, pObj->iTemp == SFM_MASK_FANIN, fVeryVerbose );
1625
    // reorder nodes acording to delay
1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641
    if ( pMit )
    {
        int nDivsNew, nOldSize = Vec_IntSize(vMap);
        Vec_IntClear( vTfo );
        Vec_IntAppend( vTfo, vMap );
        nDivsNew = Sfm_MitSortArrayByArrival( pMit, vTfo, Abc_ObjId(pPivot) );
        // collect again
        Vec_IntClear( vMap );
        Vec_IntClear( vGates );
        Abc_NtkForEachObjVec( vTfo, pNtk, pObj, i )
            Sfm_DecAddNode( pObj, vMap, vGates, Abc_ObjIsCi(pObj) || (Abc_ObjLevel(pObj) < nLevelMin && Abc_ObjFaninNum(pObj) > 0) || pObj->iTemp == SFM_MASK_FANIN, 0 );
        assert( nOldSize == Vec_IntSize(vMap) );
        // update divisor count
        nDivs = nDivsNew;
    }
    else if ( pTim )
1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655
    {
        int nDivsNew, nOldSize = Vec_IntSize(vMap);
        Vec_IntClear( vTfo );
        Vec_IntAppend( vTfo, vMap );
        nDivsNew = Sfm_TimSortArrayByArrival( pTim, vTfo, Abc_ObjId(pPivot) );
        // collect again
        Vec_IntClear( vMap );
        Vec_IntClear( vGates );
        Abc_NtkForEachObjVec( vTfo, pNtk, pObj, i )
            Sfm_DecAddNode( pObj, vMap, vGates, Abc_ObjIsCi(pObj) || (Abc_ObjLevel(pObj) < nLevelMin && Abc_ObjFaninNum(pObj) > 0) || pObj->iTemp == SFM_MASK_FANIN, 0 );
        assert( nOldSize == Vec_IntSize(vMap) );
        // update divisor count
        nDivs = nDivsNew;
    }
1656
    // add the TFO nodes
1657
if ( fVeryVerbose )
1658
printf( "\nTFO:\n" );
1659 1660
    Abc_NtkForEachObjVec( vTfi, pNtk, pObj, i )
        if ( pObj->iTemp >= SFM_MASK_MFFC )
1661
            Sfm_DecAddNode( pObj, vMap, vGates, 0, fVeryVerbose );
1662
    assert( Vec_IntSize(vMap) == Vec_IntSize(vGates) );
1663
if ( fVeryVerbose )
1664
printf( "\n" );
1665
    // create node IDs
1666
    Vec_WecClear( vFanins );
1667
    Abc_NtkForEachObjVec( vMap, pNtk, pObj, i )
1668
    {
1669
        pObj->iTemp = i;
1670
        vLevel = Vec_WecPushLevel( vFanins );
1671 1672 1673
        if ( Vec_IntEntry(vGates, i) >= 0 )
            Abc_ObjForEachFanin( pObj, pFanin, k )
                Vec_IntPush( vLevel, pFanin->iTemp );
1674
    }
1675 1676 1677 1678 1679 1680 1681
    // compute care set
    Sfm_DecMan(pPivot)->uCareSet = Sfm_ObjFindCareSet(pPivot->pNtk, vRoots);

    //printf( "care = %5d : ", Abc_ObjId(pPivot) );
    //Extra_PrintBinary( stdout, (unsigned *)&Sfm_DecMan(pPivot)->uCareSet, 64 );
    //printf( "\n" );

1682 1683 1684
    // remap roots
    Abc_NtkForEachObjVec( vRoots, pNtk, pObj, i )
        Vec_IntWriteEntry( vRoots, i, pObj->iTemp );
1685 1686 1687
    // remap inputs to MFFC
    Abc_NtkForEachObjVec( vInMffc, pNtk, pObj, i )
        Vec_IntWriteEntry( vInMffc, i, pObj->iTemp );
1688

1689 1690 1691 1692 1693 1694 1695 1696 1697
/*
    // check
    Abc_NtkForEachObjVec( vMap, pNtk, pObj, i )
    {
        if ( i == nDivs )
            break;
        Abc_NtkIncrementTravId( pNtk );
        assert( Abc_NtkDfsCheck_rec(pObj, pPivot) );
    }
1698
*/  
1699
    return nDivs;
1700
}
1701
Abc_Obj_t * Sfm_DecInsert( Abc_Ntk_t * pNtk, Abc_Obj_t * pPivot, int Limit, Vec_Int_t * vGates, Vec_Wec_t * vFanins, Vec_Int_t * vMap, Vec_Ptr_t * vGateHandles, int GateBuf, int GateInv, Vec_Wrd_t * vFuncs, Vec_Int_t * vNewNodes, Sfm_Mit_t * pMit )
1702 1703
{
    Abc_Obj_t * pObjNew = NULL; 
1704
    Vec_Int_t * vLevel;
1705
    int i, k, iObj, Gate;
1706 1707
    if ( vNewNodes )
        Vec_IntClear( vNewNodes );
1708
    // assuming that new gates are appended at the end
1709 1710
    assert( Limit < Vec_IntSize(vGates) );
    assert( Limit == Vec_IntSize(vMap) );
1711 1712 1713 1714 1715 1716 1717
    if ( Limit + 1 == Vec_IntSize(vGates) )
    {
        Gate = Vec_IntEntryLast(vGates);
        if ( Gate == GateBuf )
        {
            iObj = Vec_WecEntryEntry( vFanins, Limit, 0 );
            pObjNew = Abc_NtkObj( pNtk, Vec_IntEntry(vMap, iObj) );
1718 1719 1720 1721
            // transfer load
            if ( pMit )
                Sfm_MitTransferLoad( pMit, pObjNew, pPivot );
            // replace logic cone
1722 1723 1724 1725
            Abc_ObjReplace( pPivot, pObjNew );
            // update level
            pObjNew->Level = 0;
            Abc_NtkUpdateIncLevel_rec( pObjNew );
1726 1727
            if ( vNewNodes )
                Vec_IntPush( vNewNodes, Abc_ObjId(pObjNew) );
1728
            return pObjNew;
1729
        }
1730
        else if ( vNewNodes == NULL && Gate == GateInv )
1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750
        {
            // check if fanouts can be updated
            Abc_Obj_t * pFanout;
            Abc_ObjForEachFanout( pPivot, pFanout, i )
                if ( !Abc_ObjIsNode(pFanout) || Sfm_LibFindComplInputGate(vFuncs, Mio_GateReadValue((Mio_Gate_t*)pFanout->pData), Abc_ObjFaninNum(pFanout), Abc_NodeFindFanin(pFanout, pPivot), NULL) == -1 )
                    break;
            // update fanouts
            if ( i == Abc_ObjFanoutNum(pPivot) )
            {
                Abc_ObjForEachFanout( pPivot, pFanout, i )
                {
                    int iFanin = Abc_NodeFindFanin(pFanout, pPivot), iFaninNew = -1;
                    int iGate = Mio_GateReadValue((Mio_Gate_t*)pFanout->pData);
                    int iGateNew = Sfm_LibFindComplInputGate( vFuncs, iGate, Abc_ObjFaninNum(pFanout), iFanin, &iFaninNew );
                    assert( iGateNew >= 0 && iGateNew != iGate && iFaninNew >= 0 );
                    pFanout->pData = Vec_PtrEntry( vGateHandles, iGateNew );
                    //assert( iFanin == iFaninNew );
                    // swap fanins
                    if ( iFanin != iFaninNew )
                    {
1751
                        int * pArray = Vec_IntArray( &pFanout->vFanins );
1752 1753 1754 1755 1756 1757 1758 1759 1760
                        ABC_SWAP( int, pArray[iFanin], pArray[iFaninNew] );
                    }
                }
                iObj = Vec_WecEntryEntry( vFanins, Limit, 0 );
                pObjNew = Abc_NtkObj( pNtk, Vec_IntEntry(vMap, iObj) );
                Abc_ObjReplace( pPivot, pObjNew );
                // update level
                pObjNew->Level = 0;
                Abc_NtkUpdateIncLevel_rec( pObjNew );
1761
                return pObjNew;
1762 1763 1764
            }
        }
    }
1765
    // introduce new gates
1766 1767
    Vec_IntForEachEntryStart( vGates, Gate, i, Limit )
    {
1768
        vLevel = Vec_WecEntry( vFanins, i );
1769 1770 1771 1772
        pObjNew = Abc_NtkCreateNode( pNtk );
        Vec_IntForEachEntry( vLevel, iObj, k )
            Abc_ObjAddFanin( pObjNew, Abc_NtkObj(pNtk, Vec_IntEntry(vMap, iObj)) );
        pObjNew->pData = Vec_PtrEntry( vGateHandles, Gate );
1773
        assert( Abc_ObjFaninNum(pObjNew) == Mio_GateReadPinNum((Mio_Gate_t *)pObjNew->pData) );
1774
        Vec_IntPush( vMap, Abc_ObjId(pObjNew) );
1775 1776
        if ( vNewNodes )
            Vec_IntPush( vNewNodes, Abc_ObjId(pObjNew) );
1777
    }
1778 1779 1780 1781 1782 1783 1784
    // transfer load
    if ( pMit )
    {
        Sfm_MitTimingGrow( pMit );
        Sfm_MitTransferLoad( pMit, pObjNew, pPivot );
    }
    // replace logic cone
1785
    Abc_ObjReplace( pPivot, pObjNew );
1786 1787
    // update level
    Abc_NtkForEachObjVecStart( vMap, pNtk, pObjNew, i, Limit )
1788
        Abc_NtkUpdateIncLevel_rec( pObjNew );
1789
    return pObjNew;
1790 1791 1792
}
void Sfm_DecPrintStats( Sfm_Dec_t * p )
{
1793
    int i;
1794 1795
    printf( "Node = %d. Try = %d. Change = %d.   Const0 = %d. Const1 = %d. Buf = %d. Inv = %d. Gate = %d. AndOr = %d. Effort = %d.  NoDec = %d.\n",
        p->nTotalNodesBeg, p->nNodesTried, p->nNodesChanged, p->nNodesConst0, p->nNodesConst1, p->nNodesBuf, p->nNodesInv, p->nNodesResyn, p->nNodesAndOr, p->nEfforts, p->nNoDecs );
1796 1797
    printf( "MaxDiv = %d. MaxWin = %d.   AveDiv = %d. AveWin = %d.   Calls = %d. (Sat = %d. Unsat = %d.)  Over = %d.  T/O = %d.\n",
        p->nMaxDivs, p->nMaxWin, (int)(p->nAllDivs/Abc_MaxInt(1, p->nNodesTried)), (int)(p->nAllWin/Abc_MaxInt(1, p->nNodesTried)), p->nSatCalls, p->nSatCallsSat, p->nSatCallsUnsat, p->nSatCallsOver, p->nTimeOuts );
1798 1799

    p->timeTotal = Abc_Clock() - p->timeStart;
1800
    p->timeOther = p->timeTotal - p->timeLib - p->timeWin - p->timeCnf - p->timeSat - p->timeTime;
1801

1802 1803 1804 1805 1806 1807 1808 1809 1810 1811
    ABC_PRTP( "Lib   ", p->timeLib  ,           p->timeTotal );
    ABC_PRTP( "Win   ", p->timeWin  ,           p->timeTotal );
    ABC_PRTP( "Cnf   ", p->timeCnf  ,           p->timeTotal );
    ABC_PRTP( "Sat   ", p->timeSat-p->timeEval, p->timeTotal );
    ABC_PRTP( " Sat  ", p->timeSatSat,          p->timeTotal );
    ABC_PRTP( " Unsat", p->timeSatUnsat,        p->timeTotal );
    ABC_PRTP( "Eval  ", p->timeEval ,           p->timeTotal );
    ABC_PRTP( "Timing", p->timeTime ,           p->timeTotal );
    ABC_PRTP( "Other ", p->timeOther,           p->timeTotal );
    ABC_PRTP( "ALL   ", p->timeTotal,           p->timeTotal );
1812

1813
    printf( "Cone sizes:  " );
1814
    for ( i = 0; i <= SFM_SUPP_MAX; i++ )
1815 1816 1817 1818 1819
        if ( p->nLuckySizes[i] )
            printf( "%d=%d  ", i, p->nLuckySizes[i] );
    printf( "  " );

    printf( "Gate sizes:  " );
1820
    for ( i = 0; i <= SFM_SUPP_MAX; i++ )
1821 1822 1823 1824
        if ( p->nLuckyGates[i] )
            printf( "%d=%d  ", i, p->nLuckyGates[i] );
    printf( "\n" );

1825 1826 1827 1828
    printf( "Reduction:   " );
    printf( "Nodes  %6d out of %6d (%6.2f %%)   ", p->nTotalNodesBeg-p->nTotalNodesEnd, p->nTotalNodesBeg, 100.0*(p->nTotalNodesBeg-p->nTotalNodesEnd)/Abc_MaxInt(1, p->nTotalNodesBeg) );
    printf( "Edges  %6d out of %6d (%6.2f %%)   ", p->nTotalEdgesBeg-p->nTotalEdgesEnd, p->nTotalEdgesBeg, 100.0*(p->nTotalEdgesBeg-p->nTotalEdgesEnd)/Abc_MaxInt(1, p->nTotalEdgesBeg) );
    printf( "\n" );
1829
}
1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848
void Abc_NtkCountStats( Sfm_Dec_t * p, int Limit )
{
    int Gate, nGates = Vec_IntSize(&p->vObjGates);
    if ( nGates == Limit )
        return;
    Gate = Vec_IntEntryLast(&p->vObjGates);
    if ( nGates > Limit + 1 )
        p->nNodesResyn++;
    else if ( Gate == p->GateConst0 )
        p->nNodesConst0++;
    else if ( Gate == p->GateConst1 )
        p->nNodesConst1++;
    else if ( Gate == p->GateBuffer )
        p->nNodesBuf++;
    else if ( Gate == p->GateInvert )
        p->nNodesInv++;
    else 
        p->nNodesResyn++;
}
1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
1861
Abc_Obj_t * Abc_NtkAreaOptOne( Sfm_Dec_t * p, int i )
1862
{
1863
    abctime clk;
1864 1865
    Abc_Ntk_t * pNtk = p->pNtk;
    Sfm_Par_t * pPars = p->pPars;
1866
    Abc_Obj_t * pObj = Abc_NtkObj( p->pNtk, i ); 
1867
    int Limit, RetValue;
1868
    if ( pPars->nMffcMin > 1 && Abc_NodeMffcLabel(pObj, NULL) < pPars->nMffcMin )
1869 1870 1871 1872 1873 1874
        return NULL;
    if ( pPars->iNodeOne && i != pPars->iNodeOne )
        return NULL;
    if ( pPars->iNodeOne )
        pPars->fVeryVerbose = (int)(i == pPars->iNodeOne);
    p->nNodesTried++;
1875
clk = Abc_Clock();
1876
    p->nDivs = Sfm_DecExtract( pNtk, pPars, pObj, &p->vObjRoots, &p->vObjGates, &p->vObjFanins, &p->vObjMap, &p->vGateTfi, &p->vGateTfo, &p->vObjMffc, &p->vObjInMffc, NULL, NULL );
1877
p->timeWin += Abc_Clock() - clk;
1878 1879 1880 1881 1882 1883 1884 1885 1886 1887
    if ( pPars->nWinSizeMax && pPars->nWinSizeMax < Vec_IntSize(&p->vObjGates) )
        return NULL;
    p->nMffc = Vec_IntSize(&p->vObjMffc);
    p->AreaMffc = Sfm_DecMffcArea(pNtk, &p->vObjMffc);
    p->nMaxDivs = Abc_MaxInt( p->nMaxDivs, p->nDivs );
    p->nAllDivs += p->nDivs;
    p->iTarget = pObj->iTemp;
    Limit = Vec_IntSize( &p->vObjGates );
    p->nMaxWin = Abc_MaxInt( p->nMaxWin, Limit );
    p->nAllWin += Limit;
1888
clk = Abc_Clock();
1889
    RetValue = Sfm_DecPrepareSolver( p );
1890
p->timeCnf += Abc_Clock() - clk;
1891 1892
    if ( !RetValue )
        return NULL;
1893
clk = Abc_Clock();
1894
    RetValue = Sfm_DecPeformDec2( p, pObj );
1895 1896 1897 1898 1899 1900
    if ( pPars->fMoreEffort && RetValue < 0 )
    {
        int Var, i;
        Vec_IntForEachEntryReverse( &p->vObjInMffc, Var, i )
        {
            p->iUseThis = Var; 
1901
            RetValue = Sfm_DecPeformDec2( p, pObj );
1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918
            p->iUseThis = -1;
            if ( RetValue < 0 )
            {
                //printf( "Node %d: Not found among %d.\n", Abc_ObjId(pObj), Vec_IntSize(&p->vObjInMffc) );
            }
            else
            {
                p->nEfforts++;
                if ( p->pPars->fVerbose )
                {
                    //printf( "Node %5d: (%2d out of %2d)  Gate=%s ", Abc_ObjId(pObj), i, Vec_IntSize(&p->vObjInMffc), Mio_GateReadName((Mio_Gate_t*)pObj->pData) );
                    //Dau_DsdPrintFromTruth( p->Copy, p->nSuppVars );
                }
                break;
            }
        }
    }
1919 1920
    if ( p->pPars->fVeryVerbose )
        printf( "\n\n" );
1921
p->timeSat += Abc_Clock() - clk;
1922 1923 1924 1925
    if ( RetValue < 0 )
        return NULL;
    p->nNodesChanged++;
    Abc_NtkCountStats( p, Limit );
1926
    return Sfm_DecInsert( pNtk, pObj, Limit, &p->vObjGates, &p->vObjFanins, &p->vObjMap, &p->vGateHands, p->GateBuffer, p->GateInvert, &p->vGateFuncs, NULL, p->pMit );
1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956
}
void Abc_NtkAreaOpt( Sfm_Dec_t * p )
{
    Abc_Obj_t * pObj; 
    int i, nStop = Abc_NtkObjNumMax(p->pNtk);
    Abc_NtkForEachNode( p->pNtk, pObj, i )
    {
        if ( i >= nStop || (p->pPars->nNodesMax && i > p->pPars->nNodesMax) )
            break;
        Abc_NtkAreaOptOne( p, i );
    }
}
void Abc_NtkAreaOpt2( Sfm_Dec_t * p )
{
    Abc_Obj_t * pObj, * pObjNew, * pFanin; 
    int i, k, nStop = Abc_NtkObjNumMax(p->pNtk);
    Vec_Ptr_t * vFront = Vec_PtrAlloc( 1000 );
    Abc_NtkForEachObj( p->pNtk, pObj, i )
        assert( pObj->fMarkB == 0 );
    // start the queue of nodes to be tried
    Abc_NtkForEachCo( p->pNtk, pObj, i )
        if ( Abc_ObjIsNode(Abc_ObjFanin0(pObj)) && !Abc_ObjFanin0(pObj)->fMarkB )
        {
            Abc_ObjFanin0(pObj)->fMarkB = 1;
            Vec_PtrPush( vFront, Abc_ObjFanin0(pObj) );
        }
    // process nodes in this order
    Vec_PtrForEachEntry( Abc_Obj_t *, vFront, pObj, i )
    {
        if ( Abc_ObjIsNone(pObj) )
1957
            continue;
1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977
        pObjNew = Abc_NtkAreaOptOne( p, Abc_ObjId(pObj) );
        if ( pObjNew != NULL )
        {
            if ( !Abc_ObjIsNode(pObjNew) || Abc_ObjFaninNum(pObjNew) == 0 || pObjNew->fMarkB )
                continue;
            if ( (int)Abc_ObjId(pObjNew) < nStop )
            {
                pObjNew->fMarkB = 1;
                Vec_PtrPush( vFront, pObjNew );
                continue;
            }
        }
        else
            pObjNew = pObj;
        Abc_ObjForEachFanin( pObjNew, pFanin, k )
            if ( Abc_ObjIsNode(pFanin) && Abc_ObjFaninNum(pObjNew) > 0 && !pFanin->fMarkB )
            {
                pFanin->fMarkB = 1;
                Vec_PtrPush( vFront, pFanin );
            }
1978
    }
1979 1980 1981
    Abc_NtkForEachObj( p->pNtk, pObj, i )
        pObj->fMarkB = 0;
    Vec_PtrFree( vFront );
1982
}
1983

1984 1985 1986
void Abc_NtkDelayOpt( Sfm_Dec_t * p )
{
    Abc_Ntk_t * pNtk = p->pNtk;
1987
    Sfm_Par_t * pPars = p->pPars; int n;
1988
    Abc_NtkCleanMarkABC( pNtk );
1989
    for ( n = 0; pPars->nNodesMax == 0 || n < pPars->nNodesMax; n++ )
1990
    {
1991
        Abc_Obj_t * pObj, * pObjNew; abctime clk;
1992
        int i = 0, Limit, RetValue;
1993 1994 1995
        // collect nodes
        if ( pPars->iNodeOne )
            Vec_IntFill( &p->vCands, 1, pPars->iNodeOne );
1996 1997 1998
        else if ( p->pTim && !Sfm_TimPriorityNodes(p->pTim, &p->vCands, p->pPars->nTimeWin) )
            break;
        else if ( p->pMit && !Sfm_MitPriorityNodes(p->pMit, &p->vCands, p->pPars->nTimeWin) )
1999
            break;
2000
        // try improving delay for the nodes according to the priority
2001 2002
        Abc_NtkForEachObjVec( &p->vCands, p->pNtk, pObj, i )
        {
2003
            int OldId = Abc_ObjId(pObj);
2004
            int DelayOld = Sfm_ManReadObjDelay(p, OldId);
2005
            assert( pObj->fMarkA == 0 );
2006 2007
            p->nNodesTried++;
clk = Abc_Clock();
2008
            p->nDivs = Sfm_DecExtract( pNtk, pPars, pObj, &p->vObjRoots, &p->vObjGates, &p->vObjFanins, &p->vObjMap, &p->vGateTfi, &p->vGateTfo, &p->vObjMffc, &p->vObjInMffc, p->pTim, p->pMit );
2009 2010
p->timeWin += Abc_Clock() - clk;
            if ( p->nDivs < 2 || (pPars->nWinSizeMax && pPars->nWinSizeMax < Vec_IntSize(&p->vObjGates)) )
2011
            { 
2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032
                pObj->fMarkA = 1;
                continue;
            }
            p->nMffc = Vec_IntSize(&p->vObjMffc);
            p->AreaMffc = Sfm_DecMffcArea(pNtk, &p->vObjMffc);
            p->nMaxDivs = Abc_MaxInt( p->nMaxDivs, p->nDivs );
            p->nAllDivs += p->nDivs;
            p->iTarget = pObj->iTemp;
            Limit = Vec_IntSize( &p->vObjGates );
            p->nMaxWin = Abc_MaxInt( p->nMaxWin, Limit );
            p->nAllWin += Limit;
clk = Abc_Clock();
            RetValue = Sfm_DecPrepareSolver( p );
p->timeCnf += Abc_Clock() - clk;
            if ( !RetValue )
            {
                pObj->fMarkA = 1;
                continue;
            }
clk = Abc_Clock();
            RetValue = Sfm_DecPeformDec3( p, pObj );
2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056
            if ( pPars->fMoreEffort && RetValue < 0 )
            {
                int Var, i;
                Vec_IntForEachEntryReverse( &p->vObjInMffc, Var, i )
                {
                    p->iUseThis = Var; 
                    RetValue = Sfm_DecPeformDec3( p, pObj );
                    p->iUseThis = -1;
                    if ( RetValue < 0 )
                    {
                        //printf( "Node %d: Not found among %d.\n", Abc_ObjId(pObj), Vec_IntSize(&p->vObjInMffc) );
                    }
                    else
                    {
                        p->nEfforts++;
                        if ( p->pPars->fVerbose )
                        {
                            //printf( "Node %5d: (%2d out of %2d)  Gate=%s ", Abc_ObjId(pObj), i, Vec_IntSize(&p->vObjInMffc), Mio_GateReadName((Mio_Gate_t*)pObj->pData) );
                            //Dau_DsdPrintFromTruth( p->Copy, p->nSuppVars );
                        }
                        break;
                    }
                }
            }
2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068
            if ( p->pPars->fVeryVerbose )
                printf( "\n\n" );
p->timeSat += Abc_Clock() - clk;
            if ( RetValue < 0 )
            {
                pObj->fMarkA = 1;
                continue;
            }
            assert( Vec_IntSize(&p->vObjGates) - Limit > 0 );
            assert( Vec_IntSize(&p->vObjGates) - Limit <= 2 );
            p->nNodesChanged++;
            Abc_NtkCountStats( p, Limit );
2069
            // reduce load due to removed MFFC
2070 2071
            if ( p->pMit ) Sfm_MitUpdateLoad( p->pMit, &p->vGateMffc, 0 ); // assuming &p->vGateMffc contains MFFC
            Sfm_DecInsert( pNtk, pObj, Limit, &p->vObjGates, &p->vObjFanins, &p->vObjMap, &p->vGateHands, p->GateBuffer, p->GateInvert, &p->vGateFuncs, &p->vNewNodes, p->pMit );
2072
            // increase load due to added new nodes
2073
            if ( p->pMit ) Sfm_MitUpdateLoad( p->pMit, &p->vNewNodes, 1 ); // assuming &p->vNewNodes contains new nodes
2074
clk = Abc_Clock();
2075
            if ( p->pMit )
2076
                Sfm_MitUpdateTiming( p->pMit, &p->vNewNodes );
2077
            else
2078
                Sfm_TimUpdateTiming( p->pTim, &p->vNewNodes );
2079
p->timeTime += Abc_Clock() - clk;
2080
            pObjNew = Abc_NtkObj( pNtk, Abc_NtkObjNumMax(pNtk)-1 );
2081
            assert( p->pMit || p->DelayMin == 0 || p->DelayMin == Sfm_ManReadObjDelay(p, Abc_ObjId(pObjNew)) );
2082
            // report
2083
            if ( pPars->fDelayVerbose )
2084
                printf( "Node %5d  %5d :  I =%3d.  Cand = %5d (%6.2f %%)   Old =%8.2f.  New =%8.2f.  Final =%8.2f.  WNS =%8.2f.\n", 
2085
                    OldId, Abc_NtkObjNumMax(p->pNtk), i, Vec_IntSize(&p->vCands), 100.0 * Vec_IntSize(&p->vCands) / Abc_NtkNodeNum(p->pNtk),
2086 2087
                    Scl_Int2Flt(DelayOld), Scl_Int2Flt(Sfm_ManReadObjDelay(p, Abc_ObjId(pObjNew))), 
                    Scl_Int2Flt(Sfm_ManReadNtkDelay(p)), Scl_Int2Flt(Sfm_ManReadNtkMinSlack(p)) );
2088 2089
            break;
        }
2090 2091
        if ( pPars->iNodeOne )
            break;
2092
    }
2093
    Abc_NtkCleanMarkABC( pNtk );
2094 2095 2096 2097
}
void Abc_NtkPerformMfs3( Abc_Ntk_t * pNtk, Sfm_Par_t * pPars )
{
    Sfm_Dec_t * p = Sfm_DecStart( pPars, (Mio_Library_t *)pNtk->pManFunc, pNtk );
2098
    if ( pPars->fVerbose )
2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110
    {
        printf( "Remapping parameters: " );
        if ( pPars->nTfoLevMax )
            printf( "TFO = %d. ",     pPars->nTfoLevMax );
        if ( pPars->nTfiLevMax )
            printf( "TFI = %d. ",     pPars->nTfiLevMax );
        if ( pPars->nFanoutMax )
            printf( "FanMax = %d. ",  pPars->nFanoutMax );
        if ( pPars->nWinSizeMax )
            printf( "WinMax = %d. ",  pPars->nWinSizeMax );
        if ( pPars->nBTLimit )
            printf( "Confl = %d. ",   pPars->nBTLimit );
2111
        if ( pPars->nMffcMin && pPars->fArea )
2112
            printf( "MffcMin = %d. ", pPars->nMffcMin );
2113
        if ( pPars->nMffcMax && pPars->fArea )
2114 2115 2116 2117 2118
            printf( "MffcMax = %d. ", pPars->nMffcMax );
        if ( pPars->nDecMax )
            printf( "DecMax = %d. ",  pPars->nDecMax );
        if ( pPars->iNodeOne )
            printf( "Pivot = %d. ",   pPars->iNodeOne );
2119 2120
        if ( !pPars->fArea )
            printf( "Win = %d. ",     pPars->nTimeWin );
2121
        if ( !pPars->fArea )
2122
            printf( "Delta = %.2f ps. ", Scl_Int2Flt(p->DeltaCrit) );
2123 2124
        if ( pPars->fArea )
            printf( "0-cost = %s. ",  pPars->fZeroCost ? "yes" : "no" );
2125
        printf( "Effort = %s. ",      pPars->fMoreEffort ? "yes" : "no" );
2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137
        printf( "Sim = %s. ",         pPars->fUseSim ? "yes" : "no" );
        printf( "\n" );
    }
    // preparation steps
    Abc_NtkLevel( pNtk );
    if ( p->pPars->fUseSim )
        Sfm_NtkSimulate( pNtk );
    // record statistics
    if ( pPars->fVerbose ) p->nTotalNodesBeg = Abc_NtkNodeNum(pNtk);
    if ( pPars->fVerbose ) p->nTotalEdgesBeg = Abc_NtkGetTotalFanins(pNtk);
    // perform optimization
    if ( pPars->fArea )
2138 2139 2140 2141 2142 2143
    {
        if ( pPars->fAreaRev )
            Abc_NtkAreaOpt2( p );
        else
            Abc_NtkAreaOpt( p );
    }
2144 2145 2146 2147 2148 2149
    else
        Abc_NtkDelayOpt( p );
    // record statistics
    if ( pPars->fVerbose ) p->nTotalNodesEnd = Abc_NtkNodeNum(pNtk);
    if ( pPars->fVerbose ) p->nTotalEdgesEnd = Abc_NtkGetTotalFanins(pNtk);
    // print stats and quit
2150 2151
    if ( pPars->fVerbose )
    Sfm_DecPrintStats( p );
2152 2153
    if ( pPars->fLibVerbose )
        Sfm_LibPrint( p->pLib );
2154
    Sfm_DecStop( p );
2155 2156 2157 2158 2159
    if ( pPars->fArea )
    {
        extern void Abc_NtkChangePerform( Abc_Ntk_t * pNtk, int fVerbose );
        Abc_NtkChangePerform( pNtk, pPars->fVerbose );
    }
2160 2161 2162 2163 2164 2165 2166 2167 2168
}

////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


ABC_NAMESPACE_IMPL_END