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

  FileName    [darBalance.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [DAG-aware AIG rewriting.]

  Synopsis    [Algebraic AIG balancing.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - April 28, 2007.]

  Revision    [$Id: darBalance.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]

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

Alan Mishchenko committed
21
#include "darInt.h"
22
#include "misc/tim/tim.h"
Alan Mishchenko committed
23

24 25 26
ABC_NAMESPACE_IMPL_START


Alan Mishchenko committed
27 28 29 30
////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

31 32
//#define USE_LUTSIZE_BALANCE

Alan Mishchenko committed
33 34 35 36
////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

37 38
/**Function*************************************************************

39
  Synopsis    [Uniqifies the node.]
40 41 42 43 44 45 46 47

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
48
int Dar_ObjCompareLits( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 )
49
{
50 51 52 53 54 55
    int Diff = Aig_ObjToLit(*pp1) - Aig_ObjToLit(*pp2);
    if ( Diff < 0 )
        return -1;
    if ( Diff > 0 ) 
        return 1;
    return 0; 
56
}
57
void Dar_BalanceUniqify( Aig_Obj_t * pObj, Vec_Ptr_t * vNodes, int fExor )
58
{
59
    Aig_Obj_t * pTemp, * pTempNext;
60
    int i, k;
61
    // sort the nodes by their literal
62
    Vec_PtrSort( vNodes, (int (*)(const void *, const void *))Dar_ObjCompareLits );
63 64 65
    // remove duplicates
    k = 0;
    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pTemp, i )
66
    {
67
        if ( i + 1 == Vec_PtrSize(vNodes) )
68
        {
69
            Vec_PtrWriteEntry( vNodes, k++, pTemp );
70
            break;
71 72 73
        }
        pTempNext = (Aig_Obj_t *)Vec_PtrEntry( vNodes, i+1 );
        if ( !fExor && pTemp == Aig_Not(pTempNext) ) // pos_lit & neg_lit = 0
74
        {
75 76
            Vec_PtrClear( vNodes );
            return;
77
        }
78 79 80 81 82 83
        if ( pTemp != pTempNext )  // save if different
            Vec_PtrWriteEntry( vNodes, k++, pTemp );
        else if ( fExor ) // in case of XOR, remove identical
            i++;
    }
    Vec_PtrShrink( vNodes, k );
84 85
    if ( Vec_PtrSize(vNodes) < 2 )
        return;
86 87 88 89 90 91
    // check that there is no duplicates
    pTemp = (Aig_Obj_t *)Vec_PtrEntry( vNodes, 0 );
    Vec_PtrForEachEntryStart( Aig_Obj_t *, vNodes, pTempNext, i, 1 )
    {
        assert( pTemp != pTempNext );
        pTemp = pTempNext;
92 93 94
    }
}

95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
/**Function*************************************************************

  Synopsis    [Collects the nodes of the supergate.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Dar_BalanceCone_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper )
{
    if ( pObj != pRoot && (Aig_IsComplement(pObj) || Aig_ObjType(pObj) != Aig_ObjType(pRoot) || Aig_ObjRefs(pObj) > 1 || Vec_PtrSize(vSuper) > 10000) )
        Vec_PtrPush( vSuper, pObj );
    else
    {
        assert( !Aig_IsComplement(pObj) );
        assert( Aig_ObjIsNode(pObj) );
        // go through the branches
        Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild0(pObj) ), vSuper );
        Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild1(pObj) ), vSuper );
    }
}
Vec_Ptr_t * Dar_BalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level )
{
    Vec_Ptr_t * vNodes;
    assert( !Aig_IsComplement(pObj) );
    assert( Aig_ObjIsNode(pObj) );
    // extend the storage
    if ( Vec_VecSize( vStore ) <= Level )
        Vec_VecPush( vStore, Level, 0 );
    // get the temporary array of nodes
    vNodes = Vec_VecEntry( vStore, Level );
    Vec_PtrClear( vNodes );
    // collect the nodes in the implication supergate
    Dar_BalanceCone_rec( pObj, pObj, vNodes );
    // remove duplicates
    Dar_BalanceUniqify( pObj, vNodes, Aig_ObjIsExor(pObj) );
    return vNodes;
}
136 137


Alan Mishchenko committed
138 139 140 141 142 143 144 145 146 147 148
/**Function*************************************************************

  Synopsis    [Collects the nodes of the supergate.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
149
/*
Alan Mishchenko committed
150
int Dar_BalanceCone_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper )
Alan Mishchenko committed
151 152 153
{
    int RetValue1, RetValue2, i;
    // check if the node is visited
Alan Mishchenko committed
154
    if ( Aig_Regular(pObj)->fMarkB )
Alan Mishchenko committed
155
    {
Alan Mishchenko committed
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
        if ( Aig_ObjIsExor(pRoot) )
        {
            assert( !Aig_IsComplement(pObj) );
            // check if the node occurs in the same polarity
            Vec_PtrRemove( vSuper, pObj );
            Aig_Regular(pObj)->fMarkB = 0;
//printf( " Duplicated EXOR input!!! " );
            return 1;
        }
        else
        {
            // check if the node occurs in the same polarity
            for ( i = 0; i < vSuper->nSize; i++ )
                if ( vSuper->pArray[i] == pObj )
                    return 1;
            // check if the node is present in the opposite polarity
            for ( i = 0; i < vSuper->nSize; i++ )
                if ( vSuper->pArray[i] == Aig_Not(pObj) )
                    return -1;
        }
Alan Mishchenko committed
176 177 178 179
        assert( 0 );
        return 0;
    }
    // if the new node is complemented or a PI, another gate begins
Alan Mishchenko committed
180
    if ( pObj != pRoot && (Aig_IsComplement(pObj) || Aig_ObjType(pObj) != Aig_ObjType(pRoot) || Aig_ObjRefs(pObj) > 1 || Vec_PtrSize(vSuper) > 10000) )
Alan Mishchenko committed
181 182
    {
        Vec_PtrPush( vSuper, pObj );
Alan Mishchenko committed
183
        Aig_Regular(pObj)->fMarkB = 1;
Alan Mishchenko committed
184 185
        return 0;
    }
Alan Mishchenko committed
186 187
    assert( !Aig_IsComplement(pObj) );
    assert( Aig_ObjIsNode(pObj) );
Alan Mishchenko committed
188
    // go through the branches
Alan Mishchenko committed
189 190
    RetValue1 = Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild0(pObj) ), vSuper );
    RetValue2 = Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild1(pObj) ), vSuper );
Alan Mishchenko committed
191 192 193 194 195
    if ( RetValue1 == -1 || RetValue2 == -1 )
        return -1;
    // return 1 if at least one branch has a duplicate
    return RetValue1 || RetValue2;
}
196
Vec_Ptr_t * Dar_BalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level )
Alan Mishchenko committed
197 198 199
{
    Vec_Ptr_t * vNodes;
    int RetValue, i;
Alan Mishchenko committed
200
    assert( !Aig_IsComplement(pObj) );
Alan Mishchenko committed
201 202 203 204
    // extend the storage
    if ( Vec_VecSize( vStore ) <= Level )
        Vec_VecPush( vStore, Level, 0 );
    // get the temporary array of nodes
205
    vNodes = Vec_VecEntry( vStore, Level );
Alan Mishchenko committed
206 207
    Vec_PtrClear( vNodes );
    // collect the nodes in the implication supergate
Alan Mishchenko committed
208
    RetValue = Dar_BalanceCone_rec( pObj, pObj, vNodes );
209
    assert( RetValue != 0 || vNodes->nSize > 1 );
Alan Mishchenko committed
210
    // unmark the visited nodes
211
    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
Alan Mishchenko committed
212
        Aig_Regular(pObj)->fMarkB = 0;
Alan Mishchenko committed
213 214 215 216 217 218
    // if we found the node and its complement in the same implication supergate, 
    // return empty set of nodes (meaning that we should use constant-0 node)
    if ( RetValue == -1 )
        vNodes->nSize = 0;
    return vNodes;
}
219
*/
220 221 222

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

Alan Mishchenko committed
223 224 225 226 227 228 229 230 231 232 233 234 235
  Synopsis    [Finds the left bound on the next candidate to be paired.]

  Description [The nodes in the array are in the decreasing order of levels. 
  The last node in the array has the smallest level. By default it would be paired 
  with the next node on the left. However, it may be possible to pair it with some
  other node on the left, in such a way that the new node is shared. This procedure
  finds the index of the left-most node, which can be paired with the last node.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
236
int Dar_BalanceFindLeft( Vec_Ptr_t * vSuper )
Alan Mishchenko committed
237
{
Alan Mishchenko committed
238
    Aig_Obj_t * pObjRight, * pObjLeft;
Alan Mishchenko committed
239 240 241 242 243 244
    int Current;
    // if two or less nodes, pair with the first
    if ( Vec_PtrSize(vSuper) < 3 )
        return 0;
    // set the pointer to the one before the last
    Current = Vec_PtrSize(vSuper) - 2;
245
    pObjRight = (Aig_Obj_t *)Vec_PtrEntry( vSuper, Current );
Alan Mishchenko committed
246 247 248 249
    // go through the nodes to the left of this one
    for ( Current--; Current >= 0; Current-- )
    {
        // get the next node on the left
250
        pObjLeft = (Aig_Obj_t *)Vec_PtrEntry( vSuper, Current );
Alan Mishchenko committed
251
        // if the level of this node is different, quit the loop
Alan Mishchenko committed
252
        if ( Aig_ObjLevel(Aig_Regular(pObjLeft)) != Aig_ObjLevel(Aig_Regular(pObjRight)) )
Alan Mishchenko committed
253 254 255 256
            break;
    }
    Current++;    
    // get the node, for which the equality holds
257
    pObjLeft = (Aig_Obj_t *)Vec_PtrEntry( vSuper, Current );
Alan Mishchenko committed
258
    assert( Aig_ObjLevel(Aig_Regular(pObjLeft)) == Aig_ObjLevel(Aig_Regular(pObjRight)) );
Alan Mishchenko committed
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
    return Current;
}

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

  Synopsis    [Moves closer to the end the node that is best for sharing.]

  Description [If there is no node with sharing, randomly chooses one of 
  the legal nodes.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
274
void Dar_BalancePermute( Aig_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor )
Alan Mishchenko committed
275
{
Alan Mishchenko committed
276
    Aig_Obj_t * pObj1, * pObj2, * pObj3, * pGhost;
Alan Mishchenko committed
277 278 279 280 281 282 283
    int RightBound, i;
    // get the right bound
    RightBound = Vec_PtrSize(vSuper) - 2;
    assert( LeftBound <= RightBound );
    if ( LeftBound == RightBound )
        return;
    // get the two last nodes
284 285
    pObj1 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, RightBound + 1 );
    pObj2 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, RightBound     );
Alan Mishchenko committed
286
    if ( Aig_Regular(pObj1) == p->pConst1 || Aig_Regular(pObj2) == p->pConst1 || Aig_Regular(pObj1) == Aig_Regular(pObj2) )
Alan Mishchenko committed
287 288 289 290
        return;
    // find the first node that can be shared
    for ( i = RightBound; i >= LeftBound; i-- )
    {
291
        pObj3 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, i );
Alan Mishchenko committed
292
        if ( Aig_Regular(pObj3) == p->pConst1 )
Alan Mishchenko committed
293 294 295 296 297
        {
            Vec_PtrWriteEntry( vSuper, i,          pObj2 );
            Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
            return;
        }
Alan Mishchenko committed
298 299 300 301 302 303 304 305
        if ( Aig_Regular(pObj1) == Aig_Regular(pObj3) )
        {
            if ( pObj3 == pObj2 )
                return;
            Vec_PtrWriteEntry( vSuper, i,          pObj2 );
            Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
            return;
        }
Alan Mishchenko committed
306 307
        pGhost = Aig_ObjCreateGhost( p, pObj1, pObj3, fExor? AIG_OBJ_EXOR : AIG_OBJ_AND );
        if ( Aig_TableLookup( p, pGhost ) )
Alan Mishchenko committed
308 309 310 311 312 313 314 315 316 317 318
        {
            if ( pObj3 == pObj2 )
                return;
            Vec_PtrWriteEntry( vSuper, i,          pObj2 );
            Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
            return;
        }
    }
/*
    // we did not find the node to share, randomize choice
    {
Alan Mishchenko committed
319
        int Choice = Aig_ManRandom(0) % (RightBound - LeftBound + 1);
Alan Mishchenko committed
320 321 322 323 324 325 326 327 328 329 330
        pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice );
        if ( pObj3 == pObj2 )
            return;
        Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 );
        Vec_PtrWriteEntry( vSuper, RightBound,         pObj3 );
    }
*/
}

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

Alan Mishchenko committed
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
  Synopsis    [Procedure used for sorting the nodes in decreasing order of levels.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Aig_NodeCompareLevelsDecrease( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 )
{
    int Diff = Aig_ObjLevel(Aig_Regular(*pp1)) - Aig_ObjLevel(Aig_Regular(*pp2));
    if ( Diff > 0 )
        return -1;
    if ( Diff < 0 ) 
        return 1;
347 348 349 350 351
    Diff = Aig_ObjId(Aig_Regular(*pp1)) - Aig_ObjId(Aig_Regular(*pp2));
    if ( Diff > 0 )
        return -1;
    if ( Diff < 0 ) 
        return 1;
Alan Mishchenko committed
352 353 354 355 356
    return 0; 
}

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

Alan Mishchenko committed
357 358 359 360 361 362 363 364 365
  Synopsis    [Inserts a new node in the order by levels.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
366
void Dar_BalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Aig_Obj_t * pObj, int fExor )
Alan Mishchenko committed
367
{
Alan Mishchenko committed
368
    Aig_Obj_t * pObj1, * pObj2;
Alan Mishchenko committed
369 370
    int i;
    if ( Vec_PtrPushUnique(vStore, pObj) )
371 372 373
    {
        if ( fExor )
            Vec_PtrRemove(vStore, pObj);
Alan Mishchenko committed
374
        return;
375
    }
Alan Mishchenko committed
376 377 378
    // find the p of the node
    for ( i = vStore->nSize-1; i > 0; i-- )
    {
379 380
        pObj1 = (Aig_Obj_t *)vStore->pArray[i  ];
        pObj2 = (Aig_Obj_t *)vStore->pArray[i-1];
Alan Mishchenko committed
381
        if ( Aig_ObjLevel(Aig_Regular(pObj1)) <= Aig_ObjLevel(Aig_Regular(pObj2)) )
Alan Mishchenko committed
382 383 384 385 386 387
            break;
        vStore->pArray[i  ] = pObj2;
        vStore->pArray[i-1] = pObj1;
    }
}

Alan Mishchenko committed
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
/**Function*************************************************************

  Synopsis    [Builds implication supergate.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Aig_Obj_t * Dar_BalanceBuildSuper( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel )
{
    Aig_Obj_t * pObj1, * pObj2;
    int LeftBound;
    assert( vSuper->nSize > 1 );
    // sort the new nodes by level in the decreasing order
405
    Vec_PtrSort( vSuper, (int (*)(const void *, const void *))Aig_NodeCompareLevelsDecrease );
Alan Mishchenko committed
406 407 408 409 410 411 412 413
    // balance the nodes
    while ( vSuper->nSize > 1 )
    {
        // find the left bound on the node to be paired
        LeftBound = (!fUpdateLevel)? 0 : Dar_BalanceFindLeft( vSuper );
        // find the node that can be shared (if no such node, randomize choice)
        Dar_BalancePermute( p, vSuper, LeftBound, Type == AIG_OBJ_EXOR );
        // pull out the last two nodes
414 415
        pObj1 = (Aig_Obj_t *)Vec_PtrPop(vSuper);
        pObj2 = (Aig_Obj_t *)Vec_PtrPop(vSuper);
416
        Dar_BalancePushUniqueOrderByLevel( vSuper, Aig_Oper(p, pObj1, pObj2, Type), Type == AIG_OBJ_EXOR );
Alan Mishchenko committed
417
    }
Alan Mishchenko committed
418
    return vSuper->nSize ? (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0) : Aig_ManConst0(p);
Alan Mishchenko committed
419 420
}

421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464

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

  Synopsis    [Returns affective support size.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Aig_BaseSize( Aig_Man_t * p, Aig_Obj_t * pObj, int nLutSize )
{
    int nBaseSize;
    pObj = Aig_Regular(pObj);
    if ( Aig_ObjIsConst1(pObj) )
        return 0;
    if ( Aig_ObjLevel(pObj) >= nLutSize )
        return 1;
    nBaseSize = Aig_SupportSize( p, pObj );
    if ( nBaseSize >= nLutSize )
        return 1;
    return nBaseSize;
}

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

  Synopsis    [Builds implication supergate.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Aig_Obj_t * Dar_BalanceBuildSuperTop( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel, int nLutSize )
{
    Vec_Ptr_t * vSubset;
    Aig_Obj_t * pObj;
    int i, nBaseSizeAll, nBaseSize;
    assert( vSuper->nSize > 1 );
    // sort the new nodes by level in the decreasing order
465
    Vec_PtrSort( vSuper, (int (*)(const void *, const void *))Aig_NodeCompareLevelsDecrease );
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
    // add one LUT at a time
    while ( Vec_PtrSize(vSuper) > 1 )
    {
        // isolate the group of nodes with nLutSize inputs
        nBaseSizeAll = 0;
        vSubset = Vec_PtrAlloc( nLutSize );
        Vec_PtrForEachEntryReverse( Aig_Obj_t *, vSuper, pObj, i )
        {
            nBaseSize = Aig_BaseSize( p, pObj, nLutSize );
            if ( nBaseSizeAll + nBaseSize > nLutSize && Vec_PtrSize(vSubset) > 1 )
                break;
            nBaseSizeAll += nBaseSize;
            Vec_PtrPush( vSubset, pObj );
        }
        // remove them from vSuper
        Vec_PtrShrink( vSuper, Vec_PtrSize(vSuper) - Vec_PtrSize(vSubset) );
        // create the new supergate
        pObj = Dar_BalanceBuildSuper( p, vSubset, Type, fUpdateLevel );
        Vec_PtrFree( vSubset );
        // add the new output
486
        Dar_BalancePushUniqueOrderByLevel( vSuper, pObj, Type == AIG_OBJ_EXOR );
487 488 489 490
    }
    return (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0);
}

Alan Mishchenko committed
491 492 493 494 495 496 497 498 499 500 501
/**Function*************************************************************

  Synopsis    [Returns the new node constructed.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
502
Aig_Obj_t * Dar_Balance_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel )
Alan Mishchenko committed
503 504 505 506 507 508 509 510
{
    Aig_Obj_t * pObjNew;
    Vec_Ptr_t * vSuper;
    int i;
    assert( !Aig_IsComplement(pObjOld) );
    assert( !Aig_ObjIsBuf(pObjOld) );
    // return if the result is known
    if ( pObjOld->pData )
511
        return (Aig_Obj_t *)pObjOld->pData;
Alan Mishchenko committed
512 513
    assert( Aig_ObjIsNode(pObjOld) );
    // get the implication supergate
514
    vSuper = Dar_BalanceCone( pObjOld, vStore, Level );
Alan Mishchenko committed
515 516
    // check if supergate contains two nodes in the opposite polarity
    if ( vSuper->nSize == 0 )
517
        return (Aig_Obj_t *)(pObjOld->pData = Aig_ManConst0(pNew));
Alan Mishchenko committed
518 519 520
    // for each old node, derive the new well-balanced node
    for ( i = 0; i < Vec_PtrSize(vSuper); i++ )
    {
521
        pObjNew = Dar_Balance_rec( pNew, Aig_Regular((Aig_Obj_t *)vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel );
522 523
        if ( pObjNew == NULL )
            return NULL;
524
        vSuper->pArray[i] = Aig_NotCond( pObjNew, Aig_IsComplement((Aig_Obj_t *)vSuper->pArray[i]) );
Alan Mishchenko committed
525
    }
526 527 528
    // check for exactly one node
    if ( vSuper->nSize == 1 )
        return (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0);
Alan Mishchenko committed
529
    // build the supergate
530 531 532
#ifdef USE_LUTSIZE_BALANCE
    pObjNew = Dar_BalanceBuildSuperTop( pNew, vSuper, Aig_ObjType(pObjOld), fUpdateLevel, 6 );
#else
Alan Mishchenko committed
533
    pObjNew = Dar_BalanceBuildSuper( pNew, vSuper, Aig_ObjType(pObjOld), fUpdateLevel );
534
#endif
535 536
    if ( pNew->Time2Quit && !(Aig_Regular(pObjNew)->Id & 255) && Abc_Clock() > pNew->Time2Quit )
        return NULL;
Alan Mishchenko committed
537 538 539
    // make sure the balanced node is not assigned
//    assert( pObjOld->Level >= Aig_Regular(pObjNew)->Level );
    assert( pObjOld->pData == NULL );
540
    return (Aig_Obj_t *)(pObjOld->pData = pObjNew);
Alan Mishchenko committed
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
}

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

  Synopsis    [Performs algebraic balancing of the AIG.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Aig_Man_t * Dar_ManBalance( Aig_Man_t * p, int fUpdateLevel )
{
    Aig_Man_t * pNew;
    Aig_Obj_t * pObj, * pDriver, * pObjNew;
    Vec_Vec_t * vStore;
    int i;
Alan Mishchenko committed
560
    assert( Aig_ManVerifyTopoOrder(p) );
Alan Mishchenko committed
561 562
    // create the new manager 
    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
563 564
    pNew->pName = Abc_UtilStrsav( p->pName );
    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
Alan Mishchenko committed
565
    pNew->nAsserts = p->nAsserts;
566
    pNew->nConstrs = p->nConstrs;
567
    pNew->nBarBufs = p->nBarBufs;
568
    pNew->Time2Quit = p->Time2Quit;
Alan Mishchenko committed
569 570 571 572 573 574 575 576 577
    if ( p->vFlopNums )
        pNew->vFlopNums = Vec_IntDup( p->vFlopNums );
    // map the PI nodes
    Aig_ManCleanData( p );
    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
    vStore = Vec_VecAlloc( 50 );
    if ( p->pManTime != NULL )
    {
        float arrTime;
578
        Tim_ManIncrementTravId( (Tim_Man_t *)p->pManTime );
579
        Aig_ManSetCioIds( p );
Alan Mishchenko committed
580 581 582 583
        Aig_ManForEachObj( p, pObj, i )
        {
            if ( Aig_ObjIsNode(pObj) || Aig_ObjIsConst1(pObj) )
                continue;
584
            if ( Aig_ObjIsCi(pObj) )
Alan Mishchenko committed
585 586
            {
                // copy the PI
587
                pObjNew = Aig_ObjCreateCi(pNew); 
Alan Mishchenko committed
588 589
                pObj->pData = pObjNew;
                // set the arrival time of the new PI
590
                arrTime = Tim_ManGetCiArrival( (Tim_Man_t *)p->pManTime, Aig_ObjCioId(pObj) );
Alan Mishchenko committed
591 592
                pObjNew->Level = (int)arrTime;
            }
593
            else if ( Aig_ObjIsCo(pObj) )
Alan Mishchenko committed
594 595 596
            {
                // perform balancing
                pDriver = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
597
                pObjNew = Dar_Balance_rec( pNew, Aig_Regular(pDriver), vStore, 0, fUpdateLevel );
598 599 600 601 602 603
                if ( pObjNew == NULL )
                {
                    Vec_VecFree( vStore );
                    Aig_ManStop( pNew );
                    return NULL;
                }
Alan Mishchenko committed
604 605 606
                pObjNew = Aig_NotCond( pObjNew, Aig_IsComplement(pDriver) );
                // save arrival time of the output
                arrTime = (float)Aig_Regular(pObjNew)->Level;
607
                Tim_ManSetCoArrival( (Tim_Man_t *)p->pManTime, Aig_ObjCioId(pObj), arrTime );
Alan Mishchenko committed
608
                // create PO
609
                pObjNew = Aig_ObjCreateCo( pNew, pObjNew );
Alan Mishchenko committed
610 611 612 613
            }
            else
                assert( 0 );
        }
614
        Aig_ManCleanCioIds( p );
615
        pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 );
Alan Mishchenko committed
616 617 618
    }
    else
    {
619
        Aig_ManForEachCi( p, pObj, i )
Alan Mishchenko committed
620
        {
621
            pObjNew = Aig_ObjCreateCi(pNew); 
Alan Mishchenko committed
622 623 624
            pObjNew->Level = pObj->Level;
            pObj->pData = pObjNew;
        }
625
        if ( p->nBarBufs == 0 )
Alan Mishchenko committed
626
        {
627
            Aig_ManForEachCo( p, pObj, i )
628
            {
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
                pDriver = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
                pObjNew = Dar_Balance_rec( pNew, Aig_Regular(pDriver), vStore, 0, fUpdateLevel );
                if ( pObjNew == NULL )
                {
                    Vec_VecFree( vStore );
                    Aig_ManStop( pNew );
                    return NULL;
                }
                pObjNew = Aig_NotCond( pObjNew, Aig_IsComplement(pDriver) );
                pObjNew = Aig_ObjCreateCo( pNew, pObjNew );
            }
        }
        else
        {
            Vec_Ptr_t * vLits = Vec_PtrStart( Aig_ManCoNum(p) );
            Aig_ManForEachCo( p, pObj, i )
            {
                int k = i < p->nBarBufs ? Aig_ManCoNum(p) - p->nBarBufs + i : i - p->nBarBufs;
                pObj = Aig_ManCo( p, k );
                pDriver = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
                pObjNew = Dar_Balance_rec( pNew, Aig_Regular(pDriver), vStore, 0, fUpdateLevel );
                if ( pObjNew == NULL )
                {
                    Vec_VecFree( vStore );
                    Aig_ManStop( pNew );
                    return NULL;
                }
                pObjNew = Aig_NotCond( pObjNew, Aig_IsComplement(pDriver) );
                Vec_PtrWriteEntry( vLits, k, pObjNew );
                if ( i < p->nBarBufs )
                    Aig_ManCi(pNew, Aig_ManCiNum(p) - p->nBarBufs + i)->Level = Aig_Regular(pObjNew)->Level;
660
            }
661 662 663
            Aig_ManForEachCo( p, pObj, i )
                Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vLits, i) );
            Vec_PtrFree(vLits);
Alan Mishchenko committed
664 665 666 667 668
        }
    }
    Vec_VecFree( vStore );
    // remove dangling nodes
    Aig_ManCleanup( pNew );
Alan Mishchenko committed
669
    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
Alan Mishchenko committed
670 671 672 673 674 675 676 677
    // check the resulting AIG
    if ( !Aig_ManCheck(pNew) )
        printf( "Dar_ManBalance(): The check has failed.\n" );
    return pNew;
}

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

Alan Mishchenko committed
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706
  Synopsis    [Reproduces script "compress2".]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Aig_Man_t * Dar_ManBalanceXor( Aig_Man_t * pAig, int fExor, int fUpdateLevel, int fVerbose )
{
    Aig_Man_t * pAigXor, * pRes;
    if ( fExor )
    {
        pAigXor = Aig_ManDupExor( pAig );
        if ( fVerbose )
            Dar_BalancePrintStats( pAigXor );
        pRes = Dar_ManBalance( pAigXor, fUpdateLevel );
        Aig_ManStop( pAigXor );
    }
    else
    {
        pRes = Dar_ManBalance( pAig, fUpdateLevel );
    }
    return pRes;
}

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

Alan Mishchenko committed
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739
  Synopsis    [Inserts a new node in the order by levels.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Dar_BalancePrintStats( Aig_Man_t * p )
{
    Vec_Ptr_t * vSuper;
    Aig_Obj_t * pObj, * pTemp;
    int i, k;
    if ( Aig_ManExorNum(p) == 0 )
    {
        printf( "There is no EXOR gates.\n" );
        return;
    }
    Aig_ManForEachExor( p, pObj, i )
    {
        Aig_ObjFanin0(pObj)->fMarkA = 1;
        Aig_ObjFanin1(pObj)->fMarkA = 1;
        assert( !Aig_ObjFaninC0(pObj) );
        assert( !Aig_ObjFaninC1(pObj) );
    }
    vSuper = Vec_PtrAlloc( 1000 );
    Aig_ManForEachExor( p, pObj, i )
    {
        if ( pObj->fMarkA && pObj->nRefs == 1 )
            continue;
        Vec_PtrClear( vSuper );
        Dar_BalanceCone_rec( pObj, pObj, vSuper );
740
        Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pTemp, k )
Alan Mishchenko committed
741 742 743 744
            pTemp->fMarkB = 0;
        if ( Vec_PtrSize(vSuper) < 3 )
            continue;
        printf( "  %d(", Vec_PtrSize(vSuper) );
745
        Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pTemp, k )
Alan Mishchenko committed
746 747 748 749 750 751 752 753
            printf( " %d", pTemp->Level );
        printf( " )" );
    }
    Vec_PtrFree( vSuper );
    Aig_ManForEachObj( p, pObj, i )
        pObj->fMarkA = 0;
    printf( "\n" );
}
Alan Mishchenko committed
754 755 756 757 758

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

759

760 761
ABC_NAMESPACE_IMPL_END