FxchMan.c 25.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/**CFile****************************************************************

  FileName    [ FxchMan.c ]

  PackageName [ Fast eXtract with Cube Hashing (FXCH) ]

  Synopsis    [ Fxch Manager implementation ]

  Author      [ Bruno Schmitt - boschmitt at inf.ufrgs.br ]

  Affiliation [ UFRGS ]

  Date        [ Ver. 1.0. Started - March 6, 2016. ]

  Revision    []

***********************************************************************/
#include "Fxch.h"

ABC_NAMESPACE_IMPL_START

////////////////////////////////////////////////////////////////////////
///                LOCAL FUNCTIONS DEFINITIONS                       ///
////////////////////////////////////////////////////////////////////////
static inline int Fxch_ManSCAddRemove( Fxch_Man_t* pFxchMan,
26 27 28
                                       unsigned int SubCubeID,
                                       unsigned int iCube,
                                       unsigned int iLit0,
29 30
                                       unsigned int iLit1,
                                       char fAdd,
31
                                       char fUpdate )
32 33 34 35 36 37
{
    int ret = 0;

    if ( fAdd )
    {
        ret = Fxch_SCHashTableInsert( pFxchMan->pSCHashTable, pFxchMan->vCubes,
38
                                      SubCubeID,
39 40 41 42 43
                                      iCube, iLit0, iLit1, fUpdate );
    }
    else
    {
        ret = Fxch_SCHashTableRemove( pFxchMan->pSCHashTable, pFxchMan->vCubes,
44
                                      SubCubeID,
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
                                      iCube, iLit0, iLit1, fUpdate );
    }

    return ret;
}


static inline int Fxch_ManDivSingleCube( Fxch_Man_t* pFxchMan,
                                         int iCube,
                                         int fAdd,
                                         int fUpdate )
{
    Vec_Int_t* vCube = Vec_WecEntry( pFxchMan->vCubes, iCube );
    int i, k,
        Lit0,
        Lit1,
        fSingleCube = 1,
        fBase = 0;

64
    if ( Vec_IntSize( vCube ) < 2 )
65 66 67 68 69
        return 0;

    Vec_IntForEachEntryStart( vCube, Lit0, i, 1)
    Vec_IntForEachEntryStart( vCube, Lit1, k, (i + 1) )
    {
70
        int * pOutputID, nOnes, j, z;
71 72 73 74 75 76
        assert( Lit0 < Lit1 );

        Vec_IntClear( pFxchMan->vCubeFree );
        Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( Abc_LitNot( Lit0 ), 0 ) );
        Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( Abc_LitNot( Lit1 ), 1 ) );

77 78
        pOutputID = Vec_IntEntryP( pFxchMan->vOutputID, iCube * pFxchMan->nSizeOutputID );
        nOnes = 0;
79

80
        for ( j = 0; j < pFxchMan->nSizeOutputID; j++ )
81 82 83 84 85
            nOnes += Fxch_CountOnes( pOutputID[j] );

        if ( nOnes == 0 )
            nOnes = 1;

86 87
        if (fAdd)
        {
88
            for ( z = 0; z < nOnes; z++ )
89
                Fxch_DivAdd( pFxchMan, fUpdate, fSingleCube, fBase );
90 91 92 93
            pFxchMan->nPairsS++;
        }
        else
        {
94
            for ( z = 0; z < nOnes; z++ )
95
                Fxch_DivRemove( pFxchMan, fUpdate, fSingleCube, fBase );
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
            pFxchMan->nPairsS--;
        }
    }

    return Vec_IntSize( vCube ) * ( Vec_IntSize( vCube ) - 1 ) / 2;
}

static inline void Fxch_ManDivDoubleCube( Fxch_Man_t* pFxchMan,
                                          int iCube,
                                          int fAdd,
                                          int fUpdate )
{
    Vec_Int_t* vLitHashKeys = pFxchMan->vLitHashKeys,
             * vCube = Vec_WecEntry( pFxchMan->vCubes, iCube );
    int SubCubeID = 0,
        iLit0,
        Lit0;

    Vec_IntForEachEntryStart( vCube, Lit0, iLit0, 1)
        SubCubeID += Vec_IntEntry( vLitHashKeys, Lit0 );

117
    Fxch_ManSCAddRemove( pFxchMan, SubCubeID,
118
                         iCube, 0, 0,
119
                         (char)fAdd, (char)fUpdate );
120 121 122 123 124 125

    Vec_IntForEachEntryStart( vCube, Lit0, iLit0, 1)
    {
        /* 1 Lit remove */
        SubCubeID -= Vec_IntEntry( vLitHashKeys, Lit0 );

126
        pFxchMan->nPairsD += Fxch_ManSCAddRemove( pFxchMan, SubCubeID,
127
                                                  iCube, iLit0, 0,
128
                                                  (char)fAdd, (char)fUpdate );
129

130
        if ( Vec_IntSize( vCube ) >= 3 )
131 132 133 134 135 136 137 138 139
        {
            int Lit1,
                iLit1;

            Vec_IntForEachEntryStart( vCube, Lit1, iLit1, iLit0 + 1)
            {
                /* 2 Lit remove */
                SubCubeID -= Vec_IntEntry( vLitHashKeys, Lit1 );

140
                pFxchMan->nPairsD += Fxch_ManSCAddRemove( pFxchMan, SubCubeID,
141
                                                          iCube, iLit0, iLit1,
142
                                                          (char)fAdd, (char)fUpdate );
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168

                SubCubeID += Vec_IntEntry( vLitHashKeys, Lit1 );
            }
        }

        SubCubeID += Vec_IntEntry( vLitHashKeys, Lit0 );
    }
}

static inline void Fxch_ManCompressCubes( Vec_Wec_t* vCubes,
                                          Vec_Int_t* vLit2Cube )
{
    int i,
        k = 0,
        CubeId;

    Vec_IntForEachEntry( vLit2Cube, CubeId, i )
        if ( Vec_IntSize(Vec_WecEntry(vCubes, CubeId)) > 0 )
            Vec_IntWriteEntry( vLit2Cube, k++, CubeId );

    Vec_IntShrink( vLit2Cube, k );
}

////////////////////////////////////////////////////////////////////////
///                     PUBLIC INTERFACE                             ///
////////////////////////////////////////////////////////////////////////
169
Fxch_Man_t* Fxch_ManAlloc( Vec_Wec_t* vCubes )
170 171 172 173
{
    Fxch_Man_t* pFxchMan = ABC_CALLOC( Fxch_Man_t, 1 );

    pFxchMan->vCubes = vCubes;
174 175 176 177 178 179 180 181 182 183 184 185 186
    pFxchMan->nCubesInit = Vec_WecSize( vCubes );

    pFxchMan->pDivHash = Hsh_VecManStart( 1024 );
    pFxchMan->vDivWeights = Vec_FltAlloc( 1024 );
    pFxchMan->vDivCubePairs = Vec_WecAlloc( 1024 );

    pFxchMan->vCubeFree = Vec_IntAlloc( 4 );
    pFxchMan->vDiv = Vec_IntAlloc( 4 );

    pFxchMan->vCubesS = Vec_IntAlloc( 128 );
    pFxchMan->vPairs = Vec_IntAlloc( 128 );
    pFxchMan->vCubesToUpdate = Vec_IntAlloc( 64 );
    pFxchMan->vCubesToRemove = Vec_IntAlloc( 64 );
187
    pFxchMan->vSCC = Vec_IntAlloc( 64 );
188 189 190 191 192 193 194 195 196 197 198 199

    return pFxchMan;
}

void Fxch_ManFree( Fxch_Man_t* pFxchMan )
{
    Vec_WecFree( pFxchMan->vLits );
    Vec_IntFree( pFxchMan->vLitCount );
    Vec_IntFree( pFxchMan->vLitHashKeys );
    Hsh_VecManStop( pFxchMan->pDivHash );
    Vec_FltFree( pFxchMan->vDivWeights );
    Vec_QueFree( pFxchMan->vDivPrio );
200
    Vec_WecFree( pFxchMan->vDivCubePairs );
201
    Vec_IntFree( pFxchMan->vLevels );
202

203 204
    Vec_IntFree( pFxchMan->vCubeFree );
    Vec_IntFree( pFxchMan->vDiv );
205

206 207
    Vec_IntFree( pFxchMan->vCubesS );
    Vec_IntFree( pFxchMan->vPairs );
208 209 210 211
    Vec_IntFree( pFxchMan->vCubesToUpdate );
    Vec_IntFree( pFxchMan->vCubesToRemove );
    Vec_IntFree( pFxchMan->vSCC );

212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
    ABC_FREE( pFxchMan );
}

void Fxch_ManMapLiteralsIntoCubes( Fxch_Man_t* pFxchMan,
                                   int nVars )
{

    Vec_Int_t* vCube;
    int i, k,
        Lit,
        Count;

    pFxchMan->nVars = 0;
    pFxchMan->nLits = 0;
    Vec_WecForEachLevel( pFxchMan->vCubes, vCube, i )
    {
        assert( Vec_IntSize(vCube) > 0 );
        pFxchMan->nVars = Abc_MaxInt( pFxchMan->nVars, Vec_IntEntry( vCube, 0 ) );
        pFxchMan->nLits += Vec_IntSize(vCube) - 1;
        Vec_IntForEachEntryStart( vCube, Lit, k, 1 )
            pFxchMan->nVars = Abc_MaxInt( pFxchMan->nVars, Abc_Lit2Var( Lit ) );
    }

    assert( pFxchMan->nVars < nVars );
    pFxchMan->nVars = nVars;

    /* Count the number of time each literal appears on the SOP */
    pFxchMan->vLitCount = Vec_IntStart( 2 * pFxchMan->nVars );
    Vec_WecForEachLevel( pFxchMan->vCubes, vCube, i )
        Vec_IntForEachEntryStart( vCube, Lit, k, 1 )
            Vec_IntAddToEntry( pFxchMan->vLitCount, Lit, 1 );

    /* Allocate space to the array of arrays wich maps Literals into cubes which uses them */
    pFxchMan->vLits = Vec_WecStart( 2 * pFxchMan->nVars );
    Vec_IntForEachEntry( pFxchMan->vLitCount, Count, Lit )
        Vec_IntGrow( Vec_WecEntry( pFxchMan->vLits, Lit ), Count );

    /* Maps Literals into cubes which uses them */
    Vec_WecForEachLevel( pFxchMan->vCubes, vCube, i )
        Vec_IntForEachEntryStart( vCube, Lit, k, 1 )
            Vec_WecPush( pFxchMan->vLits, Lit, i );
}

void Fxch_ManGenerateLitHashKeys( Fxch_Man_t* pFxchMan )
{
257
    int i;
258 259 260
    /* Generates the random number which will be used for hashing cubes */
    Gia_ManRandom( 1 );
    pFxchMan->vLitHashKeys = Vec_IntAlloc( ( 2 * pFxchMan->nVars ) );
261
    for ( i = 0; i < (2 * pFxchMan->nVars); i++ )
262 263 264 265 266 267
        Vec_IntPush( pFxchMan->vLitHashKeys, Gia_ManRandom(0) & 0x3FFFFFF );
}

void Fxch_ManSCHashTablesInit( Fxch_Man_t* pFxchMan )
{
    Vec_Wec_t* vCubes = pFxchMan->vCubes;
268
    Vec_Int_t* vCube;
269 270 271 272 273 274
    int iCube,
        nTotalHashed = 0;

    Vec_WecForEachLevel( vCubes, vCube, iCube )
    {
        int nLits = Vec_IntSize( vCube ) - 1,
275
            nSubCubes = nLits <= 2? nLits + 1: ( nLits * nLits + nLits ) / 2;
276 277 278 279

        nTotalHashed += nSubCubes + 1;
    }

280
    pFxchMan->pSCHashTable = Fxch_SCHashTableCreate( pFxchMan, nTotalHashed );
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 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 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
}

void Fxch_ManSCHashTablesFree( Fxch_Man_t* pFxchMan )
{
    Fxch_SCHashTableDelete( pFxchMan->pSCHashTable );
}

void Fxch_ManDivCreate( Fxch_Man_t* pFxchMan )
{
    Vec_Int_t* vCube;
    float Weight;
    int fAdd = 1,
        fUpdate = 0,
        iCube;

    Vec_WecForEachLevel( pFxchMan->vCubes, vCube, iCube )
    {
        Fxch_ManDivSingleCube( pFxchMan, iCube, fAdd, fUpdate );
        Fxch_ManDivDoubleCube( pFxchMan, iCube, fAdd, fUpdate );
    }

    pFxchMan->vDivPrio = Vec_QueAlloc( Vec_FltSize( pFxchMan->vDivWeights ) );
    Vec_QueSetPriority( pFxchMan->vDivPrio, Vec_FltArrayP( pFxchMan->vDivWeights ) );
    Vec_FltForEachEntry( pFxchMan->vDivWeights, Weight, iCube )
    {
        if ( Weight > 0.0 )
            Vec_QuePush( pFxchMan->vDivPrio, iCube );
    }
}

/* Level Computation */
int Fxch_ManComputeLevelDiv( Fxch_Man_t* pFxchMan,
                             Vec_Int_t* vCubeFree )
{
    int i,
        Lit,
        Level = 0;

    Vec_IntForEachEntry( vCubeFree, Lit, i )
        Level = Abc_MaxInt( Level, Vec_IntEntry( pFxchMan->vLevels, Abc_Lit2Var( Abc_Lit2Var( Lit ) ) ) );

    return Abc_MinInt( Level, 800 );
}

int Fxch_ManComputeLevelCube( Fxch_Man_t* pFxchMan,
                              Vec_Int_t * vCube )
{
    int k,
        Lit,
        Level = 0;

    Vec_IntForEachEntryStart( vCube, Lit, k, 1 )
        Level = Abc_MaxInt( Level, Vec_IntEntry( pFxchMan->vLevels, Abc_Lit2Var( Lit ) ) );

    return Level;
}

void Fxch_ManComputeLevel( Fxch_Man_t* pFxchMan )
{
    Vec_Int_t* vCube;
    int i,
        iVar,
        iFirst = 0;

    iVar = Vec_IntEntry( Vec_WecEntry( pFxchMan->vCubes, 0 ), 0 );
    pFxchMan->vLevels = Vec_IntStart( pFxchMan->nVars );

    Vec_WecForEachLevel( pFxchMan->vCubes, vCube, i )
    {
        if ( iVar != Vec_IntEntry( vCube, 0 ) )
        {
            Vec_IntAddToEntry( pFxchMan->vLevels, iVar, i - iFirst );
            iVar = Vec_IntEntry( vCube, 0 );
            iFirst = i;
        }
        Vec_IntUpdateEntry( pFxchMan->vLevels, iVar, Fxch_ManComputeLevelCube( pFxchMan, vCube ) );
    }
}

360 361 362 363 364
/* Extract divisor from single-cubes */
static inline void Fxch_ManExtractDivFromCube( Fxch_Man_t* pFxchMan,
                                               const int Lit0,
                                               const int Lit1,
                                               const int iVarNew )
365
{
366 367
    int i, iCube0;
    Vec_Int_t* vLitP = Vec_WecEntry( pFxchMan->vLits, Vec_WecSize( pFxchMan->vLits ) - 2 );
368

369 370 371 372
    Vec_IntForEachEntry( pFxchMan->vCubesS, iCube0, i )
    {
        int RetValue;
        Vec_Int_t* vCube0;
373

374 375 376 377
        vCube0 = Fxch_ManGetCube( pFxchMan, iCube0 );
        RetValue  = Vec_IntRemove1( vCube0, Abc_LitNot( Lit0 ) );
        RetValue += Vec_IntRemove1( vCube0, Abc_LitNot( Lit1 ) );
        assert( RetValue == 2 );
378

379 380
        Vec_IntPush( vCube0, Abc_Var2Lit( iVarNew, 0 ) );
        Vec_IntPush( vLitP, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) );
381
        Vec_IntPush( pFxchMan->vCubesToUpdate, iCube0 );
382

383
        pFxchMan->nLits--;
384
    }
385
}
386

387
/* Extract divisor from cube pairs */
388
static inline void Fxch_ManExtractDivFromCubePairs( Fxch_Man_t* pFxchMan,
389 390 391
                                                   const int iVarNew )
{
    /* For each pair (Ci, Cj) */
392
    int iCube0, iCube1, i;
393 394 395 396


    Vec_IntForEachEntryDouble( pFxchMan->vPairs, iCube0, iCube1, i )
    {
397
        int j, Lit,
Bruno Schmitt committed
398
            RetValue,
399
            fCompl = 0;
400
        int * pOutputID0, * pOutputID1;
401

402 403 404 405 406
        Vec_Int_t* vCube = NULL,
                 * vCube0 = Fxch_ManGetCube( pFxchMan, iCube0 ),
                 * vCube1 = Fxch_ManGetCube( pFxchMan, iCube1 ),
                 * vCube0Copy = Vec_IntDup( vCube0 ),
                 * vCube1Copy = Vec_IntDup( vCube1 );
407

408
        RetValue  = Fxch_DivRemoveLits( vCube0Copy, vCube1Copy, pFxchMan->vDiv, &fCompl );
409

410
        assert( RetValue == Vec_IntSize( pFxchMan->vDiv ) );
411

412
        pFxchMan->nLits -= Vec_IntSize( pFxchMan->vDiv ) + Vec_IntSize( vCube1 ) - 2;
413

414
        /* Identify type of Extraction */
415 416
        pOutputID0 = Vec_IntEntryP( pFxchMan->vOutputID, iCube0 * pFxchMan->nSizeOutputID );
        pOutputID1 = Vec_IntEntryP( pFxchMan->vOutputID, iCube1 * pFxchMan->nSizeOutputID );
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
        RetValue = 1;
        for ( j = 0; j < pFxchMan->nSizeOutputID && RetValue; j++ )
            RetValue = ( pOutputID0[j] == pOutputID1[j] );

        /* Exact Extractraion */
        if ( RetValue )
        {
            Vec_IntClear( vCube0 );
            Vec_IntAppend( vCube0, vCube0Copy );
            vCube = vCube0;

            Vec_IntPush( pFxchMan->vCubesToUpdate, iCube0 );
            Vec_IntClear( vCube1 );

            /* Update Lit -> Cube mapping */
            Vec_IntForEachEntry( pFxchMan->vDiv, Lit, j )
            {
Bruno Schmitt committed
434
                Vec_IntRemove( Vec_WecEntry( pFxchMan->vLits, Abc_Lit2Var( Lit ) ),
435
                               Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) );
Bruno Schmitt committed
436
                Vec_IntRemove( Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Abc_Lit2Var( Lit ) ) ),
437 438 439 440 441 442 443 444 445 446 447 448 449
                               Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) );
            }

        }
        /* Unexact Extraction */
        else
        {
            for ( j = 0; j < pFxchMan->nSizeOutputID; j++ )
                pFxchMan->pTempOutputID[j] = ( pOutputID0[j] & pOutputID1[j] );

            /* Create new cube */
            vCube = Vec_WecPushLevel( pFxchMan->vCubes );
            Vec_IntAppend( vCube, vCube0Copy );
Bruno Schmitt committed
450
            Vec_IntPushArray( pFxchMan->vOutputID, pFxchMan->pTempOutputID, pFxchMan->nSizeOutputID );
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
            Vec_IntPush( pFxchMan->vCubesToUpdate, Vec_WecLevelId( pFxchMan->vCubes, vCube ) );

            /* Update Lit -> Cube mapping */
            Vec_IntForEachEntryStart( vCube, Lit, j, 1 )
                Vec_WecPush( pFxchMan->vLits, Lit, Vec_WecLevelId( pFxchMan->vCubes, vCube ) );

            /*********************************************************/
            RetValue = 0;
            for ( j = 0; j < pFxchMan->nSizeOutputID; j++ )
            {
                pFxchMan->pTempOutputID[j] = pOutputID0[j];
                RetValue |= ( pOutputID0[j] & ~( pOutputID1[j] ) );
                pOutputID0[j] &= ~( pOutputID1[j] );
            }

            if ( RetValue != 0 )
                Vec_IntPush( pFxchMan->vCubesToUpdate, iCube0 );
            else
                Vec_IntClear( vCube0 );

            /*********************************************************/
            RetValue = 0;
            for ( j = 0; j < pFxchMan->nSizeOutputID; j++ )
            {
                RetValue |= ( pOutputID1[j] & ~( pFxchMan->pTempOutputID[j] ) );
                pOutputID1[j] &= ~( pFxchMan->pTempOutputID[j] );
            }

            if ( RetValue != 0 )
                Vec_IntPush( pFxchMan->vCubesToUpdate, iCube1 );
            else
                Vec_IntClear( vCube1 );

        }
        Vec_IntFree( vCube0Copy );
        Vec_IntFree( vCube1Copy );
487

488 489
        if ( iVarNew )
        {
490 491
            Vec_Int_t* vLitP = Vec_WecEntry( pFxchMan->vLits, Vec_WecSize( pFxchMan->vLits ) - 2 ),
                     * vLitN = Vec_WecEntry( pFxchMan->vLits, Vec_WecSize( pFxchMan->vLits ) - 1 );
Bruno Schmitt committed
492

493
            assert( vCube );
494 495
            if ( Vec_IntSize( pFxchMan->vDiv ) == 2 || fCompl )
            {
496 497 498
                Vec_IntPush( vCube, Abc_Var2Lit( iVarNew, 1 ) );
                Vec_IntPush( vLitN, Vec_WecLevelId( pFxchMan->vCubes, vCube ) );
                Vec_IntSort( vLitN, 0 );
499 500 501
            }
            else
            {
502 503 504
                Vec_IntPush( vCube, Abc_Var2Lit( iVarNew, 0 ) );
                Vec_IntPush( vLitP, Vec_WecLevelId( pFxchMan->vCubes, vCube ) );
                Vec_IntSort( vLitP, 0 );
505 506
            }
        }
507 508
    }

509
    return;
510 511 512 513 514 515 516
}

static inline int Fxch_ManCreateCube( Fxch_Man_t* pFxchMan,
                                      int Lit0,
                                      int Lit1 )
{
    int Level,
Bruno Schmitt committed
517
        iVarNew,
518
        j;
519 520
    Vec_Int_t* vCube0,
             * vCube1;
Bruno Schmitt committed
521

522
    /* Create a new variable */
523
    iVarNew = pFxchMan->nVars;
524 525
    pFxchMan->nVars++;

526
    /* Clear temporary outputID vector */
527
    for ( j = 0; j < pFxchMan->nSizeOutputID; j++ )
528
        pFxchMan->pTempOutputID[j] = 0;
Bruno Schmitt committed
529

530 531 532 533 534 535 536
    /* Create new Lit hash keys */
    Vec_IntPush( pFxchMan->vLitHashKeys, Gia_ManRandom(0) & 0x3FFFFFF );
    Vec_IntPush( pFxchMan->vLitHashKeys, Gia_ManRandom(0) & 0x3FFFFFF );

    /* Create new Cube */
    vCube0 = Vec_WecPushLevel( pFxchMan->vCubes );
    Vec_IntPush( vCube0, iVarNew );
537
    Vec_IntPushArray( pFxchMan->vOutputID, pFxchMan->pTempOutputID, pFxchMan->nSizeOutputID );
538 539 540 541 542 543 544 545 546 547 548 549

    if ( Vec_IntSize( pFxchMan->vDiv ) == 2 )
    {
        if ( Lit0 > Lit1 )
            ABC_SWAP(int, Lit0, Lit1);

        Vec_IntPush( vCube0, Abc_LitNot( Lit0 ) );
        Vec_IntPush( vCube0, Abc_LitNot( Lit1 ) );
        Level = 1 + Fxch_ManComputeLevelCube( pFxchMan, vCube0 );
    }
    else
    {
550 551 552
        int i;
        int Lit;

553 554
        vCube1 = Vec_WecPushLevel( pFxchMan->vCubes );
        Vec_IntPush( vCube1, iVarNew );
555 556 557
        Vec_IntPushArray( pFxchMan->vOutputID, pFxchMan->pTempOutputID, pFxchMan->nSizeOutputID );

        vCube0 = Fxch_ManGetCube( pFxchMan, Vec_WecSize( pFxchMan->vCubes ) - 2 );
558 559 560
        Fxch_DivSepareteCubes( pFxchMan->vDiv, vCube0, vCube1 );
        Level = 2 + Abc_MaxInt( Fxch_ManComputeLevelCube( pFxchMan, vCube0 ),
                                Fxch_ManComputeLevelCube( pFxchMan, vCube1 ) );
561 562 563 564 565 566 567 568 569 570

        Vec_IntPush( pFxchMan->vCubesToUpdate, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) );
        Vec_IntPush( pFxchMan->vCubesToUpdate, Vec_WecLevelId( pFxchMan->vCubes, vCube1 ) );

        /* Update Lit -> Cube mapping */
        Vec_IntForEachEntryStart( vCube0, Lit, i, 1 )
            Vec_WecPush( pFxchMan->vLits, Lit, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) );

        Vec_IntForEachEntryStart( vCube1, Lit, i, 1 )
            Vec_WecPush( pFxchMan->vLits, Lit, Vec_WecLevelId( pFxchMan->vCubes, vCube1 ) );
571 572 573 574 575 576 577
    }
    assert( Vec_IntSize( pFxchMan->vLevels ) == iVarNew );
    Vec_IntPush( pFxchMan->vLevels, Level );

    pFxchMan->nLits += Vec_IntSize( pFxchMan->vDiv );

    /* Create new literals */
578 579
    Vec_WecPushLevel( pFxchMan->vLits );
    Vec_WecPushLevel( pFxchMan->vLits );
580

581 582
    return iVarNew;
}
583

584 585 586
void Fxch_ManUpdate( Fxch_Man_t* pFxchMan,
                     int iDiv )
{
587
    int i, iCube0, iCube1,
588 589 590
        Lit0 = -1,
        Lit1 = -1,
        iVarNew;
591

592 593 594
    Vec_Int_t* vCube0,
             * vCube1,
             * vDivCubePairs;
595

596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
    /* Get the selected candidate (divisor) */
    Vec_IntClear( pFxchMan->vDiv );
    Vec_IntAppend( pFxchMan->vDiv, Hsh_VecReadEntry( pFxchMan->pDivHash, iDiv ) );

    /* Find cubes associated with the divisor */
    Vec_IntClear( pFxchMan->vCubesS );
    if ( Vec_IntSize( pFxchMan->vDiv ) == 2 )
    {
        Lit0 = Abc_Lit2Var( Vec_IntEntry( pFxchMan->vDiv, 0 ) );
        Lit1 = Abc_Lit2Var( Vec_IntEntry( pFxchMan->vDiv, 1 ) );
        assert( Lit0 >= 0 && Lit1 >= 0 );

        Fxch_ManCompressCubes( pFxchMan->vCubes, Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Lit0 ) ) );
        Fxch_ManCompressCubes( pFxchMan->vCubes, Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Lit1 ) ) );
        Vec_IntTwoRemoveCommon( Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Lit0 ) ),
                                Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Lit1 ) ),
                                pFxchMan->vCubesS );
613 614
    }

615 616 617 618 619 620
    /* Find pairs associated with the divisor */
    Vec_IntClear( pFxchMan->vPairs );
    vDivCubePairs = Vec_WecEntry( pFxchMan->vDivCubePairs, iDiv );
    Vec_IntAppend( pFxchMan->vPairs, vDivCubePairs );
    Vec_IntErase( vDivCubePairs );

621 622
    Vec_IntForEachEntryDouble( pFxchMan->vPairs, iCube0, iCube1, i )
    {
623 624 625 626 627 628 629
        assert( Fxch_ManGetLit( pFxchMan, iCube0, 0) == Fxch_ManGetLit( pFxchMan, iCube1, 0) );
        if (iCube0 > iCube1)
        {
            Vec_IntSetEntry( pFxchMan->vPairs, i, iCube1);
            Vec_IntSetEntry( pFxchMan->vPairs, i+1, iCube0);
        }
    }
630

631 632
    Vec_IntUniqifyPairs( pFxchMan->vPairs );
    assert( Vec_IntSize( pFxchMan->vPairs ) % 2 == 0 );
633

634 635
    /* subtract cost of single-cube divisors */
    Vec_IntForEachEntry( pFxchMan->vCubesS, iCube0, i )
636 637
    {
        Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1);
638

639 640 641
        if ( Vec_WecEntryEntry( pFxchMan->vCubes, iCube0, 0 ) == 0 )
            Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 );
    }
642

643
    Vec_IntForEachEntry( pFxchMan->vPairs, iCube0, i )
644 645
    {
        Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1);
646

647 648 649 650 651
        if ( Vec_WecEntryEntry( pFxchMan->vCubes, iCube0, 0 ) == 0 )
            Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 );
    }

    Vec_IntClear( pFxchMan->vCubesToUpdate );
652 653 654 655
    if ( Fxch_DivIsNotConstant1( pFxchMan->vDiv ) )
    {
        iVarNew = Fxch_ManCreateCube( pFxchMan, Lit0, Lit1 );
        Fxch_ManExtractDivFromCube( pFxchMan, Lit0, Lit1, iVarNew );
656
        Fxch_ManExtractDivFromCubePairs( pFxchMan, iVarNew );
657
    }
658
    else
659
        Fxch_ManExtractDivFromCubePairs( pFxchMan, 0 );
Bruno Schmitt committed
660

661
    assert( Vec_IntSize( pFxchMan->vCubesToUpdate ) );
662

663 664 665 666
    /* Add cost */
    Vec_IntForEachEntry( pFxchMan->vCubesToUpdate, iCube0, i )
    {
        Fxch_ManDivSingleCube( pFxchMan, iCube0, 1, 1 );
667

668 669 670
        if ( Vec_WecEntryEntry( pFxchMan->vCubes, iCube0, 0 ) == 0 )
            Fxch_ManDivDoubleCube( pFxchMan, iCube0, 1, 1 );
    }
671

672
    /* Deal with SCC */
Bruno Schmitt committed
673
    if ( Vec_IntSize( pFxchMan->vSCC ) )
674
    {
675 676 677 678 679
        Vec_IntUniqifyPairs( pFxchMan->vSCC );
        assert( Vec_IntSize( pFxchMan->vSCC ) % 2 == 0 );

        Vec_IntForEachEntryDouble( pFxchMan->vSCC, iCube0, iCube1, i )
        {
680
            int j, RetValue = 1;
681 682 683 684 685 686
            int* pOutputID0 = Vec_IntEntryP( pFxchMan->vOutputID, iCube0 * pFxchMan->nSizeOutputID );
            int* pOutputID1 = Vec_IntEntryP( pFxchMan->vOutputID, iCube1 * pFxchMan->nSizeOutputID );
            vCube0 = Vec_WecEntry( pFxchMan->vCubes, iCube0 );
            vCube1 = Vec_WecEntry( pFxchMan->vCubes, iCube1 );

            if ( !Vec_WecIntHasMark( vCube0 ) )
687
            {
688 689 690
                Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1 );
                Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 );
                Vec_WecIntSetMark( vCube0 );
691 692
            }

693 694 695 696 697 698
            if ( !Vec_WecIntHasMark( vCube1 ) )
            {
                Fxch_ManDivSingleCube( pFxchMan, iCube1, 0, 1 );
                Fxch_ManDivDoubleCube( pFxchMan, iCube1, 0, 1 );
                Vec_WecIntSetMark( vCube1 );
            }
699

700 701
            if ( Vec_IntSize( vCube0 ) == Vec_IntSize( vCube1 ) )
            {
702
                for ( j = 0; j < pFxchMan->nSizeOutputID; j++ )
703 704 705 706 707 708 709 710
                {
                    pOutputID1[j] |= pOutputID0[j];
                    pOutputID0[j] = 0;
                }
                Vec_IntClear( Vec_WecEntry( pFxchMan->vCubes, iCube0 ) );
                Vec_WecIntXorMark( vCube0 );
                continue;
            }
711

712
            for ( j = 0; j < pFxchMan->nSizeOutputID && RetValue; j++ )
713
                RetValue = ( pOutputID0[j] == pOutputID1[j] );
714

715 716 717 718 719 720 721 722
            if ( RetValue )
            {
                Vec_IntClear( Vec_WecEntry( pFxchMan->vCubes, iCube0 ) );
                Vec_WecIntXorMark( vCube0 );
            }
            else
            {
                RetValue = 0;
723
                for ( j = 0; j < pFxchMan->nSizeOutputID; j++ )
724 725 726 727 728 729 730 731 732 733 734 735
                {
                    RetValue |= ( pOutputID0[j] & ~( pOutputID1[j] ) );
                    pOutputID0[j] &= ~( pOutputID1[j] );
                }

                if ( RetValue == 0 )
                {
                    Vec_IntClear( Vec_WecEntry( pFxchMan->vCubes, iCube0 ) );
                    Vec_WecIntXorMark( vCube0 );
                }
            }
        }
736

737 738 739 740
        Vec_IntForEachEntryDouble( pFxchMan->vSCC, iCube0, iCube1, i )
        {
            vCube0 = Vec_WecEntry( pFxchMan->vCubes, iCube0 );
            vCube1 = Vec_WecEntry( pFxchMan->vCubes, iCube1 );
741

742 743 744 745 746 747
            if ( Vec_WecIntHasMark( vCube0 ) )
            {
                Fxch_ManDivSingleCube( pFxchMan, iCube0, 1, 1 );
                Fxch_ManDivDoubleCube( pFxchMan, iCube0, 1, 1 );
                Vec_WecIntXorMark( vCube0 );
            }
748

749 750 751 752 753 754 755 756 757
            if ( Vec_WecIntHasMark( vCube1 ) )
            {
                Fxch_ManDivSingleCube( pFxchMan, iCube1, 1, 1 );
                Fxch_ManDivDoubleCube( pFxchMan, iCube1, 1, 1 );
                Vec_WecIntXorMark( vCube1 );
            }
        }

        Vec_IntClear( pFxchMan->vSCC );
758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785
    }

    pFxchMan->nExtDivs++;
}

/* Print */
void Fxch_ManPrintDivs( Fxch_Man_t* pFxchMan )
{
    int iDiv;

    for ( iDiv = 0; iDiv < Vec_FltSize( pFxchMan->vDivWeights ); iDiv++ )
        Fxch_DivPrint( pFxchMan, iDiv );
}

void Fxch_ManPrintStats( Fxch_Man_t* pFxchMan )
{
    printf( "Cubes =%8d  ", Vec_WecSizeUsed( pFxchMan->vCubes ) );
    printf( "Lits  =%8d  ", Vec_WecSizeUsed( pFxchMan->vLits ) );
    printf( "Divs  =%8d  ", Hsh_VecSize( pFxchMan->pDivHash ) );
    printf( "Divs+ =%8d  ", Vec_QueSize( pFxchMan->vDivPrio ) );
    printf( "Extr  =%7d  \n", pFxchMan->nExtDivs );
}

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

ABC_NAMESPACE_IMPL_END