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

  FileName    [ifDsd.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [FPGA mapping based on priority cuts.]

  Synopsis    [Computation of DSD representation.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - November 21, 2006.]

  Revision    [$Id: ifTruth.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]

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

21
#include <math.h>
22
#include "if.h"
23
#include "ifCount.h"
24
#include "misc/extra/extra.h"
25
#include "sat/bsat/satSolver.h"
26
#include "aig/gia/gia.h"
27
#include "bool/kit/kit.h"
28

29 30 31 32
#ifdef ABC_USE_CUDD
#include "bdd/extrab/extraBdd.h"
#endif

33 34 35 36 37 38 39 40 41 42 43
#ifdef ABC_USE_PTHREADS

#ifdef _WIN32
#include "../lib/pthread.h"
#else
#include <pthread.h>
#include <unistd.h>
#endif

#endif

44 45 46 47 48 49 50
ABC_NAMESPACE_IMPL_START


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

51 52
#define DSD_VERSION "dsd1"

53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
// network types
typedef enum { 
    IF_DSD_NONE = 0,               // 0:  unknown
    IF_DSD_CONST0,                 // 1:  constant
    IF_DSD_VAR,                    // 2:  variable
    IF_DSD_AND,                    // 3:  AND
    IF_DSD_XOR,                    // 4:  XOR
    IF_DSD_MUX,                    // 5:  MUX
    IF_DSD_PRIME                   // 6:  PRIME
} If_DsdType_t;

typedef struct If_DsdObj_t_ If_DsdObj_t;
struct If_DsdObj_t_
{
    unsigned       Id;             // node ID
    unsigned       Type    :  3;   // node type
69
    unsigned       nSupp   :  5;   // variable
70 71
    unsigned       fMark   :  1;   // user mark
    unsigned       Count   : 18;   // variable
72 73 74 75 76 77
    unsigned       nFans   :  5;   // fanin count
    unsigned       pFans[0];       // fanins
};

struct If_DsdMan_t_
{
78
    char *         pStore;         // input/output file
79
    int            nVars;          // max var number
80
    int            LutSize;        // LUT size
81 82 83 84
    int            nWords;         // word number
    int            nBins;          // table size
    unsigned *     pBins;          // hash table
    Mem_Flex_t *   pMem;           // memory for nodes
85 86 87
    Vec_Ptr_t      vObjs;          // objects
    Vec_Int_t      vNexts;         // next pointers
    Vec_Int_t      vTruths;        // truth IDs of prime nodes
88 89
    Vec_Int_t *    vTemp1;         // temp
    Vec_Int_t *    vTemp2;         // temp
90
    word **        pTtElems;       // elementary TTs
91 92
    Vec_Mem_t *    vTtMem[IF_MAX_FUNC_LUTSIZE+1];  // truth table memory and hash table
    Vec_Ptr_t *    vTtDecs[IF_MAX_FUNC_LUTSIZE+1]; // truth table decompositions
93
    Vec_Wec_t *    vIsops[IF_MAX_FUNC_LUTSIZE+1];  // ISOP for each function
94
    int *          pSched[IF_MAX_FUNC_LUTSIZE];    // grey code schedules
95 96 97
    int            nTtBits;        // the number of truth table bits
    int            nConfigWords;   // the number of words for config data per node
    Vec_Wrd_t *    vConfigs;       // permutations
98 99
    Gia_Man_t *    pTtGia;         // GIA to represent truth tables
    Vec_Int_t *    vCover;         // temporary memory
100
    void *         pSat;           // SAT solver
101
    char *         pCellStr;       // symbolic cell description
102
    int            nObjsPrev;      // previous number of objects
103
    int            fNewAsUseless;  // set new as useless
104 105
    int            nUniqueHits;    // statistics
    int            nUniqueMisses;  // statistics
106 107 108
    abctime        timeDsd;        // statistics
    abctime        timeCanon;      // statistics
    abctime        timeCheck;      // statistics
109
    abctime        timeCheck2;     // statistics
110
    abctime        timeVerify;     // statistics
111 112 113
};

static inline int           If_DsdObjWordNum( int nFans )                                    { return sizeof(If_DsdObj_t) / 8 + nFans / 2 + ((nFans & 1) > 0);              }
114
static inline int           If_DsdObjTruthId( If_DsdMan_t * p, If_DsdObj_t * pObj )          { return (pObj->Type == IF_DSD_PRIME && pObj->nFans > 2) ? Vec_IntEntry(&p->vTruths, pObj->Id) : -1;     }
115
static inline word *        If_DsdObjTruth( If_DsdMan_t * p, If_DsdObj_t * pObj )            { return Vec_MemReadEntry(p->vTtMem[pObj->nFans], If_DsdObjTruthId(p, pObj));  }
116
static inline void          If_DsdObjSetTruth( If_DsdMan_t * p, If_DsdObj_t * pObj, int Id ) { assert( pObj->Type == IF_DSD_PRIME && pObj->nFans > 2 ); Vec_IntWriteEntry(&p->vTruths, pObj->Id, Id); }
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131

static inline void          If_DsdObjClean( If_DsdObj_t * pObj )                       { memset( pObj, 0, sizeof(If_DsdObj_t) );                                            }
static inline int           If_DsdObjId( If_DsdObj_t * pObj )                          { return pObj->Id;                                                                   }
static inline int           If_DsdObjType( If_DsdObj_t * pObj )                        { return pObj->Type;                                                                 }
static inline int           If_DsdObjIsVar( If_DsdObj_t * pObj )                       { return (int)(pObj->Type == IF_DSD_VAR);                                            }
static inline int           If_DsdObjSuppSize( If_DsdObj_t * pObj )                    { return pObj->nSupp;                                                                }
static inline int           If_DsdObjFaninNum( If_DsdObj_t * pObj )                    { return pObj->nFans;                                                                }
static inline int           If_DsdObjFaninC( If_DsdObj_t * pObj, int i )               { assert(i < (int)pObj->nFans); return Abc_LitIsCompl(pObj->pFans[i]);               }
static inline int           If_DsdObjFaninLit( If_DsdObj_t * pObj, int i )             { assert(i < (int)pObj->nFans); return pObj->pFans[i];                               }

static inline If_DsdObj_t * If_DsdVecObj( Vec_Ptr_t * p, int Id )                      { return (If_DsdObj_t *)Vec_PtrEntry(p, Id);                                         }
static inline If_DsdObj_t * If_DsdVecConst0( Vec_Ptr_t * p )                           { return If_DsdVecObj( p, 0 );                                                       }
static inline If_DsdObj_t * If_DsdVecVar( Vec_Ptr_t * p, int v )                       { return If_DsdVecObj( p, v+1 );                                                     }
static inline int           If_DsdVecObjSuppSize( Vec_Ptr_t * p, int iObj )            { return If_DsdVecObj( p, iObj )->nSupp;                                             }
static inline int           If_DsdVecLitSuppSize( Vec_Ptr_t * p, int iLit )            { return If_DsdVecObjSuppSize( p, Abc_Lit2Var(iLit) );                               }
132
static inline int           If_DsdVecObjRef( Vec_Ptr_t * p, int iObj )                 { return If_DsdVecObj( p, iObj )->Count;                                             }
133
static inline void          If_DsdVecObjIncRef( Vec_Ptr_t * p, int iObj )              { if ( If_DsdVecObjRef(p, iObj) < 0x3FFFF ) If_DsdVecObj( p, iObj )->Count++;        }
134
static inline If_DsdObj_t * If_DsdObjFanin( Vec_Ptr_t * p, If_DsdObj_t * pObj, int i ) { assert(i < (int)pObj->nFans); return If_DsdVecObj(p, Abc_Lit2Var(pObj->pFans[i])); }
135 136
static inline int           If_DsdVecObjMark( Vec_Ptr_t * p, int iObj )                { return If_DsdVecObj( p, iObj )->fMark;                                             }
static inline void          If_DsdVecObjSetMark( Vec_Ptr_t * p, int iObj )             { If_DsdVecObj( p, iObj )->fMark = 1;                                                }
137
static inline void          If_DsdVecObjClearMark( Vec_Ptr_t * p, int iObj )           { If_DsdVecObj( p, iObj )->fMark = 0;                                                }
138 139 140

#define If_DsdVecForEachObj( vVec, pObj, i )                \
    Vec_PtrForEachEntry( If_DsdObj_t *, vVec, pObj, i )
141 142 143
#define If_DsdVecForEachObjStart( vVec, pObj, i, Start )    \
    Vec_PtrForEachEntryStart( If_DsdObj_t *, vVec, pObj, i, Start )
#define If_DsdVecForEachObjVec( vNodes, vVec, pObj, i )     \
144
    for ( i = 0; (i < Vec_IntSize(vNodes)) && ((pObj) = If_DsdVecObj(vVec, Vec_IntEntry(vNodes,i))); i++ )
145
#define If_DsdVecForEachNode( vVec, pObj, i )               \
146
    Vec_PtrForEachEntryStart( If_DsdObj_t *, vVec, pObj, i, 2 )
147 148
#define If_DsdObjForEachFanin( vVec, pObj, pFanin, i )      \
    for ( i = 0; (i < If_DsdObjFaninNum(pObj)) && ((pFanin) = If_DsdObjFanin(vVec, pObj, i)); i++ )
149
#define If_DsdObjForEachFaninLit( vVec, pObj, iLit, i )     \
150 151
    for ( i = 0; (i < If_DsdObjFaninNum(pObj)) && ((iLit) = If_DsdObjFaninLit(pObj, i)); i++ )

152 153
extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash );

154 155 156
////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////
157

158 159
/**Function*************************************************************

160
  Synopsis    []
161 162 163 164 165 166 167 168

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
169
char * If_DsdManFileName( If_DsdMan_t * p )
170
{
171
    return p->pStore;
172
}
173
int If_DsdManVarNum( If_DsdMan_t * p )
174
{
175
    return p->nVars;
176
}
177 178 179 180
int If_DsdManObjNum( If_DsdMan_t * p )
{
    return Vec_PtrSize( &p->vObjs );
}
181
int If_DsdManLutSize( If_DsdMan_t * p )
182
{
183
    return p->LutSize;
184
}
185 186 187 188 189 190 191 192
int If_DsdManTtBitNum( If_DsdMan_t * p )
{
    return p->nTtBits;
}
int If_DsdManPermBitNum( If_DsdMan_t * p )
{
    return (Abc_Base2Log(p->nVars + 1) + 1) * p->nVars;
}
193 194 195 196
void If_DsdManSetLutSize( If_DsdMan_t * p, int nLutSize )
{
    p->LutSize = nLutSize;
}
197 198 199 200
int If_DsdManSuppSize( If_DsdMan_t * p, int iDsd )
{
    return If_DsdVecLitSuppSize( &p->vObjs, iDsd );
}
201
int If_DsdManCheckDec( If_DsdMan_t * p, int iDsd )
202
{
203
    return If_DsdVecObjMark( &p->vObjs, Abc_Lit2Var(iDsd) );
204
}
205 206 207 208 209 210
int If_DsdManReadMark( If_DsdMan_t * p, int iDsd )
{
    return If_DsdVecObjMark( &p->vObjs, Abc_Lit2Var(iDsd) );
}
void If_DsdManSetNewAsUseless( If_DsdMan_t * p )
{
211 212
    if ( p->nObjsPrev == 0 )
        p->nObjsPrev = If_DsdManObjNum(p);
213 214
    p->fNewAsUseless = 1;
}
215
word * If_DsdManGetFuncConfig( If_DsdMan_t * p, int iDsd )
216
{
217
    return p->vConfigs ? Vec_WrdEntryP(p->vConfigs, p->nConfigWords * Abc_Lit2Var(iDsd)) : NULL;
218 219 220 221 222
}
char * If_DsdManGetCellStr( If_DsdMan_t * p )
{
    return p->pCellStr;
}
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246

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

  Synopsis    [DSD manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline word ** If_ManDsdTtElems()
{
    static word TtElems[DAU_MAX_VAR+1][DAU_MAX_WORD], * pTtElems[DAU_MAX_VAR+1] = {NULL};
    if ( pTtElems[0] == NULL )
    {
        int v;
        for ( v = 0; v <= DAU_MAX_VAR; v++ )
            pTtElems[v] = TtElems[v];
        Abc_TtElemInit( pTtElems, DAU_MAX_VAR );
    }
    return pTtElems;
}
247 248
If_DsdObj_t * If_DsdObjAlloc( If_DsdMan_t * p, int Type, int nFans )
{
249
    int nWords = If_DsdObjWordNum( nFans );
250 251 252 253
    If_DsdObj_t * pObj = (If_DsdObj_t *)Mem_FlexEntryFetch( p->pMem, sizeof(word) * nWords );
    If_DsdObjClean( pObj );
    pObj->Type   = Type;
    pObj->nFans  = nFans;
254
    pObj->Id     = Vec_PtrSize( &p->vObjs );
255
    pObj->fMark  = p->fNewAsUseless;
256
    pObj->Count  = 0;
257 258 259 260 261
    Vec_PtrPush( &p->vObjs, pObj );
    Vec_IntPush( &p->vNexts, 0 );
    Vec_IntPush( &p->vTruths, -1 );
    assert( Vec_IntSize(&p->vNexts) == Vec_PtrSize(&p->vObjs) );
    assert( Vec_IntSize(&p->vTruths) == Vec_PtrSize(&p->vObjs) );
262 263 264
    return pObj;
}
If_DsdMan_t * If_DsdManAlloc( int nVars, int LutSize )
265
{
266
    If_DsdMan_t * p; int v;
267
    char pFileName[100];
268
    assert( nVars <= DAU_MAX_VAR );
269
    sprintf( pFileName, "%02d.dsd", nVars );
270
    p = ABC_CALLOC( If_DsdMan_t, 1 );
271 272 273 274
    p->pStore  = Abc_UtilStrsav( pFileName );
    p->nVars   = nVars;
    p->LutSize = LutSize;
    p->nWords  = Abc_TtWordNum( nVars );
275
    p->nBins   = Abc_PrimeCudd( 100000 );
276 277
    p->pBins   = ABC_CALLOC( unsigned, p->nBins );
    p->pMem    = Mem_FlexStart();
278
    p->nConfigWords = 1;
279 280 281
    Vec_PtrGrow( &p->vObjs, 10000 );
    Vec_IntGrow( &p->vNexts, 10000 );
    Vec_IntGrow( &p->vTruths, 10000 );
282 283
    If_DsdObjAlloc( p, IF_DSD_CONST0, 0 );
    If_DsdObjAlloc( p, IF_DSD_VAR, 0 )->nSupp = 1;
284 285
    p->vTemp1   = Vec_IntAlloc( 32 );
    p->vTemp2   = Vec_IntAlloc( 32 );
286
    p->pTtElems = If_ManDsdTtElems();
287 288 289 290 291 292 293 294 295 296 297 298
    for ( v = 3; v <= nVars; v++ )
    {
        p->vTtMem[v] = Vec_MemAlloc( Abc_TtWordNum(v), 12 );
        Vec_MemHashAlloc( p->vTtMem[v], 10000 );
        p->vTtDecs[v] = Vec_PtrAlloc( 1000 );
    }
/*
    p->pTtGia   = Gia_ManStart( nVars );
    Gia_ManHashAlloc( p->pTtGia );
    for ( v = 0; v < nVars; v++ )
        Gia_ManAppendCi( p->pTtGia );
*/
299 300
    for ( v = 2; v < nVars; v++ )
        p->pSched[v] = Extra_GreyCodeSchedule( v );
301 302
    if ( LutSize )
    p->pSat     = If_ManSatBuildXY( LutSize );
303
    p->vCover   = Vec_IntAlloc( 0 );
304 305
    return p;
}
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
void If_DsdManAllocIsops( If_DsdMan_t * p, int nLutSize )
{
    Vec_Int_t * vLevel;
    int v, i, fCompl;
    word * pTruth;
    if ( p->vIsops[3] != NULL )
        return;
    if ( Vec_PtrSize(&p->vObjs) > 2 )
        printf( "Warning: DSD manager is already started without ISOPs.\n" );
    for ( v = 3; v <= nLutSize; v++ )
    {
        p->vIsops[v] = Vec_WecAlloc( 100 );
        Vec_MemForEachEntry( p->vTtMem[v], pTruth, i )
        {
            vLevel = Vec_WecPushLevel( p->vIsops[v] );
            fCompl = Kit_TruthIsop( (unsigned *)pTruth, v, p->vCover, 1 );
            if ( fCompl >= 0 && Vec_IntSize(p->vCover) <= 8 )
            {
                Vec_IntGrow( vLevel, Vec_IntSize(p->vCover) );
                Vec_IntAppend( vLevel, p->vCover );
                if ( fCompl )
                    vLevel->nCap ^= (1<<16); // hack to remember complemented attribute
            }
        }
        assert( Vec_WecSize(p->vIsops[v]) == Vec_MemEntryNum(p->vTtMem[v]) );
    }
}
333
void If_DsdManFree( If_DsdMan_t * p, int fVerbose )
334
{
335
    int v;
336
//    If_DsdManDumpDsd( p );
337
    if ( fVerbose )
338
        If_DsdManPrint( p, NULL, 0, 0, 0, 0, 0 );
339
    if ( fVerbose )
340 341 342 343 344 345 346 347
    {
        char FileName[10];
        for ( v = 3; v <= p->nVars; v++ )
        {
            sprintf( FileName, "dumpdsd%02d", v );
            Vec_MemDumpTruthTables( p->vTtMem[v], FileName, v );
        }
    }
348 349
    for ( v = 2; v < p->nVars; v++ )
        ABC_FREE( p->pSched[v] );
350 351 352 353 354
    for ( v = 3; v <= p->nVars; v++ )
    {
        Vec_MemHashFree( p->vTtMem[v] );
        Vec_MemFree( p->vTtMem[v] );
        Vec_VecFree( (Vec_Vec_t *)(p->vTtDecs[v]) );
355 356
        if ( p->vIsops[v] )
            Vec_WecFree( p->vIsops[v] );
357
    }
358
    Vec_WrdFreeP( &p->vConfigs );
359 360
    Vec_IntFreeP( &p->vTemp1 );
    Vec_IntFreeP( &p->vTemp2 );
361 362 363
    ABC_FREE( p->vObjs.pArray );
    ABC_FREE( p->vNexts.pArray );
    ABC_FREE( p->vTruths.pArray );
364
    Mem_FlexStop( p->pMem, 0 );
365 366
    Gia_ManStopP( &p->pTtGia );
    Vec_IntFreeP( &p->vCover );
367
    If_ManSatUnbuild( p->pSat );
368
    ABC_FREE( p->pCellStr );
369
    ABC_FREE( p->pStore );
370 371 372
    ABC_FREE( p->pBins );
    ABC_FREE( p );
}
373
void If_DsdManDumpDsd( If_DsdMan_t * p, int Support )
374
{
375
    char * pFileName = "tts_nondsd.txt";
376
    If_DsdObj_t * pObj; 
377 378
    Vec_Int_t * vMap;
    FILE * pFile = fopen( pFileName, "wb" );
379
    int v, i;
380 381 382 383 384
    if ( pFile == NULL )
    {
        printf( "Cannot open file \"%s\".\n", pFileName );
        return;
    }
385
    for ( v = 3; v <= p->nVars; v++ )
386
    {
387
        vMap = Vec_IntStart( Vec_MemEntryNum(p->vTtMem[v]) );
388
        If_DsdVecForEachObj( &p->vObjs, pObj, i )
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
        {
            if ( Support && Support != If_DsdObjSuppSize(pObj) )
                continue;
            if ( If_DsdObjType(pObj) != IF_DSD_PRIME )
                continue;
            if ( Vec_IntEntry(vMap, If_DsdObjTruthId(p, pObj)) )
                continue;
            Vec_IntWriteEntry(vMap, If_DsdObjTruthId(p, pObj), 1);
            fprintf( pFile, "0x" );
            Abc_TtPrintHexRev( pFile, If_DsdObjTruth(p, pObj), Support ? Abc_MaxInt(Support, 6) : v );
            fprintf( pFile, "\n" );
            //printf( "    " );
            //Dau_DsdPrintFromTruth( If_DsdObjTruth(p, pObj), p->nVars );
        }
        Vec_IntFree( vMap );
404 405 406
    }
    fclose( pFile );
}
407
void If_DsdManDumpAll( If_DsdMan_t * p, int Support )
408 409
{
    extern word * If_DsdManComputeTruth( If_DsdMan_t * p, int iDsd, unsigned char * pPermLits );
410
    char * pFileName = "tts_all.txt";
411
    If_DsdObj_t * pObj;
412 413
    word * pRes; int i;
    FILE * pFile = fopen( pFileName, "wb" );
414 415 416 417 418
    if ( pFile == NULL )
    {
        printf( "Cannot open file \"%s\".\n", pFileName );
        return;
    }
419
    If_DsdVecForEachObj( &p->vObjs, pObj, i )
420
    {
421 422
        if ( Support && Support != If_DsdObjSuppSize(pObj) )
            continue;
423 424
        pRes = If_DsdManComputeTruth( p, Abc_Var2Lit(i, 0), NULL );
        fprintf( pFile, "0x" );
425
        Abc_TtPrintHexRev( pFile, pRes, Support ? Abc_MaxInt(Support, 6) : p->nVars );
426 427 428
        fprintf( pFile, "\n" );
//        printf( "    " );
//        Dau_DsdPrintFromTruth( pRes, p->nVars );
429 430 431
    }
    fclose( pFile );
}
Alan Mishchenko committed
432 433 434 435 436 437 438 439 440
int If_DsdManHasMarks( If_DsdMan_t * p )
{
    If_DsdObj_t * pObj;
    int i;
    If_DsdVecForEachObj( &p->vObjs, pObj, i )
        if ( pObj->fMark )
            return 1;
    return 0;
}
441 442 443 444 445 446 447 448 449 450 451 452

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

  Synopsis    [Printing.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
453 454 455 456 457 458 459 460
void If_DsdManHashProfile( If_DsdMan_t * p )
{
    If_DsdObj_t * pObj;
    unsigned * pSpot;
    int i, Counter;
    for ( i = 0; i < p->nBins; i++ )
    {
        Counter = 0;
461 462
        for ( pSpot = p->pBins + i; *pSpot; pSpot = (unsigned *)Vec_IntEntryP(&p->vNexts, pObj->Id), Counter++ )
             pObj = If_DsdVecObj( &p->vObjs, *pSpot );
463 464 465 466 467 468 469
//        if ( Counter > 5 )
//            printf( "%d ", Counter );
//        if ( i > 10000 )
//            break;
    }
//    printf( "\n" );
}
470 471 472 473
int If_DsdManCheckNonDec_rec( If_DsdMan_t * p, int Id )
{
    If_DsdObj_t * pObj;
    int i, iFanin;
474
    pObj = If_DsdVecObj( &p->vObjs, Id );
475 476 477 478 479 480
    if ( If_DsdObjType(pObj) == IF_DSD_CONST0 )
        return 0;
    if ( If_DsdObjType(pObj) == IF_DSD_VAR )
        return 0;
    if ( If_DsdObjType(pObj) == IF_DSD_PRIME )
        return 1;
481
    If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
482 483 484 485 486
        if ( If_DsdManCheckNonDec_rec( p, Abc_Lit2Var(iFanin) ) )
            return 1;
    return 0;
}
void If_DsdManPrint_rec( FILE * pFile, If_DsdMan_t * p, int iDsdLit, unsigned char * pPermLits, int * pnSupp )
487 488 489 490 491 492
{
    char OpenType[7]  = {0, 0, 0, '(', '[', '<', '{'};
    char CloseType[7] = {0, 0, 0, ')', ']', '>', '}'};
    If_DsdObj_t * pObj;
    int i, iFanin;
    fprintf( pFile, "%s", Abc_LitIsCompl(iDsdLit) ? "!" : ""  );
493
    pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iDsdLit) );
494 495 496 497
    if ( If_DsdObjType(pObj) == IF_DSD_CONST0 )
        { fprintf( pFile, "0" ); return; }
    if ( If_DsdObjType(pObj) == IF_DSD_VAR )
    {
498
        int iPermLit = pPermLits ? (int)pPermLits[(*pnSupp)++] : Abc_Var2Lit((*pnSupp)++, 0);
499 500 501 502 503 504
        fprintf( pFile, "%s%c", Abc_LitIsCompl(iPermLit)? "!":"", 'a' + Abc_Lit2Var(iPermLit) );
        return;
    }
    if ( If_DsdObjType(pObj) == IF_DSD_PRIME )
        Abc_TtPrintHexRev( pFile, If_DsdObjTruth(p, pObj), If_DsdObjFaninNum(pObj) );
    fprintf( pFile, "%c", OpenType[If_DsdObjType(pObj)] );
505
    If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
506
        If_DsdManPrint_rec( pFile, p, iFanin, pPermLits, pnSupp );
507 508
    fprintf( pFile, "%c", CloseType[If_DsdObjType(pObj)] );
}
509
void If_DsdManPrintOne( FILE * pFile, If_DsdMan_t * p, int iObjId, unsigned char * pPermLits, int fNewLine )
510 511 512
{
    int nSupp = 0;
    fprintf( pFile, "%6d : ", iObjId );
513 514 515
    fprintf( pFile, "%2d ",   If_DsdVecObjSuppSize(&p->vObjs, iObjId) );
    fprintf( pFile, "%8d ",   If_DsdVecObjRef(&p->vObjs, iObjId) );
    fprintf( pFile, "%d  ",    If_DsdVecObjMark(&p->vObjs, iObjId) );
516
    If_DsdManPrint_rec( pFile, p, Abc_Var2Lit(iObjId, 0), pPermLits, &nSupp );
517 518
    if ( fNewLine )
        fprintf( pFile, "\n" );
519
    assert( nSupp == If_DsdVecObjSuppSize(&p->vObjs, iObjId) );
520
}
521 522 523 524
#define DSD_ARRAY_LIMIT 16
void If_DsdManPrintDecs( FILE * pFile, If_DsdMan_t * p )
{
    Vec_Int_t * vDecs;
525
    int i, k, v, nSuppSize, nDecMax = 0;
526 527 528 529 530
    int pDecMax[IF_MAX_FUNC_LUTSIZE] = {0};
    int pCountsAll[IF_MAX_FUNC_LUTSIZE] = {0};
    int pCountsSSizes[IF_MAX_FUNC_LUTSIZE] = {0};
    int pCounts[IF_MAX_FUNC_LUTSIZE][DSD_ARRAY_LIMIT+2] = {{0}};
    word * pTruth;
531 532 533 534 535
    for ( v = 3; v <= p->nVars; v++ )
    {
        assert( Vec_MemEntryNum(p->vTtMem[v]) == Vec_PtrSize(p->vTtDecs[v]) );
        // find max number of decompositions
        Vec_PtrForEachEntry( Vec_Int_t *, p->vTtDecs[v], vDecs, i )
536
        {
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558
            pTruth = Vec_MemReadEntry( p->vTtMem[v], i );
            nSuppSize = Abc_TtSupportSize( pTruth, p->nVars );
            pDecMax[nSuppSize] = Abc_MaxInt( pDecMax[nSuppSize], Vec_IntSize(vDecs) );
            nDecMax = Abc_MaxInt( nDecMax, Vec_IntSize(vDecs) );
        }
        // fill up
        Vec_PtrForEachEntry( Vec_Int_t *, p->vTtDecs[v], vDecs, i )
        {
            pTruth = Vec_MemReadEntry( p->vTtMem[v], i );
            nSuppSize = Abc_TtSupportSize( pTruth, p->nVars );
            pCountsAll[nSuppSize]++;
            pCountsSSizes[nSuppSize] += Vec_IntSize(vDecs);
            pCounts[nSuppSize][Abc_MinInt(DSD_ARRAY_LIMIT+1,Vec_IntSize(vDecs))]++;
    //        pCounts[nSuppSize][Abc_MinInt(DSD_ARRAY_LIMIT+1,Vec_IntSize(vDecs)?1+(Vec_IntSize(vDecs)/10):0)]++;
    /*
            if ( nSuppSize == 6 && Vec_IntSize(vDecs) == pDecMax[6] )
            {
                fprintf( pFile, "0x" );
                Abc_TtPrintHex( pTruth, nSuppSize );
                Dau_DecPrintSets( vDecs, nSuppSize );
            }
    */
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
        }
    }
    // print header
    fprintf( pFile, " N :  " );
    fprintf( pFile, " Total  " );
    for ( k = 0; k <= DSD_ARRAY_LIMIT; k++ )
        fprintf( pFile, "%6d", k );
    fprintf( pFile, "  " );
    fprintf( pFile, "  More" );
    fprintf( pFile, "     Ave" );
    fprintf( pFile, "     Max" );
    fprintf( pFile, "\n" );
    // print rows
    for ( i = 0; i <= p->nVars; i++ )
    {
        fprintf( pFile, "%2d :  ", i );
        fprintf( pFile, "%6d  ", pCountsAll[i] );
        for ( k = 0; k <= DSD_ARRAY_LIMIT; k++ )
//            fprintf( pFile, "%6d", pCounts[i][k] );
            fprintf( pFile, "%6.1f", 100.0*pCounts[i][k]/Abc_MaxInt(1,pCountsAll[i]) );
        fprintf( pFile, "  " );
//        fprintf( pFile, "%6d", pCounts[i][k] );
        fprintf( pFile, "%6.1f", 100.0*pCounts[i][k]/Abc_MaxInt(1,pCountsAll[i]) );
        fprintf( pFile, "  " );
        fprintf( pFile, "%6.1f", 1.0*pCountsSSizes[i]/Abc_MaxInt(1,pCountsAll[i]) );
        fprintf( pFile, "  " );
        fprintf( pFile, "%6d", pDecMax[i] );
        fprintf( pFile, "\n" );
    }
}
589 590 591 592 593 594 595 596 597
void If_DsdManPrintOccurs( FILE * pFile, If_DsdMan_t * p )
{
    char Buffer[100];
    If_DsdObj_t * pObj;
    Vec_Int_t * vOccurs;
    int nOccurs, nOccursMax, nOccursAll;
    int i, k, nSizeMax, Counter = 0;
    // determine the largest fanin and fanout
    nOccursMax = nOccursAll = 0;
598
    If_DsdVecForEachNode( &p->vObjs, pObj, i )
599 600 601 602 603 604 605 606 607
    {
        nOccurs = pObj->Count;
        nOccursAll += nOccurs;
        nOccursMax  = Abc_MaxInt( nOccursMax, nOccurs );
    }
    // allocate storage for fanin/fanout numbers
    nSizeMax = 10 * (Abc_Base10Log(nOccursMax) + 1);
    vOccurs  = Vec_IntStart( nSizeMax );
    // count the number of fanins and fanouts
608
    If_DsdVecForEachNode( &p->vObjs, pObj, i )
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
    {
        nOccurs = pObj->Count;
        if ( nOccurs < 10 )
            Vec_IntAddToEntry( vOccurs, nOccurs, 1 );
        else if ( nOccurs < 100 )
            Vec_IntAddToEntry( vOccurs, 10 + nOccurs/10, 1 );
        else if ( nOccurs < 1000 )
            Vec_IntAddToEntry( vOccurs, 20 + nOccurs/100, 1 );
        else if ( nOccurs < 10000 )
            Vec_IntAddToEntry( vOccurs, 30 + nOccurs/1000, 1 );
        else if ( nOccurs < 100000 )
            Vec_IntAddToEntry( vOccurs, 40 + nOccurs/10000, 1 );
        else if ( nOccurs < 1000000 )
            Vec_IntAddToEntry( vOccurs, 50 + nOccurs/100000, 1 );
        else if ( nOccurs < 10000000 )
            Vec_IntAddToEntry( vOccurs, 60 + nOccurs/1000000, 1 );
    }
    fprintf( pFile, "The distribution of object occurrences:\n" );
    for ( k = 0; k < nSizeMax; k++ )
    {
        if ( Vec_IntEntry(vOccurs, k) == 0 )
            continue;
        if ( k < 10 )
            fprintf( pFile, "%15d : ", k );
        else
        {
            sprintf( Buffer, "%d - %d", (int)pow((double)10, k/10) * (k%10), (int)pow((double)10, k/10) * (k%10+1) - 1 );
            fprintf( pFile, "%15s : ", Buffer );
        }
        fprintf( pFile, "%12d   ", Vec_IntEntry(vOccurs, k) );
        Counter += Vec_IntEntry(vOccurs, k);
640
        fprintf( pFile, "(%6.2f %%)", 100.0*Counter/Vec_PtrSize(&p->vObjs) );
641 642 643
        fprintf( pFile, "\n" );
    }
    Vec_IntFree( vOccurs );
644
    fprintf( pFile, "Fanins: Max = %d. Ave = %.2f.\n", nOccursMax,  1.0*nOccursAll/Vec_PtrSize(&p->vObjs) );
645 646
}

647 648
void If_DsdManPrintDistrib( If_DsdMan_t * p )
{
649 650 651 652 653 654 655 656
    If_DsdObj_t * pObj; int i;
    int CountObj[IF_MAX_FUNC_LUTSIZE+2] = {0};
    int CountObjNon[IF_MAX_FUNC_LUTSIZE+2] = {0};
    int CountObjNpn[IF_MAX_FUNC_LUTSIZE+2] = {0};
    int CountStr[IF_MAX_FUNC_LUTSIZE+2] = {0};
    int CountStrNon[IF_MAX_FUNC_LUTSIZE+2] = {0};
    int CountMarked[IF_MAX_FUNC_LUTSIZE+2] = {0};
    for ( i = 3; i <= p->nVars; i++ )
657
    {
658 659
        CountObjNpn[i] = Vec_MemEntryNum(p->vTtMem[i]);
        CountObjNpn[p->nVars+1] += Vec_MemEntryNum(p->vTtMem[i]);
660
    }
661
    If_DsdVecForEachObj( &p->vObjs, pObj, i )
662
    {
663 664 665 666 667 668
        CountObj[If_DsdObjFaninNum(pObj)]++,        CountObj[p->nVars+1]++;
        if ( If_DsdObjType(pObj) == IF_DSD_PRIME )
            CountObjNon[If_DsdObjFaninNum(pObj)]++, CountObjNon[p->nVars+1]++;
        CountStr[If_DsdObjSuppSize(pObj)]++,        CountStr[p->nVars+1]++;
        if ( If_DsdManCheckNonDec_rec(p, i) )
            CountStrNon[If_DsdObjSuppSize(pObj)]++, CountStrNon[p->nVars+1]++;
669
        if ( If_DsdVecObjMark(&p->vObjs, i) )
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697
            CountMarked[If_DsdObjSuppSize(pObj)]++, CountMarked[p->nVars+1]++;
    }
    printf( "***** DSD MANAGER STATISTICS *****\n" );
    printf( "Support     " );
    printf( "Obj   " );
    printf( "ObjNDSD            " );
    printf( "NPNNDSD                  " );
    printf( "Str   " );
    printf( "StrNDSD             " );
    printf( "Marked  " );
    printf( "\n" );
    for ( i = 0; i <= p->nVars + 1; i++ )
    {
        if ( i == p->nVars + 1 )
            printf( "All : " );
        else
            printf( "%3d : ", i );
        printf( "%9d ", CountObj[i] );
        printf( "%9d ", CountObjNon[i] );
        printf( "%6.2f %% ", 100.0 * CountObjNon[i] / Abc_MaxInt(1, CountObj[i]) );
        printf( "%9d ", CountObjNpn[i] );
        printf( "%6.2f %% ", 100.0 * CountObjNpn[i] / Abc_MaxInt(1, CountObj[i]) );
        printf( "  " );
        printf( "%9d ", CountStr[i] );
        printf( "%9d ", CountStrNon[i] );
        printf( "%6.2f %% ", 100.0 * CountStrNon[i] / Abc_MaxInt(1, CountStr[i]) );
        printf( "%9d ", CountMarked[i] );
        printf( "%6.2f %%",  100.0 * CountMarked[i] / Abc_MaxInt(1, CountStr[i]) );
698 699 700
        printf( "\n" );
    }
}
701
void If_DsdManPrint( If_DsdMan_t * p, char * pFileName, int Number, int Support, int fOccurs, int fTtDump, int fVerbose )
702 703
{
    If_DsdObj_t * pObj;
704
    Vec_Int_t * vStructs, * vCounts;
705 706
    int CountUsed = 0, CountNonDsd = 0, CountNonDsdStr = 0, CountMarked = 0, CountPrime = 0;
    int i, v, * pPerm, DsdMax = 0, MemSizeTTs = 0, MemSizeDecs = 0;
707 708 709 710 711 712 713
    FILE * pFile;
    pFile = pFileName ? fopen( pFileName, "wb" ) : stdout;
    if ( pFileName && pFile == NULL )
    {
        printf( "cannot open output file\n" );
        return;
    }
Alan Mishchenko committed
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731
    if ( fVerbose )
    {
        fprintf( pFile, "*****  NOTATIONS USED BELOW  *****\n" );
        fprintf( pFile, "Support -- the support size\n" );
        fprintf( pFile, "Obj     -- the number of nodes in the DSD manager for each support size\n" );
        fprintf( pFile, "           (the constant node and the primary input node have no support)\n" );
        fprintf( pFile, "ObjNDSD -- the number of prime nodes (that is, nodes whose function has no DSD)\n" );
        fprintf( pFile, "           (percentage is relative to the number of all nodes of that size)\n" );
        fprintf( pFile, "NPNNDSD -- the number of different NPN classes of prime nodes\n" );
        fprintf( pFile, "           (Each NPN class may appear more than once. For example: F1 = 17(ab(cd))\n" ); 
        fprintf( pFile, "           and F2 = 17(ab[cd]) both have prime majority node (hex TT is 17),\n" ); 
        fprintf( pFile, "           but in one case the majority node is fed by AND, and in another by XOR.\n" );
        fprintf( pFile, "           These two majority nodes are different nodes in the DSD manager\n" );
        fprintf( pFile, "Str     -- the number of structures for each support size\n" );
        fprintf( pFile, "           (each structure is composed of one or more nodes)\n" );
        fprintf( pFile, "StrNDSD -- the number of DSD structures containing at least one prime node\n" );
        fprintf( pFile, "Marked  -- the number of DSD structures matchable with the LUT structure (say, \"44\")\n" );
    }
732
    If_DsdVecForEachObj( &p->vObjs, pObj, i )
733
    {
734 735
        if ( If_DsdObjType(pObj) == IF_DSD_PRIME )
            DsdMax = Abc_MaxInt( DsdMax, pObj->nFans ); 
736
        CountPrime += If_DsdObjType(pObj) == IF_DSD_PRIME;
737
        CountNonDsdStr += If_DsdManCheckNonDec_rec( p, pObj->Id );
738 739
        CountUsed += ( If_DsdVecObjRef(&p->vObjs, pObj->Id) > 0 );
        CountMarked += If_DsdVecObjMark( &p->vObjs, i );
740
    }
741 742 743 744 745 746 747
    for ( v = 3; v <= p->nVars; v++ )
    {
        CountNonDsd += Vec_MemEntryNum(p->vTtMem[v]);
        MemSizeTTs += Vec_MemEntrySize(p->vTtMem[v]) * Vec_MemEntryNum(p->vTtMem[v]);
        MemSizeDecs += (int)Vec_VecMemoryInt((Vec_Vec_t *)(p->vTtDecs[v]));
    }
    If_DsdManPrintDistrib( p );
748 749
    printf( "Number of inputs = %d.  LUT size = %d.  Marks = %s.  NewAsUseless = %s.  Bookmark = %d.\n", 
        p->nVars, p->LutSize, If_DsdManHasMarks(p)? "yes" : "no", p->fNewAsUseless? "yes" : "no", p->nObjsPrev );
750 751
    if ( p->pCellStr )
        printf( "Symbolic cell description: %s\n", p->pCellStr );
752 753
    if ( p->pTtGia )
    fprintf( pFile, "Non-DSD AIG nodes          = %8d\n", Gia_ManAndNum(p->pTtGia) );
754
    fprintf( pFile, "Unique table misses        = %8d\n", p->nUniqueMisses );
755
    fprintf( pFile, "Unique table hits          = %8d\n", p->nUniqueHits );
756
    fprintf( pFile, "Memory used for objects    = %8.2f MB.\n", 1.0*Mem_FlexReadMemUsage(p->pMem)/(1<<20) );
757 758
    fprintf( pFile, "Memory used for functions  = %8.2f MB.\n", 8.0*(MemSizeTTs+sizeof(int)*Vec_IntCap(&p->vTruths))/(1<<20) );
    fprintf( pFile, "Memory used for hash table = %8.2f MB.\n", 1.0*sizeof(int)*(p->nBins+Vec_IntCap(&p->vNexts))/(1<<20) );
759
    fprintf( pFile, "Memory used for bound sets = %8.2f MB.\n", 1.0*MemSizeDecs/(1<<20) );
760
    fprintf( pFile, "Memory used for array      = %8.2f MB.\n", 1.0*sizeof(void *)*Vec_PtrCap(&p->vObjs)/(1<<20) );
761 762
    if ( p->pTtGia )
    fprintf( pFile, "Memory used for AIG        = %8.2f MB.\n", 8.0*Gia_ManAndNum(p->pTtGia)/(1<<20) );
763 764 765 766 767 768 769 770
    if ( p->timeDsd )
    {
        Abc_PrintTime( 1, "Time DSD   ", p->timeDsd    );
        Abc_PrintTime( 1, "Time canon ", p->timeCanon-p->timeCheck  );
        Abc_PrintTime( 1, "Time check ", p->timeCheck  );
        Abc_PrintTime( 1, "Time check2", p->timeCheck2 );
        Abc_PrintTime( 1, "Time verify", p->timeVerify );
    }
771 772
    if ( fOccurs )
        If_DsdManPrintOccurs( stdout, p );
773
//    If_DsdManHashProfile( p );
774 775 776 777
    if ( fTtDump )
        If_DsdManDumpDsd( p, Support );
    if ( fTtDump )
        If_DsdManDumpAll( p, Support );
778
//    If_DsdManPrintDecs( stdout, p );
779 780
    if ( !fVerbose )
        return;
781 782
    vStructs = Vec_IntAlloc( 1000 );
    vCounts  = Vec_IntAlloc( 1000 );
783
    If_DsdVecForEachObj( &p->vObjs, pObj, i )
784
    {
785 786
        if ( Number && i % Number )
            continue;
787 788
        if ( Support && Support != If_DsdObjSuppSize(pObj) )
            continue;
789 790 791 792 793 794 795 796 797
        Vec_IntPush( vStructs, i );
        Vec_IntPush( vCounts, -(int)pObj->Count );
//        If_DsdManPrintOne( pFile, p, pObj->Id, NULL, 1 );
    }
//    fprintf( pFile, "\n" );
    pPerm = Abc_MergeSortCost( Vec_IntArray(vCounts), Vec_IntSize(vCounts) );
    for ( i = 0; i < Abc_MinInt(Vec_IntSize(vCounts), 20); i++ )
    {
        printf( "%2d : ", i+1 );
798
        pObj = If_DsdVecObj( &p->vObjs, Vec_IntEntry(vStructs, pPerm[i]) );
799
        If_DsdManPrintOne( pFile, p, pObj->Id, NULL, 1 );
800
    }
801 802 803
    ABC_FREE( pPerm );
    Vec_IntFree( vStructs );
    Vec_IntFree( vCounts );
804 805 806
    if ( pFileName )
        fclose( pFile );
}
807 808 809
 
/**Function*************************************************************

810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834
  Synopsis    [Check if the function is non-trivial.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int If_DsdManCheckNonTriv( If_DsdMan_t * p, int Id, int nVars, int iVarMax )
{
    If_DsdObj_t * pObj; int i, iFanin;
    pObj = If_DsdVecObj( &p->vObjs, Id );
    if ( If_DsdObjType(pObj) == IF_DSD_PRIME )
        return 1;
    if ( If_DsdObjFaninNum(pObj) == nVars )
        return 0;
    If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
        if ( Abc_Lit2Var(iFanin) == 1 && i == iVarMax )
            return 0;
    return 1;
}

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

835 836 837 838 839 840 841 842 843
  Synopsis    [Sorting DSD literals.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
844
int If_DsdObjCompare( If_DsdMan_t * pMan, Vec_Ptr_t * p, int iLit0, int iLit1 )
845 846 847 848 849 850 851 852 853 854 855 856 857 858
{
    If_DsdObj_t * p0 = If_DsdVecObj(p, Abc_Lit2Var(iLit0));
    If_DsdObj_t * p1 = If_DsdVecObj(p, Abc_Lit2Var(iLit1));
    int i, Res;
    if ( If_DsdObjType(p0) < If_DsdObjType(p1) )
        return -1;
    if ( If_DsdObjType(p0) > If_DsdObjType(p1) )
        return 1;
    if ( If_DsdObjType(p0) < IF_DSD_AND )
        return 0;
    if ( If_DsdObjFaninNum(p0) < If_DsdObjFaninNum(p1) )
        return -1;
    if ( If_DsdObjFaninNum(p0) > If_DsdObjFaninNum(p1) )
        return 1;
859 860
    if ( If_DsdObjType(p0) == IF_DSD_PRIME )
    {
861
        if ( If_DsdObjTruthId(pMan, p0) < If_DsdObjTruthId(pMan, p1) )
862
            return -1;
863
        if ( If_DsdObjTruthId(pMan, p0) > If_DsdObjTruthId(pMan, p1) )
864 865
            return 1;
    }
866 867
    for ( i = 0; i < If_DsdObjFaninNum(p0); i++ )
    {
868
        Res = If_DsdObjCompare( pMan, p, If_DsdObjFaninLit(p0, i), If_DsdObjFaninLit(p1, i) );
869 870 871 872
        if ( Res != 0 )
            return Res;
    }
    if ( Abc_LitIsCompl(iLit0) > Abc_LitIsCompl(iLit1) )
873 874
        return -1;
    if ( Abc_LitIsCompl(iLit0) < Abc_LitIsCompl(iLit1) )
875
        return 1;
876
    assert( iLit0 == iLit1 );
877 878
    return 0;
}
879
void If_DsdObjSort( If_DsdMan_t * pMan, Vec_Ptr_t * p, int * pLits, int nLits, int * pPerm )
880 881 882 883 884 885
{
    int i, j, best_i;
    for ( i = 0; i < nLits-1; i++ )
    {
        best_i = i;
        for ( j = i+1; j < nLits; j++ )
886
            if ( If_DsdObjCompare(pMan, p, pLits[best_i], pLits[j]) == 1 )
887 888 889 890 891 892 893 894
                best_i = j;
        if ( i == best_i )
            continue;
        ABC_SWAP( int, pLits[i], pLits[best_i] );
        if ( pPerm )
            ABC_SWAP( int, pPerm[i], pPerm[best_i] );
    }
}
895 896 897

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

898 899 900 901 902 903 904 905 906 907 908
  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline unsigned If_DsdObjHashKey( If_DsdMan_t * p, int Type, int * pLits, int nLits, int truthId )
{
909 910 911
    static int s_Primes[24] = { 1049, 1297, 1559, 1823, 2089, 2371, 2663, 2909, 
                                3221, 3517, 3779, 4073, 4363, 4663, 4973, 5281, 
                                5573, 5861, 6199, 6481, 6803, 7109, 7477, 7727 };
912 913 914
    int i;
    unsigned uHash = Type * 7873 + nLits * 8147;
    for ( i = 0; i < nLits; i++ )
915
        uHash += pLits[i] * s_Primes[i & 0xF];
916
    if ( Type == IF_DSD_PRIME )
917
        uHash += truthId * s_Primes[i & 0xF];
918 919 920 921 922 923
    return uHash % p->nBins;
}
unsigned * If_DsdObjHashLookup( If_DsdMan_t * p, int Type, int * pLits, int nLits, int truthId )
{
    If_DsdObj_t * pObj;
    unsigned * pSpot = p->pBins + If_DsdObjHashKey(p, Type, pLits, nLits, truthId);
924
    for ( ; *pSpot; pSpot = (unsigned *)Vec_IntEntryP(&p->vNexts, pObj->Id) )
925
    {
926
        pObj = If_DsdVecObj( &p->vObjs, *pSpot );
927 928 929
        if ( If_DsdObjType(pObj) == Type && 
             If_DsdObjFaninNum(pObj) == nLits && 
             !memcmp(pObj->pFans, pLits, sizeof(int)*If_DsdObjFaninNum(pObj)) &&
930
             truthId == If_DsdObjTruthId(p, pObj) )
931 932 933 934 935 936 937 938
        {
            p->nUniqueHits++;
            return pSpot;
        }
    }
    p->nUniqueMisses++;
    return pSpot;
}
939 940 941 942 943 944 945 946
static void If_DsdObjHashResize( If_DsdMan_t * p )
{
    If_DsdObj_t * pObj;
    unsigned * pSpot;
    int i, Prev = p->nUniqueMisses;
    p->nBins = Abc_PrimeCudd( 2 * p->nBins );
    p->pBins = ABC_REALLOC( unsigned, p->pBins, p->nBins );
    memset( p->pBins, 0, sizeof(unsigned) * p->nBins );
947 948
    Vec_IntFill( &p->vNexts, Vec_PtrSize(&p->vObjs), 0 );
    If_DsdVecForEachNode( &p->vObjs, pObj, i )
949
    {
950
        pSpot = If_DsdObjHashLookup( p, pObj->Type, (int *)pObj->pFans, pObj->nFans, If_DsdObjTruthId(p, pObj) );
951 952 953
        assert( *pSpot == 0 );
        *pSpot = pObj->Id;
    }
954
    assert( p->nUniqueMisses - Prev == Vec_PtrSize(&p->vObjs) - 2 );
955 956 957
    p->nUniqueMisses = Prev;
}

958 959 960 961 962 963
int If_DsdObjCreate( If_DsdMan_t * p, int Type, int * pLits, int nLits, int truthId )
{
    If_DsdObj_t * pObj, * pFanin;
    int i, iPrev = -1;
    // check structural canonicity
    assert( Type != DAU_DSD_MUX || nLits == 3 );
964
//    assert( Type != DAU_DSD_MUX || !Abc_LitIsCompl(pLits[0]) );
965 966 967 968 969 970
    assert( Type != DAU_DSD_MUX || !Abc_LitIsCompl(pLits[1]) || !Abc_LitIsCompl(pLits[2]) );
    // check that leaves are in good order
    if ( Type == DAU_DSD_AND || Type == DAU_DSD_XOR )
    {
        for ( i = 0; i < nLits; i++ )
        {
971
            pFanin = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(pLits[i]) );
972 973
            assert( Type != DAU_DSD_AND || Abc_LitIsCompl(pLits[i]) || If_DsdObjType(pFanin) != DAU_DSD_AND );
            assert( Type != DAU_DSD_XOR || If_DsdObjType(pFanin) != DAU_DSD_XOR );
974
            assert( iPrev == -1 || If_DsdObjCompare(p, &p->vObjs, iPrev, pLits[i]) <= 0 );
975 976 977 978 979 980 981 982 983 984 985
            iPrev = pLits[i];
        }
    }
    // create new node
    pObj = If_DsdObjAlloc( p, Type, nLits );
    if ( Type == DAU_DSD_PRIME )
        If_DsdObjSetTruth( p, pObj, truthId );
    assert( pObj->nSupp == 0 );
    for ( i = 0; i < nLits; i++ )
    {
        pObj->pFans[i] = pLits[i];
986
        pObj->nSupp += If_DsdVecLitSuppSize(&p->vObjs, pLits[i]);
987 988
    }
    // check decomposability
989
    if ( p->LutSize && !If_DsdManCheckXY(p, Abc_Var2Lit(pObj->Id, 0), p->LutSize, 0, 0, 0, 0) )
990
        If_DsdVecObjSetMark( &p->vObjs, pObj->Id );
991 992
    return pObj->Id;
}
993 994
int If_DsdObjFindOrAdd( If_DsdMan_t * p, int Type, int * pLits, int nLits, word * pTruth )
{
995
    int PrevSize       = (Type == IF_DSD_PRIME) ? Vec_MemEntryNum( p->vTtMem[nLits] ) : -1;   
996
    int objId, truthId = (Type == IF_DSD_PRIME) ? Vec_MemHashInsert(p->vTtMem[nLits], pTruth) : -1;
997
    unsigned * pSpot = If_DsdObjHashLookup( p, Type, pLits, nLits, truthId );
998
//abctime clk;
999
    if ( *pSpot )
1000
        return (int)*pSpot;
1001
//clk = Abc_Clock();
1002
    if ( p->LutSize && truthId >= 0 && truthId == Vec_PtrSize(p->vTtDecs[nLits]) )
1003
    {
1004
        Vec_Int_t * vSets = Dau_DecFindSets_int( pTruth, nLits, p->pSched );
1005 1006
        assert( truthId == Vec_MemEntryNum(p->vTtMem[nLits])-1 );
        Vec_PtrPush( p->vTtDecs[nLits], vSets );
1007 1008
//        Dau_DecPrintSets( vSets, nLits );
    }
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
    if ( p->vIsops[nLits] && truthId >= 0 && PrevSize != Vec_MemEntryNum(p->vTtMem[nLits]) )
    {
        Vec_Int_t * vLevel = Vec_WecPushLevel( p->vIsops[nLits] );
        int fCompl = Kit_TruthIsop( (unsigned *)pTruth, nLits, p->vCover, 1 );
        if ( fCompl >= 0 && Vec_IntSize(p->vCover) <= 8 )
        {
            Vec_IntGrow( vLevel, Vec_IntSize(p->vCover) );
            Vec_IntAppend( vLevel, p->vCover );
            if ( fCompl )
                vLevel->nCap ^= (1<<16); // hack to remember complemented attribute
        }
        assert( Vec_WecSize(p->vIsops[nLits]) == Vec_MemEntryNum(p->vTtMem[nLits]) );
    }
1022 1023
    if ( p->pTtGia && truthId >= 0 && truthId == Vec_MemEntryNum(p->vTtMem[nLits])-1 )
    {
1024
//        int nObjOld = Gia_ManAndNum(p->pTtGia);
1025 1026 1027 1028
        int Lit = Kit_TruthToGia( p->pTtGia, (unsigned *)pTruth, nLits, p->vCover, NULL, 1 );
//        printf( "%d ", Gia_ManAndNum(p->pTtGia)-nObjOld );
        Gia_ManAppendCo( p->pTtGia, Lit );
    }
1029
//p->timeCheck += Abc_Clock() - clk;
1030
    *pSpot = Vec_PtrSize( &p->vObjs );
1031
    objId = If_DsdObjCreate( p, Type, pLits, nLits, truthId );
1032
    if ( Vec_PtrSize(&p->vObjs) > p->nBins )
1033 1034
        If_DsdObjHashResize( p );
    return objId;
1035 1036 1037 1038 1039
}


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

1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053
  Synopsis    [Saving/loading DSD manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void If_DsdManSave( If_DsdMan_t * p, char * pFileName )
{
    If_DsdObj_t * pObj; 
    Vec_Int_t * vSets;
    word * pTruth; 
1054
    int i, v, Num;
1055 1056 1057 1058 1059 1060
    FILE * pFile = fopen( pFileName ? pFileName : p->pStore, "wb" );
    if ( pFile == NULL )
    {
        printf( "Writing DSD manager file \"%s\" has failed.\n", pFileName ? pFileName : p->pStore );
        return;
    }
1061
    fwrite( DSD_VERSION, 4, 1, pFile );
1062 1063 1064 1065
    Num = p->nVars;
    fwrite( &Num, 4, 1, pFile );
    Num = p->LutSize;
    fwrite( &Num, 4, 1, pFile );
1066
    Num = Vec_PtrSize(&p->vObjs);
1067
    fwrite( &Num, 4, 1, pFile );
1068
    Vec_PtrForEachEntryStart( If_DsdObj_t *, &p->vObjs, pObj, i, 2 )
1069
    {
1070
        Num = If_DsdObjWordNum( pObj->nFans );
1071 1072
        fwrite( &Num, 4, 1, pFile );
        fwrite( pObj, sizeof(word)*Num, 1, pFile );
1073
        if ( pObj->Type == IF_DSD_PRIME )
1074
            fwrite( Vec_IntEntryP(&p->vTruths, i), 4, 1, pFile );
1075
    }
1076
    for ( v = 3; v <= p->nVars; v++ )
1077
    {
1078 1079 1080 1081 1082 1083
        int nBytes = sizeof(word)*Vec_MemEntrySize(p->vTtMem[v]);
        Num = Vec_MemEntryNum(p->vTtMem[v]);
        fwrite( &Num, 4, 1, pFile );
        Vec_MemForEachEntry( p->vTtMem[v], pTruth, i )
            fwrite( pTruth, nBytes, 1, pFile );
        Num = Vec_PtrSize(p->vTtDecs[v]);
1084
        fwrite( &Num, 4, 1, pFile );
1085 1086 1087 1088 1089 1090
        Vec_PtrForEachEntry( Vec_Int_t *, p->vTtDecs[v], vSets, i )
        {
            Num = Vec_IntSize(vSets);
            fwrite( &Num, 4, 1, pFile );
            fwrite( Vec_IntArray(vSets), sizeof(int)*Num, 1, pFile );
        }
1091
    }
1092 1093 1094 1095 1096
    Num = p->nConfigWords;
    fwrite( &Num, 4, 1, pFile );
    Num = p->nTtBits;
    fwrite( &Num, 4, 1, pFile );
    Num = p->vConfigs ? Vec_WrdSize(p->vConfigs) : 0;
1097 1098
    fwrite( &Num, 4, 1, pFile );
    if ( Num )
1099
        fwrite( Vec_WrdArray(p->vConfigs), sizeof(word)*Num, 1, pFile );
1100 1101 1102 1103
    Num = p->pCellStr ? strlen(p->pCellStr) : 0;
    fwrite( &Num, 4, 1, pFile );
    if ( Num )
        fwrite( p->pCellStr, sizeof(char)*Num, 1, pFile );
1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
    fclose( pFile );
}
If_DsdMan_t * If_DsdManLoad( char * pFileName )
{
    If_DsdMan_t * p;
    If_DsdObj_t * pObj; 
    Vec_Int_t * vSets;
    char pBuffer[10];
    unsigned * pSpot;
    word * pTruth;
1114
    int i, v, Num, Num2, RetValue;
1115 1116 1117 1118 1119 1120
    FILE * pFile = fopen( pFileName, "rb" );
    if ( pFile == NULL )
    {
        printf( "Reading DSD manager file \"%s\" has failed.\n", pFileName );
        return NULL;
    }
1121
    RetValue = fread( pBuffer, 4, 1, pFile );
1122
    if ( strncmp(pBuffer, DSD_VERSION, strlen(DSD_VERSION)) )
1123 1124 1125 1126
    {
        printf( "Unrecognized format of file \"%s\".\n", pFileName );
        return NULL;
    }
1127
    RetValue = fread( &Num, 4, 1, pFile );
1128 1129 1130
    p = If_DsdManAlloc( Num, 0 );
    ABC_FREE( p->pStore );
    p->pStore = Abc_UtilStrsav( pFileName );
1131
    RetValue = fread( &Num, 4, 1, pFile );
1132
    p->LutSize = Num;
1133
    p->pSat  = If_ManSatBuildXY( p->LutSize );
1134
    RetValue = fread( &Num, 4, 1, pFile );
1135
    assert( Num >= 2 );
1136 1137 1138
    Vec_PtrFillExtra( &p->vObjs, Num, NULL );
    Vec_IntFill( &p->vNexts, Num, 0 );
    Vec_IntFill( &p->vTruths, Num, -1 );
1139 1140 1141
    p->nBins = Abc_PrimeCudd( 2*Num );
    p->pBins = ABC_REALLOC( unsigned, p->pBins, p->nBins );
    memset( p->pBins, 0, sizeof(unsigned) * p->nBins );
1142
    for ( i = 2; i < Vec_PtrSize(&p->vObjs); i++ )
1143
    {
1144
        RetValue = fread( &Num, 4, 1, pFile );
1145
        pObj = (If_DsdObj_t *)Mem_FlexEntryFetch( p->pMem, sizeof(word) * Num );
1146
        RetValue = fread( pObj, sizeof(word)*Num, 1, pFile );
1147
        Vec_PtrWriteEntry( &p->vObjs, i, pObj );
1148 1149 1150
        if ( pObj->Type == IF_DSD_PRIME )
        {
            RetValue = fread( &Num, 4, 1, pFile );
1151
            Vec_IntWriteEntry( &p->vTruths, i, Num );
1152 1153
        }
        pSpot = If_DsdObjHashLookup( p, pObj->Type, (int *)pObj->pFans, pObj->nFans, If_DsdObjTruthId(p, pObj) );
1154 1155 1156
        assert( *pSpot == 0 );
        *pSpot = pObj->Id;
    }
1157
    assert( p->nUniqueMisses == Vec_PtrSize(&p->vObjs) - 2 );
1158
    p->nUniqueMisses = 0;
1159
    pTruth = ABC_ALLOC( word, p->nWords );
1160
    for ( v = 3; v <= p->nVars; v++ )
1161
    {
1162
        int nBytes = sizeof(word)*Vec_MemEntrySize(p->vTtMem[v]);
1163
        RetValue = fread( &Num, 4, 1, pFile );
1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
        for ( i = 0; i < Num; i++ )
        {
            RetValue = fread( pTruth, nBytes, 1, pFile );
            Vec_MemHashInsert( p->vTtMem[v], pTruth );
        }
        assert( Num == Vec_MemEntryNum(p->vTtMem[v]) );
        RetValue = fread( &Num2, 4, 1, pFile );
        for ( i = 0; i < Num2; i++ )
        {
            RetValue = fread( &Num, 4, 1, pFile );
            vSets = Vec_IntAlloc( Num );
            RetValue = fread( Vec_IntArray(vSets), sizeof(int)*Num, 1, pFile );
            vSets->nSize = Num;
            Vec_PtrPush( p->vTtDecs[v], vSets );
        }
        assert( Num2 == Vec_PtrSize(p->vTtDecs[v]) ); 
1180
    }
1181
    ABC_FREE( pTruth );
1182
    RetValue = fread( &Num, 4, 1, pFile );
1183 1184 1185 1186
    p->nConfigWords = Num;
    RetValue = fread( &Num, 4, 1, pFile );
    p->nTtBits = Num;
    RetValue = fread( &Num, 4, 1, pFile );
1187
    if ( RetValue && Num )
1188
    {
1189 1190
        p->vConfigs = Vec_WrdStart( Num );
        RetValue = fread( Vec_WrdArray(p->vConfigs), sizeof(word)*Num, 1, pFile );
1191 1192
    }
    RetValue = fread( &Num, 4, 1, pFile );
1193
    if ( RetValue && Num )
1194 1195 1196 1197
    {
        p->pCellStr = ABC_CALLOC( char, Num + 1 );
        RetValue = fread( p->pCellStr, sizeof(char)*Num, 1, pFile );
    }
1198 1199 1200
    fclose( pFile );
    return p;
}
1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216
void If_DsdManMerge( If_DsdMan_t * p, If_DsdMan_t * pNew )
{
    If_DsdObj_t * pObj; 
    Vec_Int_t * vMap;
    int pFanins[DAU_MAX_VAR];
    int i, k, iFanin, Id;
    if ( p->nVars < pNew->nVars )
    {
        printf( "The number of variables should be the same or smaller.\n" );
        return;
    }
    if ( p->LutSize != pNew->LutSize )
    {
        printf( "LUT size should be the same.\n" );
        return;
    }
1217 1218
    assert( p->nTtBits == pNew->nTtBits );
    assert( p->nConfigWords == pNew->nConfigWords );
Alan Mishchenko committed
1219 1220 1221
    if ( If_DsdManHasMarks(p) != If_DsdManHasMarks(pNew) )
        printf( "Warning! Old manager has %smarks while new manager has %smarks.\n", 
            If_DsdManHasMarks(p) ? "" : "no ", If_DsdManHasMarks(pNew) ? "" : "no " );
1222
    vMap = Vec_IntAlloc( Vec_PtrSize(&pNew->vObjs) );
1223 1224
    Vec_IntPush( vMap, 0 );
    Vec_IntPush( vMap, 1 );
1225 1226
    if ( p->vConfigs && pNew->vConfigs )
        Vec_WrdFillExtra( p->vConfigs, p->nConfigWords * (Vec_PtrSize(&p->vObjs) + Vec_PtrSize(&pNew->vObjs)), 0 );
1227
    If_DsdVecForEachNode( &pNew->vObjs, pObj, i )
1228
    {
1229
        If_DsdObjForEachFaninLit( &pNew->vObjs, pObj, iFanin, k )
1230 1231
            pFanins[k] = Abc_Lit2LitV( Vec_IntArray(vMap), iFanin );
        Id = If_DsdObjFindOrAdd( p, pObj->Type, pFanins, pObj->nFans, pObj->Type == IF_DSD_PRIME ? If_DsdObjTruth(pNew, pObj) : NULL );
Alan Mishchenko committed
1232 1233
        if ( pObj->fMark )
            If_DsdVecObjSetMark( &p->vObjs, Id );
1234 1235 1236 1237 1238 1239 1240
        if ( p->vConfigs && pNew->vConfigs && p->nConfigWords * i < Vec_WrdSize(pNew->vConfigs) )
        {
            //Vec_WrdFillExtra( p->vConfigs, Id, Vec_WrdEntry(pNew->vConfigs, i) );
            word * pConfigNew = Vec_WrdEntryP(pNew->vConfigs, p->nConfigWords * i);
            word * pConfigOld = Vec_WrdEntryP(p->vConfigs, p->nConfigWords * Id);
            memcpy( pConfigOld, pConfigNew, sizeof(word) * p->nConfigWords );
        }
1241 1242
        Vec_IntPush( vMap, Id );
    }
1243
    assert( Vec_IntSize(vMap) == Vec_PtrSize(&pNew->vObjs) );
1244
    Vec_IntFree( vMap );
1245 1246
    if ( p->vConfigs && pNew->vConfigs )
        Vec_WrdShrink( p->vConfigs, p->nConfigWords * Vec_PtrSize(&p->vObjs) );
1247
}
1248
void If_DsdManCleanOccur( If_DsdMan_t * p, int fVerbose )
1249 1250 1251
{
    If_DsdObj_t * pObj; 
    int i;
1252
    If_DsdVecForEachObj( &p->vObjs, pObj, i )
1253 1254
        pObj->Count = 0;
}
1255 1256 1257 1258
void If_DsdManCleanMarks( If_DsdMan_t * p, int fVerbose )
{
    If_DsdObj_t * pObj; 
    int i;
1259
    ABC_FREE( p->pCellStr );
1260
    Vec_WrdFreeP( &p->vConfigs );
1261 1262 1263
    If_DsdVecForEachObj( &p->vObjs, pObj, i )
        pObj->fMark = 0;
}
1264 1265 1266 1267 1268
void If_DsdManInvertMarks( If_DsdMan_t * p, int fVerbose )
{
    If_DsdObj_t * pObj; 
    int i;
    ABC_FREE( p->pCellStr );
1269
    //Vec_WrdFreeP( &p->vConfigs );
1270 1271 1272
    If_DsdVecForEachObj( &p->vObjs, pObj, i )
        pObj->fMark = !pObj->fMark;
}
Alan Mishchenko committed
1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308
void If_DsdManFilter_rec( If_DsdMan_t * pNew, If_DsdMan_t * p, int i, Vec_Int_t * vMap )
{
    If_DsdObj_t * pObj;
    int pFanins[DAU_MAX_VAR];
    int k, iFanin, Id;
    if ( Vec_IntEntry(vMap, i) >= 0 )
        return;
    // call recursively
    pObj = If_DsdVecObj( &p->vObjs, i );
    If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, k )
        If_DsdManFilter_rec( pNew, p, Abc_Lit2Var(iFanin), vMap );
    // duplicate this one
    If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, k )
        pFanins[k] = Abc_Lit2LitV( Vec_IntArray(vMap), iFanin );
    Id = If_DsdObjFindOrAdd( pNew, pObj->Type, pFanins, pObj->nFans, pObj->Type == IF_DSD_PRIME ? If_DsdObjTruth(p, pObj) : NULL );
    if ( pObj->fMark )
        If_DsdVecObjSetMark( &pNew->vObjs, Id );
    If_DsdVecObj( &pNew->vObjs, Id )->Count = pObj->Count;
    // save the result
    Vec_IntWriteEntry( vMap, i, Id );
}
If_DsdMan_t * If_DsdManFilter( If_DsdMan_t * p, int Limit )
{
    If_DsdMan_t * pNew = If_DsdManAlloc( p->nVars, p->LutSize );
    If_DsdObj_t * pObj; 
    Vec_Int_t * vMap;
    int i;
    vMap = Vec_IntStartFull( Vec_PtrSize(&p->vObjs) );
    Vec_IntWriteEntry( vMap, 0, 0 );
    Vec_IntWriteEntry( vMap, 1, 1 );
    If_DsdVecForEachNode( &p->vObjs, pObj, i )
        if ( (int)pObj->Count >= Limit )
            If_DsdManFilter_rec( pNew, p, i, vMap );
    Vec_IntFree( vMap );
    return pNew;
}
1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320

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

  Synopsis    [Collect nodes of the tree.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
1321
void If_DsdManCollect_rec( If_DsdMan_t * p, int Id, Vec_Int_t * vNodes, Vec_Int_t * vFirsts, int * pnSupp )
1322
{
1323
    int i, iFanin, iFirst;
1324
    If_DsdObj_t * pObj = If_DsdVecObj( &p->vObjs, Id );
1325 1326 1327 1328 1329
    if ( If_DsdObjType(pObj) == IF_DSD_CONST0 )
        return;
    if ( If_DsdObjType(pObj) == IF_DSD_VAR )
    {
        (*pnSupp)++;
1330
        return;
1331 1332
    }
    iFirst = *pnSupp;
1333
    If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
1334
        If_DsdManCollect_rec( p, Abc_Lit2Var(iFanin), vNodes, vFirsts, pnSupp );
1335
    Vec_IntPush( vNodes, Id );
1336
    Vec_IntPush( vFirsts, iFirst );
1337
}
1338
void If_DsdManCollect( If_DsdMan_t * p, int Id, Vec_Int_t * vNodes, Vec_Int_t * vFirsts )
1339
{
1340
    int nSupp = 0;
1341
    Vec_IntClear( vNodes );
1342 1343
    Vec_IntClear( vFirsts );
    If_DsdManCollect_rec( p, Id, vNodes, vFirsts, &nSupp );
1344 1345 1346 1347
}

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

1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359
  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void If_DsdManComputeTruth_rec( If_DsdMan_t * p, int iDsd, word * pRes, unsigned char * pPermLits, int * pnSupp )
{
    int i, iFanin, fCompl = Abc_LitIsCompl(iDsd);
1360
    If_DsdObj_t * pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iDsd) );
1361 1362
    if ( If_DsdObjType(pObj) == IF_DSD_VAR )
    {
1363 1364
        int iPermLit = pPermLits ? (int)pPermLits[*pnSupp] : Abc_Var2Lit(*pnSupp, 0);
        (*pnSupp)++;
1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375
        assert( (*pnSupp) <= p->nVars );
        Abc_TtCopy( pRes, p->pTtElems[Abc_Lit2Var(iPermLit)], p->nWords, fCompl ^ Abc_LitIsCompl(iPermLit) );
        return;
    }
    if ( If_DsdObjType(pObj) == IF_DSD_AND || If_DsdObjType(pObj) == IF_DSD_XOR )
    {
        word pTtTemp[DAU_MAX_WORD];
        if ( If_DsdObjType(pObj) == IF_DSD_AND )
            Abc_TtConst1( pRes, p->nWords );
        else
            Abc_TtConst0( pRes, p->nWords );
1376
        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389
        {
            If_DsdManComputeTruth_rec( p, iFanin, pTtTemp, pPermLits, pnSupp );
            if ( If_DsdObjType(pObj) == IF_DSD_AND )
                Abc_TtAnd( pRes, pRes, pTtTemp, p->nWords, 0 );
            else
                Abc_TtXor( pRes, pRes, pTtTemp, p->nWords, 0 );
        }
        if ( fCompl ) Abc_TtNot( pRes, p->nWords );
        return;
    }
    if ( If_DsdObjType(pObj) == IF_DSD_MUX ) // mux
    {
        word pTtTemp[3][DAU_MAX_WORD];
1390
        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
1391 1392 1393 1394 1395 1396 1397 1398 1399
            If_DsdManComputeTruth_rec( p, iFanin, pTtTemp[i], pPermLits, pnSupp );
        assert( i == 3 );
        Abc_TtMux( pRes, pTtTemp[0], pTtTemp[1], pTtTemp[2], p->nWords );
        if ( fCompl ) Abc_TtNot( pRes, p->nWords );
        return;
    }
    if ( If_DsdObjType(pObj) == IF_DSD_PRIME ) // function
    {
        word pFanins[DAU_MAX_VAR][DAU_MAX_WORD];
1400
        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
1401 1402 1403 1404 1405 1406 1407 1408
            If_DsdManComputeTruth_rec( p, iFanin, pFanins[i], pPermLits, pnSupp );
        Dau_DsdTruthCompose_rec( If_DsdObjTruth(p, pObj), pFanins, pRes, pObj->nFans, p->nWords );
        if ( fCompl ) Abc_TtNot( pRes, p->nWords );
        return;
    }
    assert( 0 );

}
1409
void If_DsdManComputeTruthPtr( If_DsdMan_t * p, int iDsd, unsigned char * pPermLits, word * pRes )
1410 1411
{
    int nSupp = 0;
1412
    If_DsdObj_t * pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iDsd) );
1413 1414 1415 1416 1417 1418
    if ( iDsd == 0 )
        Abc_TtConst0( pRes, p->nWords );
    else if ( iDsd == 1 )
        Abc_TtConst1( pRes, p->nWords );
    else if ( pObj->Type == IF_DSD_VAR )
    {
1419 1420
        int iPermLit = pPermLits ? (int)pPermLits[nSupp] : Abc_Var2Lit(nSupp, 0);
        nSupp++;
1421 1422 1423 1424
        Abc_TtCopy( pRes, p->pTtElems[Abc_Lit2Var(iPermLit)], p->nWords, Abc_LitIsCompl(iDsd) ^ Abc_LitIsCompl(iPermLit) );
    }
    else
        If_DsdManComputeTruth_rec( p, iDsd, pRes, pPermLits, &nSupp );
1425
    assert( nSupp == If_DsdVecLitSuppSize(&p->vObjs, iDsd) );
1426 1427 1428 1429 1430
}
word * If_DsdManComputeTruth( If_DsdMan_t * p, int iDsd, unsigned char * pPermLits )
{
    word * pRes = p->pTtElems[DAU_MAX_VAR];
    If_DsdManComputeTruthPtr( p, iDsd, pPermLits, pRes );
1431 1432 1433 1434 1435
    return pRes;
}

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

1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448
  Synopsis    [Procedures to propagate the invertor.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int If_DsdManCheckInv_rec( If_DsdMan_t * p, int iLit )
{
    If_DsdObj_t * pObj;
    int i, iFanin;
1449
    pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iLit) );
1450 1451 1452 1453 1454 1455
    if ( If_DsdObjType(pObj) == IF_DSD_VAR )
        return 1;
    if ( If_DsdObjType(pObj) == IF_DSD_AND || If_DsdObjType(pObj) == IF_DSD_PRIME )
        return 0;
    if ( If_DsdObjType(pObj) == IF_DSD_XOR )
    {
1456
        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469
            if ( If_DsdManCheckInv_rec(p, iFanin) )
                return 1;
        return 0;
    }
    if ( If_DsdObjType(pObj) == IF_DSD_MUX )
        return If_DsdManCheckInv_rec(p, pObj->pFans[1]) && If_DsdManCheckInv_rec(p, pObj->pFans[2]);
    assert( 0 );
    return 0;
}
int If_DsdManPushInv_rec( If_DsdMan_t * p, int iLit, unsigned char * pPerm )
{
    If_DsdObj_t * pObj;
    int i, iFanin;
1470
    pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iLit) );
1471 1472 1473 1474
    if ( If_DsdObjType(pObj) == IF_DSD_VAR )
        pPerm[0] = (unsigned char)Abc_LitNot((int)pPerm[0]);
    else if ( If_DsdObjType(pObj) == IF_DSD_XOR )
    {
1475
        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
1476 1477 1478 1479 1480 1481
        {
            if ( If_DsdManCheckInv_rec(p, iFanin) )
            {
                If_DsdManPushInv_rec( p, iFanin, pPerm );
                break;
            }
1482
            pPerm += If_DsdVecLitSuppSize(&p->vObjs, iFanin);
1483 1484 1485 1486 1487
        }
    }
    else if ( If_DsdObjType(pObj) == IF_DSD_MUX )
    {
        assert( If_DsdManCheckInv_rec(p, pObj->pFans[1]) && If_DsdManCheckInv_rec(p, pObj->pFans[2]) );
1488
        pPerm += If_DsdVecLitSuppSize(&p->vObjs, pObj->pFans[0]);
1489
        If_DsdManPushInv_rec(p, pObj->pFans[1], pPerm);
1490
        pPerm += If_DsdVecLitSuppSize(&p->vObjs, pObj->pFans[1]);
1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504
        If_DsdManPushInv_rec(p, pObj->pFans[2], pPerm);
    }
    else assert( 0 );
    return 1;
}
int If_DsdManPushInv( If_DsdMan_t * p, int iLit, unsigned char * pPerm )
{
    if ( Abc_LitIsCompl(iLit) && If_DsdManCheckInv_rec(p, iLit) )
        return If_DsdManPushInv_rec( p, iLit, pPerm );
    return 0;
}

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

1505 1506 1507 1508 1509 1510 1511 1512 1513
  Synopsis    [Performs DSD operation.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
1514 1515 1516 1517 1518 1519
int If_DsdManComputeFirstArray( If_DsdMan_t * p, int * pLits, int nLits, int * pFirsts )
{
    int i, nSSize = 0;
    for ( i = 0; i < nLits; i++ )
    {
        pFirsts[i] = nSSize;
1520
        nSSize += If_DsdVecLitSuppSize(&p->vObjs, pLits[i]);
1521 1522 1523 1524 1525
    }
    return nSSize;
}
int If_DsdManComputeFirst( If_DsdMan_t * p, If_DsdObj_t * pObj, int * pFirsts )
{
1526
    return If_DsdManComputeFirstArray( p, (int *)pObj->pFans, pObj->nFans, pFirsts );
1527
}
1528 1529 1530
int If_DsdManOperation( If_DsdMan_t * p, int Type, int * pLits, int nLits, unsigned char * pPerm, word * pTruth )
{
    If_DsdObj_t * pObj, * pFanin;
1531
    unsigned char pPermNew[DAU_MAX_VAR], * pPermStart = pPerm;
1532
    int nChildren = 0, pChildren[DAU_MAX_VAR], pBegEnd[DAU_MAX_VAR];
1533 1534
    int i, k, j, Id, iFanin, fCompl = 0, nSSize = 0;
    if ( Type == IF_DSD_AND || Type == IF_DSD_XOR )
1535 1536 1537
    {
        for ( k = 0; k < nLits; k++ )
        {
1538
            if ( Type == IF_DSD_XOR && Abc_LitIsCompl(pLits[k]) )
1539
            {
1540 1541
                pLits[k] = Abc_LitNot(pLits[k]);
                fCompl ^= 1;
1542
            }
1543
            pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(pLits[k]) );
1544
            if ( Type == If_DsdObjType(pObj) && (Type == IF_DSD_XOR || !Abc_LitIsCompl(pLits[k])) )
1545
            {
1546
                If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
1547
                {
1548 1549
                    assert( Type == IF_DSD_AND || !Abc_LitIsCompl(iFanin) );
                    pChildren[nChildren] = iFanin;
1550 1551
                    pBegEnd[nChildren++] = (nSSize << 16) | (nSSize + If_DsdVecLitSuppSize(&p->vObjs, iFanin));
                    nSSize += If_DsdVecLitSuppSize(&p->vObjs, iFanin);
1552 1553 1554
                }
            }
            else
1555
            {
1556 1557 1558
                pChildren[nChildren] = Abc_LitNotCond( pLits[k], If_DsdManPushInv(p, pLits[k], pPermStart) );
                pBegEnd[nChildren++] = (nSSize << 16) | (nSSize + If_DsdObjSuppSize(pObj));
                nSSize += If_DsdObjSuppSize(pObj);
1559
            }
1560
            pPermStart += If_DsdObjSuppSize(pObj);
1561
        }
1562
        If_DsdObjSort( p, &p->vObjs, pChildren, nChildren, pBegEnd );
1563 1564 1565
        // create permutation
        for ( j = i = 0; i < nChildren; i++ )
            for ( k = (pBegEnd[i] >> 16); k < (pBegEnd[i] & 0xFF); k++ )
1566
                pPermNew[j++] = pPerm[k];
1567 1568 1569
        assert( j == nSSize );
        for ( j = 0; j < nSSize; j++ )
            pPerm[j] = pPermNew[j];
1570 1571 1572
    }
    else if ( Type == IF_DSD_MUX )
    {
1573 1574
        int RetValue;
        assert( nLits == 3 );
1575
        for ( k = 0; k < nLits; k++ )
1576
        {
1577
            pFanin = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(pLits[k]) );
1578 1579
            pLits[k] = Abc_LitNotCond( pLits[k], If_DsdManPushInv(p, pLits[k], pPermStart) );
            pPermStart += pFanin->nSupp;
1580
        }
1581
        RetValue = If_DsdObjCompare( p, &p->vObjs, pLits[1], pLits[2] );
1582
        if ( RetValue == 1 || (RetValue == 0 && Abc_LitIsCompl(pLits[0])) )
1583
        {
1584 1585 1586
            int nSupp0 = If_DsdVecLitSuppSize( &p->vObjs, pLits[0] );
            int nSupp1 = If_DsdVecLitSuppSize( &p->vObjs, pLits[1] );
            int nSupp2 = If_DsdVecLitSuppSize( &p->vObjs, pLits[2] );
1587 1588 1589
            pLits[0] = Abc_LitNot(pLits[0]);
            ABC_SWAP( int, pLits[1], pLits[2] );
            for ( j = k = 0; k < nSupp0; k++ )
1590
                pPermNew[j++] = pPerm[k];
1591 1592 1593 1594 1595
            for ( k = 0; k < nSupp2; k++ )
                pPermNew[j++] = pPerm[nSupp0 + nSupp1 + k];
            for ( k = 0; k < nSupp1; k++ )
                pPermNew[j++] = pPerm[nSupp0 + k];
            for ( j = 0; j < nSupp0 + nSupp1 + nSupp2; j++ )
1596 1597
                pPerm[j] = pPermNew[j];
        }
1598
        if ( Abc_LitIsCompl(pLits[1]) )
1599
        {
1600 1601
            pLits[1] = Abc_LitNot(pLits[1]);
            pLits[2] = Abc_LitNot(pLits[2]);
1602 1603
            fCompl ^= 1;
        }
1604 1605 1606
        pPermStart = pPerm;
        for ( k = 0; k < nLits; k++ )
        {
1607
            pFanin = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(pLits[k]) );
1608 1609 1610
            pChildren[nChildren++] = Abc_LitNotCond( pLits[k], If_DsdManPushInv(p, pLits[k], pPermStart) );
            pPermStart += pFanin->nSupp;
        }
1611 1612 1613
    }
    else if ( Type == IF_DSD_PRIME )
    {
1614 1615 1616 1617
        char pCanonPerm[DAU_MAX_VAR];
        int i, uCanonPhase, pFirsts[DAU_MAX_VAR];
        uCanonPhase = Abc_TtCanonicize( pTruth, nLits, pCanonPerm );
        fCompl = ((uCanonPhase >> nLits) & 1);
1618
        nSSize = If_DsdManComputeFirstArray( p, pLits, nLits, pFirsts );
1619 1620 1621
        for ( j = i = 0; i < nLits; i++ )
        {
            int iLitNew = Abc_LitNotCond( pLits[(int)pCanonPerm[i]], ((uCanonPhase>>i)&1) );
1622
            pFanin = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iLitNew) );
1623 1624
            pPermStart = pPerm + pFirsts[(int)pCanonPerm[i]];
            pChildren[nChildren++] = Abc_LitNotCond( iLitNew, If_DsdManPushInv(p, iLitNew, pPermStart) );
1625
            for ( k = 0; k < (int)pFanin->nSupp; k++ )            
1626
                pPermNew[j++] = pPermStart[k];
1627 1628 1629 1630
        }
        assert( j == nSSize );
        for ( j = 0; j < nSSize; j++ )
            pPerm[j] = pPermNew[j];
1631
        Abc_TtStretch6( pTruth, nLits, p->nVars );
1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664
    }
    else assert( 0 );
    // create new graph
    Id = If_DsdObjFindOrAdd( p, Type, pChildren, nChildren, pTruth );
    return Abc_Var2Lit( Id, fCompl );
}

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

  Synopsis    [Creating DSD network from SOP.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline void If_DsdMergeMatches( char * pDsd, int * pMatches )
{
    int pNested[DAU_MAX_VAR];
    int i, nNested = 0;
    for ( i = 0; pDsd[i]; i++ )
    {
        pMatches[i] = 0;
        if ( pDsd[i] == '(' || pDsd[i] == '[' || pDsd[i] == '<' || pDsd[i] == '{' )
            pNested[nNested++] = i;
        else if ( pDsd[i] == ')' || pDsd[i] == ']' || pDsd[i] == '>' || pDsd[i] == '}' )
            pMatches[pNested[--nNested]] = i;
        assert( nNested < DAU_MAX_VAR );
    }
    assert( nNested == 0 );
}
1665
int If_DsdManAddDsd_rec( char * pStr, char ** p, int * pMatches, If_DsdMan_t * pMan, word * pTruth, unsigned char * pPerm, int * pnSupp )
1666
{
1667
    unsigned char * pPermStart = pPerm + *pnSupp;
1668 1669 1670 1671 1672 1673
    int iRes = -1, fCompl = 0;
    if ( **p == '!' )
    {
        fCompl = 1;
        (*p)++;
    }
1674
    if ( **p >= 'a' && **p <= 'z' ) // var
1675
    {
1676 1677
        pPerm[(*pnSupp)++] = Abc_Var2Lit( **p - 'a', fCompl );
        return 2;
1678 1679 1680
    }
    if ( **p == '(' || **p == '[' || **p == '<' || **p == '{' ) // and/or/xor
    {
Alan Mishchenko committed
1681
        int Type = 0, nLits = 0, pLits[DAU_MAX_VAR];
1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693
        char * q = pStr + pMatches[ *p - pStr ];
        if ( **p == '(' )
            Type = DAU_DSD_AND;
        else if ( **p == '[' )
            Type = DAU_DSD_XOR;
        else if ( **p == '<' )
            Type = DAU_DSD_MUX;
        else if ( **p == '{' )
            Type = DAU_DSD_PRIME;
        else assert( 0 );
        assert( *q == **p + 1 + (**p != '(') );
        for ( (*p)++; *p < q; (*p)++ )
1694
            pLits[nLits++] = If_DsdManAddDsd_rec( pStr, p, pMatches, pMan, pTruth, pPerm, pnSupp );
1695
        assert( *p == q );
1696
        iRes = If_DsdManOperation( pMan, Type, pLits, nLits, pPermStart, pTruth );
1697 1698
        return Abc_LitNotCond( iRes, fCompl );
    }
1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714
    if ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') )
    {
        word pFunc[DAU_MAX_WORD];
        int nLits = 0, pLits[DAU_MAX_VAR];
        char * q;
        int i, nVarsF = Abc_TtReadHex( pFunc, *p );
        *p += Abc_TtHexDigitNum( nVarsF );
        q = pStr + pMatches[ *p - pStr ];
        assert( **p == '{' && *q == '}' );
        for ( i = 0, (*p)++; *p < q; (*p)++, i++ )
            pLits[nLits++] = If_DsdManAddDsd_rec( pStr, p, pMatches, pMan, pTruth, pPerm, pnSupp );
        assert( i == nVarsF );
        assert( *p == q );
        iRes = If_DsdManOperation( pMan, DAU_DSD_PRIME, pLits, nLits, pPermStart, pFunc );
        return Abc_LitNotCond( iRes, fCompl );
    }
1715 1716 1717
    assert( 0 );
    return -1;
}
1718
int If_DsdManAddDsd( If_DsdMan_t * p, char * pDsd, word * pTruth, unsigned char * pPerm, int * pnSupp )
1719 1720 1721 1722
{
    int iRes = -1, fCompl = 0;
    if ( *pDsd == '!' )
         pDsd++, fCompl = 1;
1723
    if ( Dau_DsdIsConst0(pDsd) )
1724
        iRes = 0;
1725 1726
    else if ( Dau_DsdIsConst1(pDsd) )
        iRes = 1;
1727
    else if ( Dau_DsdIsVar(pDsd) )
1728 1729 1730 1731
    {
        pPerm[(*pnSupp)++] = Dau_DsdReadVar(pDsd);
        iRes = 2;
    }
1732 1733 1734 1735
    else
    {
        int pMatches[DAU_MAX_STR];
        If_DsdMergeMatches( pDsd, pMatches );
1736
        iRes = If_DsdManAddDsd_rec( pDsd, &pDsd, pMatches, p, pTruth, pPerm, pnSupp );
1737 1738 1739 1740 1741 1742
    }
    return Abc_LitNotCond( iRes, fCompl );
}

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

1743 1744 1745 1746 1747 1748 1749 1750 1751
  Synopsis    [Returns 1 if XY-decomposability holds to this LUT size.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
1752 1753 1754 1755 1756 1757 1758
// create signature of the support of the node
unsigned If_DsdSign_rec( If_DsdMan_t * p, If_DsdObj_t * pObj, int * pnSupp )
{
    unsigned uSign = 0; int i;
    If_DsdObj_t * pFanin;
    if ( If_DsdObjType(pObj) == IF_DSD_VAR )
        return (1 << (2*(*pnSupp)++));
1759
    If_DsdObjForEachFanin( &p->vObjs, pObj, pFanin, i )
1760 1761 1762 1763 1764
        uSign |= If_DsdSign_rec( p, pFanin, pnSupp );
    return uSign;
}
unsigned If_DsdSign( If_DsdMan_t * p, If_DsdObj_t * pObj, int iFan, int iFirst, int fShared )
{
1765
    If_DsdObj_t * pFanin = If_DsdObjFanin( &p->vObjs, pObj, iFan );
1766 1767 1768
    unsigned uSign = If_DsdSign_rec( p, pFanin, &iFirst );
    return fShared ? (uSign << 1) | uSign : uSign;
}
1769 1770 1771 1772
// collect supports of the node
void If_DsdManGetSuppSizes( If_DsdMan_t * p, If_DsdObj_t * pObj, int * pSSizes )
{
    If_DsdObj_t * pFanin; int i;
1773
    If_DsdObjForEachFanin( &p->vObjs, pObj, pFanin, i )
1774 1775 1776
        pSSizes[i] = If_DsdObjSuppSize(pFanin);    
}
// checks if there is a way to package some fanins 
1777
unsigned If_DsdManCheckAndXor( If_DsdMan_t * p, int iFirst, unsigned uMaskNot, If_DsdObj_t * pObj, int nSuppAll, int LutSize, int fDerive, int fVerbose )
1778 1779
{
    int i[6], LimitOut, SizeIn, SizeOut, pSSizes[DAU_MAX_VAR];
1780
    int nFans = If_DsdObjFaninNum(pObj), pFirsts[DAU_MAX_VAR];
1781
    unsigned uRes;
1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793
    assert( pObj->nFans > 2 );
    assert( If_DsdObjSuppSize(pObj) > LutSize );
    If_DsdManGetSuppSizes( p, pObj, pSSizes );
    LimitOut = LutSize - (nSuppAll - pObj->nSupp + 1);
    assert( LimitOut < LutSize );
    for ( i[0] = 0;      i[0] < nFans; i[0]++ )
    for ( i[1] = i[0]+1; i[1] < nFans; i[1]++ )
    {
        SizeIn = pSSizes[i[0]] + pSSizes[i[1]];
        SizeOut = pObj->nSupp - SizeIn;
        if ( SizeIn > LutSize || SizeOut > LimitOut )
            continue;
1794 1795 1796
        if ( !fDerive )
            return ~0;
        If_DsdManComputeFirst( p, pObj, pFirsts );
1797
        uRes = If_DsdSign(p, pObj, i[0], iFirst + pFirsts[i[0]], 0) | 
1798
               If_DsdSign(p, pObj, i[1], iFirst + pFirsts[i[1]], 0);
1799
        if ( uRes & uMaskNot )
1800 1801
            continue;
        return uRes;
1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812
    }
    if ( pObj->nFans == 3 )
        return 0;
    for ( i[0] = 0;      i[0] < nFans; i[0]++ )
    for ( i[1] = i[0]+1; i[1] < nFans; i[1]++ )
    for ( i[2] = i[1]+1; i[2] < nFans; i[2]++ )
    {
        SizeIn = pSSizes[i[0]] + pSSizes[i[1]] + pSSizes[i[2]];
        SizeOut = pObj->nSupp - SizeIn;
        if ( SizeIn > LutSize || SizeOut > LimitOut )
            continue;
1813 1814 1815
        if ( !fDerive )
            return ~0;
        If_DsdManComputeFirst( p, pObj, pFirsts );
1816
        uRes = If_DsdSign(p, pObj, i[0], iFirst + pFirsts[i[0]], 0) | 
1817 1818
               If_DsdSign(p, pObj, i[1], iFirst + pFirsts[i[1]], 0) | 
               If_DsdSign(p, pObj, i[2], iFirst + pFirsts[i[2]], 0);
1819
        if ( uRes & uMaskNot )
1820 1821
            continue;
        return uRes;
1822
    }
1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833
    if ( pObj->nFans == 4 )
        return 0;
    for ( i[0] = 0;      i[0] < nFans; i[0]++ )
    for ( i[1] = i[0]+1; i[1] < nFans; i[1]++ )
    for ( i[2] = i[1]+1; i[2] < nFans; i[2]++ )
    for ( i[3] = i[2]+1; i[3] < nFans; i[3]++ )
    {
        SizeIn = pSSizes[i[0]] + pSSizes[i[1]] + pSSizes[i[2]] + pSSizes[i[3]];
        SizeOut = pObj->nSupp - SizeIn;
        if ( SizeIn > LutSize || SizeOut > LimitOut )
            continue;
1834 1835 1836
        if ( !fDerive )
            return ~0;
        If_DsdManComputeFirst( p, pObj, pFirsts );
1837
        uRes = If_DsdSign(p, pObj, i[0], iFirst + pFirsts[i[0]], 0) | 
1838 1839 1840
               If_DsdSign(p, pObj, i[1], iFirst + pFirsts[i[1]], 0) | 
               If_DsdSign(p, pObj, i[2], iFirst + pFirsts[i[2]], 0) | 
               If_DsdSign(p, pObj, i[3], iFirst + pFirsts[i[3]], 0);
1841
        if ( uRes & uMaskNot )
1842 1843
            continue;
        return uRes;
1844
    }
1845 1846 1847
    return 0;
}
// checks if there is a way to package some fanins 
1848
unsigned If_DsdManCheckMux( If_DsdMan_t * p, int iFirst, unsigned uMaskNot, If_DsdObj_t * pObj, int nSuppAll, int LutSize, int fDerive, int fVerbose )
1849
{
1850
    int LimitOut, SizeIn, SizeOut, pSSizes[DAU_MAX_VAR], pFirsts[DAU_MAX_VAR];
1851
    unsigned uRes;
1852 1853 1854 1855 1856 1857 1858
    assert( If_DsdObjFaninNum(pObj) == 3 );
    assert( If_DsdObjSuppSize(pObj) > LutSize );
    If_DsdManGetSuppSizes( p, pObj, pSSizes );
    LimitOut = LutSize - (nSuppAll - If_DsdObjSuppSize(pObj) + 1);
    assert( LimitOut < LutSize );
    // first input
    SizeIn = pSSizes[0] + pSSizes[1];
1859
    SizeOut = pSSizes[0] + pSSizes[2] + 1;
1860 1861
    if ( SizeIn <= LutSize && SizeOut <= LimitOut )
    {
1862 1863 1864
        if ( !fDerive )
            return ~0;
        If_DsdManComputeFirst( p, pObj, pFirsts );
1865
        uRes = If_DsdSign(p, pObj, 0, iFirst + pFirsts[0], 1) | If_DsdSign(p, pObj, 1, iFirst + pFirsts[1], 0);
1866
        if ( (uRes & uMaskNot) == 0 )
1867
            return uRes;
1868 1869 1870
    }
    // second input
    SizeIn = pSSizes[0] + pSSizes[2];
1871
    SizeOut = pSSizes[0] + pSSizes[1] + 1;
1872 1873
    if ( SizeIn <= LutSize && SizeOut <= LimitOut )
    {
1874 1875 1876
        if ( !fDerive )
            return ~0;
        If_DsdManComputeFirst( p, pObj, pFirsts );
1877
        uRes = If_DsdSign(p, pObj, 0, iFirst + pFirsts[0], 1) | If_DsdSign(p, pObj, 2, iFirst + pFirsts[2], 0);
1878
        if ( (uRes & uMaskNot) == 0 )
1879
            return uRes;
1880 1881 1882 1883
    }
    return 0;
}
// checks if there is a way to package some fanins 
1884
unsigned If_DsdManCheckPrime( If_DsdMan_t * p, int iFirst, unsigned uMaskNot, If_DsdObj_t * pObj, int nSuppAll, int LutSize, int fDerive, int fVerbose )
1885
{
1886
    int i, v, set, LimitOut, SizeIn, SizeOut, pSSizes[DAU_MAX_VAR], pFirsts[DAU_MAX_VAR];
1887
    int truthId = If_DsdObjTruthId(p, pObj);
1888
    int nFans = If_DsdObjFaninNum(pObj);
1889
    Vec_Int_t * vSets = (Vec_Int_t *)Vec_PtrEntry(p->vTtDecs[pObj->nFans], truthId);
1890 1891 1892 1893
if ( fVerbose )
printf( "\n" );
if ( fVerbose )
Dau_DecPrintSets( vSets, nFans );
1894
    assert( If_DsdObjFaninNum(pObj) > 2 );
1895 1896
    assert( If_DsdObjSuppSize(pObj) > LutSize );
    If_DsdManGetSuppSizes( p, pObj, pSSizes );
1897
    LimitOut = LutSize - (nSuppAll - If_DsdObjSuppSize(pObj) + 1);
1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913
    assert( LimitOut < LutSize );
    Vec_IntForEachEntry( vSets, set, i )
    {
        SizeIn = SizeOut = 0;
        for ( v = 0; v < nFans; v++ )
        {
            int Value = ((set >> (v << 1)) & 3);
            if ( Value == 0 )
                SizeOut += pSSizes[v];
            else if ( Value == 1 )
                SizeIn += pSSizes[v];
            else if ( Value == 3 )
            {
                SizeIn += pSSizes[v];
                SizeOut += pSSizes[v];
            }
1914
            else assert( 0 );
1915 1916 1917 1918
            if ( SizeIn > LutSize || SizeOut > LimitOut )
                break;
        }
        if ( v == nFans )
1919
        {
1920
            unsigned uRes = 0;
1921 1922 1923 1924 1925 1926 1927 1928 1929
            if ( !fDerive )
                return ~0;
            If_DsdManComputeFirst( p, pObj, pFirsts );
            for ( v = 0; v < nFans; v++ )
            {
                int Value = ((set >> (v << 1)) & 3);
                if ( Value == 0 )
                {}
                else if ( Value == 1 )
1930
                    uRes |= If_DsdSign(p, pObj, v, iFirst + pFirsts[v], 0);
1931
                else if ( Value == 3 )
1932
                    uRes |= If_DsdSign(p, pObj, v, iFirst + pFirsts[v], 1);
1933
                else assert( 0 );
1934
            }
1935
            if ( uRes & uMaskNot )
1936 1937
                continue;
            return uRes;
1938
        }
1939 1940 1941
    }
    return 0;
}
1942
unsigned If_DsdManCheckXY_int( If_DsdMan_t * p, int iDsd, int LutSize, int fDerive, unsigned uMaskNot, int fVerbose )
1943
{
1944 1945
    If_DsdObj_t * pObj, * pTemp; 
    int i, Mask, iFirst;
1946
    unsigned uRes;
1947
    pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iDsd) );
1948 1949 1950 1951 1952 1953
    if ( fVerbose )
    If_DsdManPrintOne( stdout, p, Abc_Lit2Var(iDsd), NULL, 0 );
    if ( If_DsdObjSuppSize(pObj) <= LutSize )
    {
        if ( fVerbose )
        printf( "    Trivial\n" );
1954
        return ~0;
1955
    }
1956
    If_DsdManCollect( p, pObj->Id, p->vTemp1, p->vTemp2 );
1957
    If_DsdVecForEachObjVec( p->vTemp1, &p->vObjs, pTemp, i )
1958 1959 1960 1961 1962 1963
        if ( If_DsdObjSuppSize(pTemp) <= LutSize && If_DsdObjSuppSize(pObj) - If_DsdObjSuppSize(pTemp) <= LutSize - 1 )
        {
            if ( fVerbose )
            printf( "    Dec using node " );
            if ( fVerbose )
            If_DsdManPrintOne( stdout, p, pTemp->Id, NULL, 1 );
1964
            iFirst = Vec_IntEntry(p->vTemp2, i);
1965 1966 1967 1968
            uRes = If_DsdSign_rec(p, pTemp, &iFirst);
            if ( uRes & uMaskNot )
                continue;
            return uRes;
1969
        }
1970
    If_DsdVecForEachObjVec( p->vTemp1, &p->vObjs, pTemp, i )
1971 1972
        if ( (If_DsdObjType(pTemp) == IF_DSD_AND || If_DsdObjType(pTemp) == IF_DSD_XOR) && If_DsdObjFaninNum(pTemp) > 2 && If_DsdObjSuppSize(pTemp) > LutSize )
        {
1973
            if ( (Mask = If_DsdManCheckAndXor(p, Vec_IntEntry(p->vTemp2, i), uMaskNot, pTemp, If_DsdObjSuppSize(pObj), LutSize, fDerive, fVerbose)) )
1974 1975 1976 1977 1978 1979 1980
            {
                if ( fVerbose )
                printf( "    " );
                if ( fVerbose )
                Abc_TtPrintBinary( (word *)&Mask, 4 ); 
                if ( fVerbose )
                printf( "    Using multi-input AND/XOR node\n" );
1981
                return Mask;
1982 1983
            }
        }
1984
    If_DsdVecForEachObjVec( p->vTemp1, &p->vObjs, pTemp, i )
1985 1986
        if ( If_DsdObjType(pTemp) == IF_DSD_MUX && If_DsdObjSuppSize(pTemp) > LutSize )
        {
1987
            if ( (Mask = If_DsdManCheckMux(p, Vec_IntEntry(p->vTemp2, i), uMaskNot, pTemp, If_DsdObjSuppSize(pObj), LutSize, fDerive, fVerbose)) )
1988 1989 1990 1991 1992 1993 1994
            {
                if ( fVerbose )
                printf( "    " );
                if ( fVerbose )
                Abc_TtPrintBinary( (word *)&Mask, 4 ); 
                if ( fVerbose )
                printf( "    Using multi-input MUX node\n" );
1995
                return Mask;
1996 1997
            }
        }
1998
    If_DsdVecForEachObjVec( p->vTemp1, &p->vObjs, pTemp, i )
1999
        if ( If_DsdObjType(pTemp) == IF_DSD_PRIME && If_DsdObjSuppSize(pTemp) > LutSize )
2000
        {
2001
            if ( (Mask = If_DsdManCheckPrime(p, Vec_IntEntry(p->vTemp2, i), uMaskNot, pTemp, If_DsdObjSuppSize(pObj), LutSize, fDerive, fVerbose)) )
2002 2003 2004 2005 2006 2007 2008
            {
                if ( fVerbose )
                printf( "    " );
                if ( fVerbose )
                Dau_DecPrintSet( Mask, If_DsdObjFaninNum(pTemp), 0 );
                if ( fVerbose )
                printf( "    Using prime node\n" );
2009
                return Mask;
2010 2011 2012 2013
            }
        }
    if ( fVerbose )
    printf( "    UNDEC\n" );
2014
//    If_DsdManPrintOne( stdout, p, Abc_Lit2Var(iDsd), NULL, 1 );
2015 2016
    return 0;
}
2017
unsigned If_DsdManCheckXY( If_DsdMan_t * p, int iDsd, int LutSize, int fDerive, unsigned uMaskNot, int fHighEffort, int fVerbose )
2018
{
2019
    unsigned uSet = If_DsdManCheckXY_int( p, iDsd, LutSize, fDerive, uMaskNot, fVerbose );
2020
    if ( uSet == 0 && fHighEffort )
2021
    {
2022
//        abctime clk = Abc_Clock();
2023
        int nVars = If_DsdVecLitSuppSize( &p->vObjs, iDsd );
2024 2025 2026 2027 2028 2029 2030
        word * pRes = If_DsdManComputeTruth( p, iDsd, NULL );
        uSet = If_ManSatCheckXYall( p->pSat, LutSize, pRes, nVars, p->vTemp1 );
        if ( uSet )
        {
//            If_DsdManPrintOne( stdout, p, Abc_Lit2Var(iDsd), NULL, 1 );
//            Dau_DecPrintSet( uSet, nVars, 1 );
        }
2031
//        p->timeCheck2 += Abc_Clock() - clk;
2032 2033 2034
    }
    return uSet;
}
2035 2036 2037

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

2038 2039 2040 2041 2042 2043 2044 2045 2046
  Synopsis    [Checks existence of decomposition.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
2047
unsigned If_DsdManCheckXYZ( If_DsdMan_t * p, int iDsd, int LutSize, int fDerive, int fVerbose ) 
2048
{
2049
    return ~0;
2050 2051 2052 2053
}

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

2054 2055 2056 2057 2058 2059 2060 2061 2062
  Synopsis    [Add the function to the DSD manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
2063
int If_DsdManCompute( If_DsdMan_t * p, word * pTruth, int nLeaves, unsigned char * pPerm, char * pLutStruct )
2064 2065 2066
{
    word pCopy[DAU_MAX_WORD], * pRes;
    char pDsd[DAU_MAX_STR];
2067
    int iDsd, nSizeNonDec, nSupp = 0;
2068
    int nWords = Abc_TtWordNum(nLeaves);
2069
//    abctime clk = 0;
2070
    assert( nLeaves <= DAU_MAX_VAR );
2071
    Abc_TtCopy( pCopy, pTruth, nWords, 0 );
2072
//clk = Abc_Clock();
2073
    nSizeNonDec = Dau_DsdDecompose( pCopy, nLeaves, 0, 1, pDsd );
2074
//p->timeDsd += Abc_Clock() - clk;
2075 2076
    if ( nSizeNonDec > 0 )
        Abc_TtStretch6( pCopy, nSizeNonDec, p->nVars );
2077
    memset( pPerm, 0xFF, (size_t)nLeaves );
2078
//clk = Abc_Clock();
2079
    iDsd = If_DsdManAddDsd( p, pDsd, pCopy, pPerm, &nSupp );
2080
//p->timeCanon += Abc_Clock() - clk;
2081
    assert( nSupp == nLeaves );
2082
    // verify the result
2083
//clk = Abc_Clock();
2084
    pRes = If_DsdManComputeTruth( p, iDsd, pPerm );
2085
//p->timeVerify += Abc_Clock() - clk;
2086
    if ( !Abc_TtEqual(pRes, pTruth, nWords) )
2087 2088 2089
    {
//        If_DsdManPrint( p, NULL );
        printf( "\n" );
2090
        printf( "Verification failed!\n" );
2091
        printf( "%s\n", pDsd );
2092 2093 2094
        Dau_DsdPrintFromTruth( pTruth, nLeaves );
        Dau_DsdPrintFromTruth( pRes, nLeaves );
        If_DsdManPrintOne( stdout, p, Abc_Lit2Var(iDsd), pPerm, 1 );
2095 2096
        printf( "\n" );
    }
2097
    If_DsdVecObjIncRef( &p->vObjs, Abc_Lit2Var(iDsd) );
2098
    assert( If_DsdVecLitSuppSize(&p->vObjs, iDsd) == nLeaves );
2099
    return iDsd;
2100
}
2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113

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

  Synopsis    [Checks existence of decomposition.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void If_DsdManTest()
2114
{
2115 2116 2117 2118 2119 2120
    Vec_Int_t * vSets;
    word t = 0x5277;
    t = Abc_Tt6Stretch( t, 4 );
//    word t = 0xD9D900D900D900001010001000100000;
    vSets = Dau_DecFindSets( &t, 6 );
    Vec_IntFree( vSets );
2121
}
2122

2123

2124 2125
/**Function*************************************************************

2126
  Synopsis    [Compute pin delays.]
2127 2128 2129 2130 2131 2132 2133 2134

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
2135
int If_CutDsdBalancePinDelays_rec( If_DsdMan_t * p, int Id, int * pTimes, word * pRes, int * pnSupp, int nSuppAll, char * pPermLits )
2136 2137 2138
{
    If_DsdObj_t * pObj = If_DsdVecObj( &p->vObjs, Id );
    if ( If_DsdObjType(pObj) == IF_DSD_VAR )
2139 2140 2141 2142 2143
    {
        int iCutVar = Abc_Lit2Var(pPermLits[(*pnSupp)++]);
        *pRes = If_CutPinDelayInit(iCutVar);
        return pTimes[iCutVar];
    }
2144 2145
    if ( If_DsdObjType(pObj) == IF_DSD_MUX )
    {
2146
        word pFaninRes[3], Res0, Res1;
2147
        int i, iFanin, Delays[3];
2148
        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
2149
            Delays[i] = If_CutDsdBalancePinDelays_rec( p, Abc_Lit2Var(iFanin), pTimes, pFaninRes+i, pnSupp, nSuppAll, pPermLits );
2150 2151 2152
        Res0 = If_CutPinDelayMax( pFaninRes[0], pFaninRes[1], nSuppAll, 1 );
        Res1 = If_CutPinDelayMax( pFaninRes[0], pFaninRes[2], nSuppAll, 1 );
        *pRes = If_CutPinDelayMax( Res0, Res1, nSuppAll, 1 );
2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163
        return 2 + Abc_MaxInt(Delays[0], Abc_MaxInt(Delays[1], Delays[2]));
    }
    if ( If_DsdObjType(pObj) == IF_DSD_PRIME )
    {
        word pFaninRes[IF_MAX_FUNC_LUTSIZE];
        int i, iFanin, Delays[IF_MAX_FUNC_LUTSIZE];
        Vec_Int_t * vCover = Vec_WecEntry( p->vIsops[pObj->nFans], If_DsdObjTruthId(p, pObj) );
        assert( Vec_IntSize(vCover) > 0 );
        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
            Delays[i] = If_CutDsdBalancePinDelays_rec( p, Abc_Lit2Var(iFanin), pTimes, pFaninRes+i, pnSupp, nSuppAll, pPermLits );
        return If_CutSopBalancePinDelaysInt( vCover, Delays, pFaninRes, nSuppAll, pRes );
2164
    }
2165
    assert( If_DsdObjType(pObj) == IF_DSD_AND || If_DsdObjType(pObj) == IF_DSD_XOR );
2166
    {
2167
        word pFaninRes[IF_MAX_FUNC_LUTSIZE];
2168
        int i, iFanin, Delay, Result = 0;
2169
        int fXor = 0;//(If_DsdObjType(pObj) == IF_DSD_XOR);
2170 2171 2172
        int nCounter = 0, pCounter[IF_MAX_FUNC_LUTSIZE];
        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
        {
2173 2174
            Delay = If_CutDsdBalancePinDelays_rec( p, Abc_Lit2Var(iFanin), pTimes, pFaninRes+i, pnSupp, nSuppAll, pPermLits );
            Result = If_LogCounterPinDelays( pCounter, &nCounter, pFaninRes, Delay, pFaninRes[i], nSuppAll, fXor );
2175
        }
2176 2177 2178 2179
        assert( nCounter > 0 );
        if ( fXor )
            Result = If_LogCounterDelayXor( pCounter, nCounter ); // estimation
        *pRes = If_LogPinDelaysMulti( pFaninRes, nCounter, nSuppAll, fXor );
2180 2181 2182
        return Result;
    }
}
2183
int If_CutDsdBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm )
2184
{
2185
    if ( pCut->nLeaves == 0 ) // const
2186
        return 0;
2187 2188 2189 2190 2191
    if ( pCut->nLeaves == 1 ) // variable
    {
        pPerm[0] = 0;
        return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay;
    }
2192 2193
    else
    {
2194 2195 2196 2197
        word Result = 0;
        int i, Delay, nSupp = 0, pTimes[IF_MAX_FUNC_LUTSIZE];
        for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
            pTimes[i] = (int)If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; 
2198
        Delay = If_CutDsdBalancePinDelays_rec( p->pIfDsdMan, Abc_Lit2Var(If_CutDsdLit(p, pCut)), pTimes, &Result, &nSupp, If_CutLeaveNum(pCut), If_CutDsdPerm(p, pCut) );
2199 2200
        assert( nSupp == If_CutLeaveNum(pCut) );
        If_CutPinDelayTranslate( Result, If_CutLeaveNum(pCut), pPerm );
2201 2202
        return Delay;
    }
2203
}
2204 2205 2206 2207


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

2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229
  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int If_CutDsdPermLitMax( char * pPermLits, int nVars, int iVar )
{
    int i;
    assert( iVar >= 0 && iVar < nVars );
    for ( i = 0; i < nVars; i++ )
        if ( iVar == Abc_Lit2Var((int)pPermLits[i]) )
            return i;
    assert( 0 );
    return -1;
}

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

2230
  Synopsis    [Evaluate delay using DSD balancing.]
2231 2232 2233 2234 2235 2236 2237 2238

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
2239
int If_CutDsdBalanceEval_rec( If_DsdMan_t * p, int Id, int * pTimes, int * pnSupp, Vec_Int_t * vAig, int * piLit, int nSuppAll, int * pArea, char * pPermLits )
2240 2241 2242 2243
{
    If_DsdObj_t * pObj = If_DsdVecObj( &p->vObjs, Id );
    if ( If_DsdObjType(pObj) == IF_DSD_VAR )
    {
2244
        int iCutVar = Abc_Lit2Var( pPermLits[*pnSupp] );
2245
        if ( vAig ) 
2246 2247 2248
            *piLit = Abc_Var2Lit( iCutVar, Abc_LitIsCompl(pPermLits[*pnSupp]) );
        (*pnSupp)++;
        return pTimes[iCutVar];
2249 2250 2251
    }
    if ( If_DsdObjType(pObj) == IF_DSD_MUX )
    {
2252
        int i, iFanin, Delays[3], pFaninLits[3];
2253 2254
        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
        {
2255 2256
            Delays[i] = If_CutDsdBalanceEval_rec( p, Abc_Lit2Var(iFanin), pTimes, pnSupp, vAig, pFaninLits+i, nSuppAll, pArea, pPermLits );
            if ( Delays[i] == -1 )
2257
                return -1;
2258 2259
            if ( vAig ) 
                pFaninLits[i] = Abc_LitNotCond( pFaninLits[i], Abc_LitIsCompl(iFanin) );
2260 2261 2262 2263 2264
        }
        if ( vAig )
            *piLit = If_LogCreateMux( vAig, pFaninLits[0], pFaninLits[1], pFaninLits[2], nSuppAll );
        else
            *pArea += 3;
2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277
        return 2 + Abc_MaxInt(Delays[0], Abc_MaxInt(Delays[1], Delays[2]));
    }
    if ( If_DsdObjType(pObj) == IF_DSD_PRIME )
    {
        int i, iFanin, Delays[IF_MAX_FUNC_LUTSIZE], pFaninLits[IF_MAX_FUNC_LUTSIZE];
        Vec_Int_t * vCover = Vec_WecEntry( p->vIsops[pObj->nFans], If_DsdObjTruthId(p, pObj) );
        if ( Vec_IntSize(vCover) == 0 )
            return -1;
        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
        {
            Delays[i] = If_CutDsdBalanceEval_rec( p, Abc_Lit2Var(iFanin), pTimes, pnSupp, vAig, pFaninLits+i, nSuppAll, pArea, pPermLits );
            if ( Delays[i] == -1 )
                return -1;
2278 2279
            if ( vAig ) 
                pFaninLits[i] = Abc_LitNotCond( pFaninLits[i], Abc_LitIsCompl(iFanin) );
2280 2281
        }
        return If_CutSopBalanceEvalInt( vCover, Delays, pFaninLits, vAig, piLit, nSuppAll, pArea );
2282 2283 2284 2285
    }
    assert( If_DsdObjType(pObj) == IF_DSD_AND || If_DsdObjType(pObj) == IF_DSD_XOR );
    {
        int i, iFanin, Delay, Result = 0;
2286 2287
        int fXor = 0;//(If_DsdObjType(pObj) == IF_DSD_XOR);
        int fXorFunc = (If_DsdObjType(pObj) == IF_DSD_XOR);
2288 2289 2290
        int nCounter = 0, pCounter[IF_MAX_FUNC_LUTSIZE], pFaninLits[IF_MAX_FUNC_LUTSIZE];
        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
        {
2291
            Delay = If_CutDsdBalanceEval_rec( p, Abc_Lit2Var(iFanin), pTimes, pnSupp, vAig, pFaninLits+i, nSuppAll, pArea, pPermLits );
2292 2293
            if ( Delay == -1 )
                return -1;
2294 2295 2296
            if ( vAig ) 
                pFaninLits[i] = Abc_LitNotCond( pFaninLits[i], Abc_LitIsCompl(iFanin) );
            Result = If_LogCounterAddAig( pCounter, &nCounter, pFaninLits, Delay, vAig ? pFaninLits[i] : -1, vAig, nSuppAll, fXor, fXorFunc );
2297
        }
2298 2299 2300
        assert( nCounter > 0 );
        if ( fXor )
            Result = If_LogCounterDelayXor( pCounter, nCounter ); // estimation
2301
        if ( vAig )
2302
            *piLit = If_LogCreateAndXorMulti( vAig, pFaninLits, nCounter, nSuppAll, fXorFunc );
2303 2304 2305 2306 2307
        else
            *pArea += (pObj->nFans - 1) * (1 + 2 * fXor);
        return Result;
    }
}
2308
int If_CutDsdBalanceEvalInt( If_DsdMan_t * p, int iDsd, int * pTimes, Vec_Int_t * vAig, int * pArea, char * pPermLits )
2309 2310 2311
{
    int nSupp = 0, iLit = 0;
    int nSuppAll = If_DsdVecLitSuppSize( &p->vObjs, iDsd );
2312 2313 2314
    int Res = If_CutDsdBalanceEval_rec( p, Abc_Lit2Var(iDsd), pTimes, &nSupp, vAig, &iLit, nSuppAll, pArea, pPermLits );
    if ( Res == -1 )
        return -1;
2315 2316 2317
    assert( nSupp == nSuppAll );
    assert( vAig == NULL || Abc_Lit2Var(iLit) == nSupp + Abc_Lit2Var(Vec_IntSize(vAig)) - 1 );
    if ( vAig )
2318
        Vec_IntPush( vAig, Abc_LitIsCompl(iLit) ^ Abc_LitIsCompl(iDsd) );
2319 2320 2321
    assert( vAig == NULL || (Vec_IntSize(vAig) & 1) );
    return Res;
}
2322
int If_CutDsdBalanceEval( If_Man_t * p, If_Cut_t * pCut, Vec_Int_t * vAig )
2323
{
2324
    int fUseCofs = 0;
2325 2326 2327 2328 2329
    pCut->fUser = 1;
    if ( vAig )
        Vec_IntClear( vAig );
    if ( pCut->nLeaves == 0 ) // const
    {
2330
        assert( Abc_Lit2Var(If_CutDsdLit(p, pCut)) == 0 );
2331
        if ( vAig )
2332
            Vec_IntPush( vAig, Abc_LitIsCompl(If_CutDsdLit(p, pCut)) );
2333
        pCut->Cost = 0;
2334 2335 2336 2337
        return 0;
    }
    if ( pCut->nLeaves == 1 ) // variable
    {
2338
        assert( Abc_Lit2Var(If_CutDsdLit(p, pCut)) == 1 );
2339 2340 2341
        if ( vAig )
            Vec_IntPush( vAig, 0 );
        if ( vAig )
2342
            Vec_IntPush( vAig, Abc_LitIsCompl(If_CutDsdLit(p, pCut)) );
2343
        pCut->Cost = 0;
2344
        return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay;
2345 2346 2347
    }
    else
    {
2348
        int fVerbose = 0;
2349 2350
        int i, pTimes[IF_MAX_FUNC_LUTSIZE];
        int Delay, Area = 0;
2351
        char * pPermLits = If_CutDsdPerm(p, pCut);
2352 2353
        for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
            pTimes[i] = (int)If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; 
2354
        Delay = If_CutDsdBalanceEvalInt( p->pIfDsdMan, Abc_LitNotCond(If_CutDsdLit(p, pCut), pCut->fCompl), pTimes, vAig, &Area, If_CutDsdPerm(p, pCut) );
2355
        pCut->Cost = Area;
2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374
        // try cofactoring 
        if ( fUseCofs )
        {
            // count how many times the max one appears
            int iMax = 0, nCountMax = 1;
            for ( i = 1; i < If_CutLeaveNum(pCut); i++ )
                if ( pTimes[i] > pTimes[iMax] )
                    iMax = i, nCountMax = 1;
                else if ( pTimes[i] == pTimes[iMax] )
                    nCountMax++;
            // decide when to try the decomposition
            if ( nCountMax == 1 && pTimes[iMax] + 2 < Delay && If_DsdManCheckNonTriv( p->pIfDsdMan, Abc_Lit2Var(If_CutDsdLit(p, pCut)), 
                 If_CutLeaveNum(pCut), If_CutDsdPermLitMax(pPermLits, If_CutLeaveNum(pCut), iMax)) )
            {
//                fVerbose = 1;
                Delay = pTimes[iMax] + 2;
            }
        }
        // report the result
2375 2376
        if ( fVerbose )
        {
2377
/*
2378 2379 2380 2381 2382 2383 2384
            int Max = 0, Two = 0;
            for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
                Max = Abc_MaxInt( Max, pTimes[i] );
            for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
                if ( pTimes[i] != Max )
                    Two = Abc_MaxInt( Two, pTimes[i] );
            if ( Two + 2 < Max && Max + 3 < Delay )
2385
*/
2386 2387 2388 2389 2390 2391 2392 2393 2394 2395
            {
                for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
                    printf( "%3d ", pTimes[Abc_Lit2Var(pPermLits[i])] );
                for ( ; i < p->pPars->nLutSize; i++ )
                    printf( "    " );
                printf( "-> %3d   ", Delay );
                If_DsdManPrintOne( stdout, p->pIfDsdMan, Abc_Lit2Var(If_CutDsdLit(p, pCut)), NULL, 0 );
                printf( "\n" );
            }
        }
2396 2397
        return Delay;
    }
2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
2411
void If_DsdManTune( If_DsdMan_t * p, int LutSize, int fFast, int fAdd, int fSpec, int fVerbose )
2412 2413 2414
{
    ProgressBar * pProgress = NULL;
    sat_solver * pSat = NULL;
2415 2416
    If_DsdObj_t * pObj;
    Vec_Int_t * vLits;
2417 2418
    int i, Value, nVars;
    word * pTruth;
2419
    if ( !fAdd || !LutSize )
2420
        If_DsdVecForEachObj( &p->vObjs, pObj, i )
2421
            pObj->fMark = 0;
2422 2423 2424 2425
    if ( LutSize == 0 )
        return;
    vLits = Vec_IntAlloc( 1000 );
    pSat = (sat_solver *)If_ManSatBuildXY( LutSize );
2426 2427
    pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(&p->vObjs) );
    If_DsdVecForEachObj( &p->vObjs, pObj, i )
2428 2429 2430 2431 2432
    {
        Extra_ProgressBarUpdate( pProgress, i, NULL );
        nVars = If_DsdObjSuppSize(pObj);
        if ( nVars <= LutSize )
            continue;
2433 2434 2435
        if ( fAdd && !pObj->fMark )
            continue;
        pObj->fMark = 0;
2436
        if ( If_DsdManCheckXY(p, Abc_Var2Lit(i, 0), LutSize, 0, 0, 0, 0) )
2437 2438 2439
            continue;
        if ( fFast )
            Value = 0;
2440 2441
        else
        {
2442 2443
            pTruth = If_DsdManComputeTruth( p, Abc_Var2Lit(i, 0), NULL );
            Value = If_ManSatCheckXYall( pSat, LutSize, pTruth, nVars, vLits );
2444 2445 2446
        }
        if ( Value )
            continue;
2447
        If_DsdVecObjSetMark( &p->vObjs, i );
2448
    }
2449
    Extra_ProgressBarStop( pProgress );
2450 2451 2452 2453 2454 2455 2456
    If_ManSatUnbuild( pSat );
    Vec_IntFree( vLits );
    if ( fVerbose )
        If_DsdManPrintDistrib( p );
}


2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
2469
void Id_DsdManTuneStr1( If_DsdMan_t * p, char * pStruct, int nConfls, int fVerbose )
2470 2471 2472 2473
{
    int fVeryVerbose = 0;
    ProgressBar * pProgress = NULL;
    If_DsdObj_t * pObj;
2474
    word * pTruth, * pConfig;
2475 2476 2477 2478
    int i, nVars, Value, LutSize;
    abctime clk = Abc_Clock();
    // parse the structure
    Ifn_Ntk_t * pNtk = Ifn_NtkParse( pStruct );
2479 2480
    if ( pNtk == NULL )
        return;
2481 2482 2483 2484 2485 2486
    if ( If_DsdManVarNum(p) > Ifn_NtkInputNum(pNtk) )
    {
        printf( "The support of DSD manager (%d) exceeds the support of the structure (%d).\n", If_DsdManVarNum(p), Ifn_NtkInputNum(pNtk) );
        ABC_FREE( pNtk );
        return;
    }
2487 2488
    ABC_FREE( p->pCellStr );
    p->pCellStr = Abc_UtilStrsav( pStruct );
2489 2490
    if ( If_DsdManVarNum(p) < Ifn_NtkInputNum(pNtk) )
        printf( "Warning: The support of DSD manager (%d) is less than the support of the structure (%d).\n", If_DsdManVarNum(p), Ifn_NtkInputNum(pNtk) );
2491
    LutSize = Ifn_NtkLutSizeMax(pNtk);
2492 2493
    p->nTtBits = Ifn_NtkTtBits( pStruct );
    p->nConfigWords = 1 + Abc_Bit6WordNum( p->nTtBits );
2494 2495 2496 2497 2498 2499 2500
    // print
    if ( fVerbose )
    {
        printf( "Considering programmable cell: " );
        Ifn_NtkPrint( pNtk );
        printf( "Largest LUT size = %d.\n", LutSize );
    }
2501 2502
    if ( p->nObjsPrev > 0 )
        printf( "Starting the tuning process from object %d (out of %d).\n", p->nObjsPrev, Vec_PtrSize(&p->vObjs) );
2503 2504
    // clean the attributes
    If_DsdVecForEachObj( &p->vObjs, pObj, i )
2505 2506
        if ( i >= p->nObjsPrev )
            pObj->fMark = 0;
2507 2508
    if ( p->vConfigs == NULL )
        p->vConfigs = Vec_WrdStart( p->nConfigWords * Vec_PtrSize(&p->vObjs) );
2509
    else
2510
        Vec_WrdFillExtra( p->vConfigs, p->nConfigWords * Vec_PtrSize(&p->vObjs), 0 );
2511
    pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(&p->vObjs) );
2512
    If_DsdVecForEachObjStart( &p->vObjs, pObj, i, p->nObjsPrev )
2513
    {
2514 2515
        if ( (i & 0xFF) == 0 )
            Extra_ProgressBarUpdate( pProgress, i, NULL );
2516
        nVars = If_DsdObjSuppSize(pObj);
2517 2518
        //if ( nVars <= LutSize )
        //    continue;
2519 2520 2521 2522 2523
        pTruth = If_DsdManComputeTruth( p, Abc_Var2Lit(i, 0), NULL );
        if ( fVeryVerbose )
            Dau_DsdPrintFromTruth( pTruth, nVars );
        if ( fVerbose )
            printf( "%6d : %2d ", i, nVars );
2524 2525
        pConfig = Vec_WrdEntryP( p->vConfigs, p->nConfigWords * i );
        Value = Ifn_NtkMatch( pNtk, pTruth, nVars, nConfls, fVerbose, fVeryVerbose, pConfig );
2526 2527 2528
        if ( fVeryVerbose )
            printf( "\n" );
        if ( Value == 0 )
2529
        {
2530
            If_DsdVecObjSetMark( &p->vObjs, i );
2531 2532
            memset( pConfig, 0, sizeof(word) * p->nConfigWords );
        }
2533
    }
2534
    p->nObjsPrev = 0;
2535
    p->LutSize = 0;
2536 2537 2538 2539 2540
    Extra_ProgressBarStop( pProgress );
    printf( "Finished matching %d functions. ", Vec_PtrSize(&p->vObjs) );
    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
    if ( fVeryVerbose )
        If_DsdManPrintDistrib( p );
2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568
    ABC_FREE( pNtk );
}


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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
#ifndef ABC_USE_PTHREADS
void Id_DsdManTuneStr( If_DsdMan_t * p, char * pStruct, int nConfls, int nProcs, int fVerbose )
{
    Id_DsdManTuneStr1( p, pStruct, nConfls, fVerbose );
}
#else // pthreads are used


#define PAR_THR_MAX 100
typedef struct Ifn_ThData_t_
{
    Ifn_Ntk_t * pNtk;    // network
    word        pTruth[DAU_MAX_WORD];
2569 2570
    word        pConfig[10]; // configuration data
    int         nConfigWords;// configuration data word count
2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593
    int         nVars;   // support
    int         Id;      // object
    int         nConfls; // conflicts
    int         Result;  // result
    int         Status;  // state
    abctime     clkUsed; // total runtime
} Ifn_ThData_t;
void * Ifn_WorkerThread( void * pArg )
{
    Ifn_ThData_t * pThData = (Ifn_ThData_t *)pArg;
    volatile int * pPlace = &pThData->Status;
    abctime clk;
    while ( 1 )
    {
        while ( *pPlace == 0 );
        assert( pThData->Status == 1 );
        if ( pThData->Id == -1 )
        {
            pthread_exit( NULL );
            assert( 0 );
            return NULL;
        }
        clk = Abc_Clock();
2594 2595
        memset( pThData->pConfig, 0, sizeof(word) * pThData->nConfigWords );
        pThData->Result = Ifn_NtkMatch( pThData->pNtk, pThData->pTruth, pThData->nVars, pThData->nConfls, 0, 0, pThData->pConfig );
2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630
        pThData->clkUsed += Abc_Clock() - clk;
        pThData->Status = 0;
//        printf( "Finished object %d\n", pThData->Id );
    }
    assert( 0 );
    return NULL;
}
void Id_DsdManTuneStr( If_DsdMan_t * p, char * pStruct, int nConfls, int nProcs, int fVerbose )
{
    int fVeryVerbose = 0;
    ProgressBar * pProgress = NULL;
    int i, k, nVars, LutSize;
    abctime clk = Abc_Clock();
    Ifn_Ntk_t * pNtk;
    If_DsdObj_t * pObj;
    if ( nProcs == 1 )
    {
        Id_DsdManTuneStr1( p, pStruct, nConfls, fVerbose );
        return;
    }
    if ( nProcs > PAR_THR_MAX )
    {
        printf( "The number of processes (%d) exceeds the precompiled limit (%d).\n", nProcs, PAR_THR_MAX );
        return;
    }
    // parse the structure
    pNtk = Ifn_NtkParse( pStruct );
    if ( pNtk == NULL )
        return;
    if ( If_DsdManVarNum(p) > Ifn_NtkInputNum(pNtk) )
    {
        printf( "The support of DSD manager (%d) exceeds the support of the structure (%d).\n", If_DsdManVarNum(p), Ifn_NtkInputNum(pNtk) );
        ABC_FREE( pNtk );
        return;
    }
2631 2632
    ABC_FREE( p->pCellStr );
    p->pCellStr = Abc_UtilStrsav( pStruct );
2633 2634 2635 2636
    if ( If_DsdManVarNum(p) < Ifn_NtkInputNum(pNtk) )
        printf( "Warning: The support of DSD manager (%d) is less than the support of the structure (%d).\n", If_DsdManVarNum(p), Ifn_NtkInputNum(pNtk) );
    // check the largest LUT
    LutSize = Ifn_NtkLutSizeMax(pNtk);
2637 2638 2639
    p->nTtBits = Ifn_NtkTtBits( pStruct );
    p->nConfigWords = 1 + Abc_Bit6WordNum( p->nTtBits );
    assert( p->nConfigWords <= 10 );
2640 2641 2642 2643 2644 2645 2646
    if ( fVerbose )
    {
        printf( "Considering programmable cell: " );
        Ifn_NtkPrint( pNtk );
        printf( "Largest LUT size = %d.\n", LutSize );
    }
    ABC_FREE( pNtk );
2647 2648
    if ( p->nObjsPrev > 0 )
        printf( "Starting the tuning process from object %d (out of %d).\n", p->nObjsPrev, Vec_PtrSize(&p->vObjs) );
2649 2650
    // clean the attributes
    If_DsdVecForEachObj( &p->vObjs, pObj, i )
2651 2652
        if ( i >= p->nObjsPrev )
            pObj->fMark = 0;
2653 2654
    if ( p->vConfigs == NULL )
        p->vConfigs = Vec_WrdStart( p->nConfigWords * Vec_PtrSize(&p->vObjs) );
2655
    else
2656
        Vec_WrdFillExtra( p->vConfigs, p->nConfigWords * Vec_PtrSize(&p->vObjs), 0 );
2657 2658 2659 2660 2661 2662 2663
    pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(&p->vObjs) );

    // perform concurrent solving
    {
        pthread_t WorkerThread[PAR_THR_MAX];
        Ifn_ThData_t ThData[PAR_THR_MAX];
        abctime clk, clkUsed = 0;
2664
        int status, fRunning = 1, iCurrentObj = p->nObjsPrev;
2665 2666 2667
        // start the threads
        for ( i = 0; i < nProcs; i++ )
        {
2668 2669 2670 2671 2672 2673 2674 2675
            ThData[i].pNtk     = Ifn_NtkParse( pStruct );
            ThData[i].nVars    = -1;      // support
            ThData[i].Id       = -1;      // object
            ThData[i].nConfls  = nConfls; // conflicts
            ThData[i].Result   = -1;      // result
            ThData[i].Status   =  0;      // state
            ThData[i].clkUsed  =  0;      // total runtime
            ThData[i].nConfigWords = p->nConfigWords;
2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689
            status = pthread_create( WorkerThread + i, NULL, Ifn_WorkerThread, (void *)(ThData + i) );  assert( status == 0 );
        }
        // run the threads
        while ( fRunning || iCurrentObj < Vec_PtrSize(&p->vObjs) )
        {
            for ( i = 0; i < nProcs; i++ )
            {
                if ( ThData[i].Status )
                    continue;
                assert( ThData[i].Status == 0 );
                if ( ThData[i].Id >= 0 )
                {
                    //printf( "Closing obj %d with Thread %d:\n", ThData[i].Id, i );
                    assert( ThData[i].Result == 0 || ThData[i].Result == 1 );
2690
                    if ( ThData[i].Result == 0 )
2691
                        If_DsdVecObjSetMark( &p->vObjs, ThData[i].Id );
2692
                    else
2693 2694 2695 2696
                    {
                        word * pTtWords = Vec_WrdEntryP( p->vConfigs, p->nConfigWords * ThData[i].Id );
                        memcpy( pTtWords, ThData[i].pConfig, sizeof(word) * p->nConfigWords );
                    }
2697 2698 2699 2700 2701
                    ThData[i].Id     = -1;
                    ThData[i].Result = -1;
                }
                for ( k = iCurrentObj; k < Vec_PtrSize(&p->vObjs); k++ )
                {
2702
                    if ( (k & 0xFF) == 0 )
2703 2704 2705
                        Extra_ProgressBarUpdate( pProgress, k, NULL );
                    pObj  = If_DsdVecObj( &p->vObjs, k );
                    nVars = If_DsdObjSuppSize(pObj);
2706 2707
                    //if ( nVars <= LutSize )
                    //    continue;
2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745
                    clk = Abc_Clock();
                    If_DsdManComputeTruthPtr( p, Abc_Var2Lit(k, 0), NULL, ThData[i].pTruth );
                    clkUsed += Abc_Clock() - clk;
                    ThData[i].nVars  = nVars;
                    ThData[i].Id     =  k;
                    ThData[i].Result = -1;
                    ThData[i].Status =  1;
                    //printf( "Scheduling %d for Thread %d\n", ThData[i].Id, i );
                    iCurrentObj = k+1;
                    break;
                }
            }
            fRunning = 0;
            for ( i = 0; i < nProcs; i++ )
                if ( ThData[i].Status == 1 || (ThData[i].Status == 0 && ThData[i].Id >= 0) )
                    fRunning = 1;
            //printf( "fRunning %d\n", fRunning );
        }
        // stop the threads
        for ( i = 0; i < nProcs; i++ )
        {
            assert( ThData[i].Status == 0 );
            ThData[i].Id = -1;
            ThData[i].Status = 1;
            ABC_FREE( ThData[i].pNtk );
        }
        if ( fVerbose )
        {
            printf( "Main     : " );
            Abc_PrintTime( 1, "Time", clkUsed );
            for ( i = 0; i < nProcs; i++ )
            {
                printf( "Thread %d : ", i );
                Abc_PrintTime( 1, "Time", ThData[i].clkUsed );
            }
        }
    }

2746
    p->nObjsPrev = 0;
2747
    p->LutSize = 0;
2748 2749 2750 2751 2752
    Extra_ProgressBarStop( pProgress );
    printf( "Finished matching %d functions. ", Vec_PtrSize(&p->vObjs) );
    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
    if ( fVeryVerbose )
        If_DsdManPrintDistrib( p );
2753 2754
}

2755 2756
#endif // pthreads are used

2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767
/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
2768 2769
#ifdef ABC_USE_CUDD

2770
void Id_DsdManTuneThresh( If_DsdMan_t * p, int fUnate, int fThresh, int fThreshHeuristic, int fVerbose )
2771 2772
{
    extern int Extra_ThreshCheck( word * t, int nVars, int * pW );
2773
    extern int Extra_ThreshHeuristic( word * t, int nVars, int * pW );
2774 2775 2776 2777 2778 2779 2780
    int fVeryVerbose = 0;
    int pW[16];
    ProgressBar * pProgress = NULL;
    If_DsdObj_t * pObj;
    word * pTruth, Perm;
    int i, nVars, Value;
    abctime clk = Abc_Clock();
2781
    assert( fUnate + fThresh + fThreshHeuristic <= 1 );
2782 2783 2784 2785 2786 2787
    if ( p->nObjsPrev > 0 )
        printf( "Starting the tuning process from object %d (out of %d).\n", p->nObjsPrev, Vec_PtrSize(&p->vObjs) );
    // clean the attributes
    If_DsdVecForEachObj( &p->vObjs, pObj, i )
        if ( i >= p->nObjsPrev )
            pObj->fMark = 0;
2788 2789
    if ( p->vConfigs == NULL )
        p->vConfigs = Vec_WrdStart( Vec_PtrSize(&p->vObjs) );
2790
    else
2791
        Vec_WrdFillExtra( p->vConfigs, Vec_PtrSize(&p->vObjs), 0 );
2792 2793 2794 2795 2796 2797
    pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(&p->vObjs) );
    If_DsdVecForEachObjStart( &p->vObjs, pObj, i, p->nObjsPrev )
    {
        if ( (i & 0xFF) == 0 )
            Extra_ProgressBarUpdate( pProgress, i, NULL );
        nVars = If_DsdObjSuppSize(pObj);
Alan Mishchenko committed
2798 2799
        if ( nVars > 8 )
            continue;
2800 2801 2802 2803 2804 2805 2806 2807 2808
        pTruth = If_DsdManComputeTruth( p, Abc_Var2Lit(i, 0), NULL );
        if ( fVeryVerbose )
            Dau_DsdPrintFromTruth( pTruth, nVars );
        if ( fVerbose )
            printf( "%6d : %2d ", i, nVars );
        if ( fUnate )
            Value = Abc_TtIsUnate( pTruth, nVars );
        else if ( fThresh )
            Value = Extra_ThreshCheck( pTruth, nVars, pW );
2809 2810 2811
        else if ( fThreshHeuristic )
            Value = Extra_ThreshHeuristic( pTruth, nVars, pW );
        else
Alan Mishchenko committed
2812
            Value = 0;
2813 2814 2815 2816 2817 2818
        Perm = 0;
        if ( fVeryVerbose )
            printf( "\n" );
        if ( Value )
            If_DsdVecObjSetMark( &p->vObjs, i );
        else
2819
            Vec_WrdWriteEntry( p->vConfigs, i, Perm );
2820 2821 2822 2823 2824 2825 2826 2827 2828 2829
    }
    p->nObjsPrev = 0;
    p->LutSize = 0;
    Extra_ProgressBarStop( pProgress );
    printf( "Finished matching %d functions. ", Vec_PtrSize(&p->vObjs) );
    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
    if ( fVeryVerbose )
        If_DsdManPrintDistrib( p );
}

2830 2831
#endif // ABC_USE_CUDD are used

2832 2833 2834 2835 2836 2837 2838
////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


ABC_NAMESPACE_IMPL_END