ivyBalance.c 14.1 KB
Newer Older
Alan Mishchenko committed
1 2
/**CFile****************************************************************

Alan Mishchenko committed
3
  FileName    [ivyBalance.c]
Alan Mishchenko committed
4 5 6

  SystemName  [ABC: Logic synthesis and verification system.]

Alan Mishchenko committed
7
  PackageName [And-Inverter Graph package.]
Alan Mishchenko committed
8 9 10 11 12 13 14 15 16

  Synopsis    [Algebraic AIG balancing.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - May 11, 2006.]

Alan Mishchenko committed
17
  Revision    [$Id: ivyBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
Alan Mishchenko committed
18 19

***********************************************************************/
Alan Mishchenko committed
20

Alan Mishchenko committed
21
#include "ivy.h"
Alan Mishchenko committed
22

23 24 25
ABC_NAMESPACE_IMPL_START


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

Alan Mishchenko committed
30 31 32 33 34
static int         Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel );
static Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level );
static int         Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper );
static void        Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor );
static void        Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj );
Alan Mishchenko committed
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

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

  Synopsis    [Performs algebraic balancing of the AIG.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
51
Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel )
Alan Mishchenko committed
52
{
Alan Mishchenko committed
53 54
    Ivy_Man_t * pNew;
    Ivy_Obj_t * pObj, * pDriver;
Alan Mishchenko committed
55
    Vec_Vec_t * vStore;
Alan Mishchenko committed
56 57 58
    int i, NewNodeId;
    // clean the old manager
    Ivy_ManCleanTravId( p );
Alan Mishchenko committed
59
    // create the new manager 
Alan Mishchenko committed
60 61 62 63 64 65 66 67
    pNew = Ivy_ManStart();
    // map the nodes
    Ivy_ManConst1(p)->TravId = Ivy_EdgeFromNode( Ivy_ManConst1(pNew) );
    Ivy_ManForEachPi( p, pObj, i )
        pObj->TravId = Ivy_EdgeFromNode( Ivy_ObjCreatePi(pNew) );
    // if HAIG is defined, trasfer the pointers to the PIs/latches
//    if ( p->pHaig )
//        Ivy_ManHaigTrasfer( p, pNew );
Alan Mishchenko committed
68 69
    // balance the AIG
    vStore = Vec_VecAlloc( 50 );
Alan Mishchenko committed
70
    Ivy_ManForEachPo( p, pObj, i )
Alan Mishchenko committed
71
    {
Alan Mishchenko committed
72 73 74 75
        pDriver   = Ivy_ObjReal( Ivy_ObjChild0(pObj) );
        NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(pDriver), vStore, 0, fUpdateLevel );
        NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(pDriver) );
        Ivy_ObjCreatePo( pNew, Ivy_EdgeToNode(pNew, NewNodeId) );
Alan Mishchenko committed
76 77
    }
    Vec_VecFree( vStore );
Alan Mishchenko committed
78
    if ( (i = Ivy_ManCleanup( pNew )) )
Alan Mishchenko committed
79
    {
Alan Mishchenko committed
80
//        printf( "Cleanup after balancing removed %d dangling nodes.\n", i );
Alan Mishchenko committed
81
    }
Alan Mishchenko committed
82
    // check the resulting AIG
Alan Mishchenko committed
83 84
    if ( !Ivy_ManCheck(pNew) )
        printf( "Ivy_ManBalance(): The check has failed.\n" );
Alan Mishchenko committed
85 86 87 88 89
    return pNew;
}

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

Alan Mishchenko committed
90
  Synopsis    [Procedure used for sorting the nodes in decreasing order of levels.]
Alan Mishchenko committed
91 92 93 94 95 96 97 98

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
99
int Ivy_NodeCompareLevelsDecrease( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 )
Alan Mishchenko committed
100
{
Alan Mishchenko committed
101 102 103 104 105
    int Diff = Ivy_Regular(*pp1)->Level - Ivy_Regular(*pp2)->Level;
    if ( Diff > 0 )
        return -1;
    if ( Diff < 0 ) 
        return 1;
106 107 108 109 110
    Diff = Ivy_Regular(*pp1)->Id - Ivy_Regular(*pp2)->Id;
    if ( Diff > 0 )
        return -1;
    if ( Diff < 0 ) 
        return 1;
Alan Mishchenko committed
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
    return 0; 
}

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

  Synopsis    [Returns the ID of new node constructed.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel )
{
    Ivy_Obj_t * pObjNew;
Alan Mishchenko committed
128
    Vec_Ptr_t * vSuper;
Alan Mishchenko committed
129 130 131
    int i, NewNodeId;
    assert( !Ivy_IsComplement(pObjOld) );
    assert( !Ivy_ObjIsBuf(pObjOld) );
Alan Mishchenko committed
132
    // return if the result is known
Alan Mishchenko committed
133 134 135 136 137
    if ( Ivy_ObjIsConst1(pObjOld) )
        return pObjOld->TravId;
    if ( pObjOld->TravId )
        return pObjOld->TravId;
    assert( Ivy_ObjIsNode(pObjOld) );
Alan Mishchenko committed
138
    // get the implication supergate
Alan Mishchenko committed
139
    vSuper = Ivy_NodeBalanceCone( pObjOld, vStore, Level );
Alan Mishchenko committed
140
    if ( vSuper->nSize == 0 )
Alan Mishchenko committed
141 142 143 144 145
    { // it means that the supergate contains two nodes in the opposite polarity
        pObjOld->TravId = Ivy_EdgeFromNode( Ivy_ManConst0(pNew) );
        return pObjOld->TravId;
    }
    if ( vSuper->nSize < 2 )
Alan Mishchenko committed
146 147
        printf( "BUG!\n" );
    // for each old node, derive the new well-balanced node
Alan Mishchenko committed
148
    for ( i = 0; i < vSuper->nSize; i++ )
Alan Mishchenko committed
149
    {
150 151
        NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular((Ivy_Obj_t *)vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel );
        NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement((Ivy_Obj_t *)vSuper->pArray[i]) );
Alan Mishchenko committed
152
        vSuper->pArray[i] = Ivy_EdgeToNode( pNew, NewNodeId );
Alan Mishchenko committed
153 154
    }
    // build the supergate
Alan Mishchenko committed
155 156
    pObjNew = Ivy_NodeBalanceBuildSuper( pNew, vSuper, Ivy_ObjType(pObjOld), fUpdateLevel );
    vSuper->nSize = 0;
Alan Mishchenko committed
157
    // make sure the balanced node is not assigned
Alan Mishchenko committed
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
    assert( pObjOld->TravId == 0 );
    pObjOld->TravId = Ivy_EdgeFromNode( pObjNew );
//    assert( pObjOld->Level >= Ivy_Regular(pObjNew)->Level );
    return pObjOld->TravId;
}

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

  Synopsis    [Builds implication supergate.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel )
{
    Ivy_Obj_t * pObj1, * pObj2;
    int LeftBound;
    assert( vSuper->nSize > 1 );
    // sort the new nodes by level in the decreasing order
181
    Vec_PtrSort( vSuper, (int (*)(void))Ivy_NodeCompareLevelsDecrease );
Alan Mishchenko committed
182 183 184 185 186 187 188 189
    // balance the nodes
    while ( vSuper->nSize > 1 )
    {
        // find the left bound on the node to be paired
        LeftBound = (!fUpdateLevel)? 0 : Ivy_NodeBalanceFindLeft( vSuper );
        // find the node that can be shared (if no such node, randomize choice)
        Ivy_NodeBalancePermute( p, vSuper, LeftBound, Type == IVY_EXOR );
        // pull out the last two nodes
190 191
        pObj1 = (Ivy_Obj_t *)Vec_PtrPop(vSuper);
        pObj2 = (Ivy_Obj_t *)Vec_PtrPop(vSuper);
Alan Mishchenko committed
192 193
        Ivy_NodeBalancePushUniqueOrderByLevel( vSuper, Ivy_Oper(p, pObj1, pObj2, Type) );
    }
194
    return (Ivy_Obj_t *)Vec_PtrEntry(vSuper, 0);
Alan Mishchenko committed
195 196 197 198 199 200 201 202 203 204 205 206 207
}

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

  Synopsis    [Collects the nodes of the supergate.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
208
int Ivy_NodeBalanceCone_rec( Ivy_Obj_t * pRoot, Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper )
Alan Mishchenko committed
209 210 211
{
    int RetValue1, RetValue2, i;
    // check if the node is visited
Alan Mishchenko committed
212
    if ( Ivy_Regular(pObj)->fMarkB )
Alan Mishchenko committed
213 214 215 216 217 218 219
    {
        // 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++ )
Alan Mishchenko committed
220
            if ( vSuper->pArray[i] == Ivy_Not(pObj) )
Alan Mishchenko committed
221 222 223 224 225
                return -1;
        assert( 0 );
        return 0;
    }
    // if the new node is complemented or a PI, another gate begins
Alan Mishchenko committed
226
    if ( pObj != pRoot && (Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Ivy_ObjType(pRoot) || Ivy_ObjRefs(pObj) > 1 || Vec_PtrSize(vSuper) > 10000) )
Alan Mishchenko committed
227 228
    {
        Vec_PtrPush( vSuper, pObj );
Alan Mishchenko committed
229
        Ivy_Regular(pObj)->fMarkB = 1;
Alan Mishchenko committed
230 231
        return 0;
    }
Alan Mishchenko committed
232 233
    assert( !Ivy_IsComplement(pObj) );
    assert( Ivy_ObjIsNode(pObj) );
Alan Mishchenko committed
234
    // go through the branches
Alan Mishchenko committed
235 236
    RetValue1 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild0(pObj) ), vSuper );
    RetValue2 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild1(pObj) ), vSuper );
Alan Mishchenko committed
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
    if ( RetValue1 == -1 || RetValue2 == -1 )
        return -1;
    // return 1 if at least one branch has a duplicate
    return RetValue1 || RetValue2;
}

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

  Synopsis    [Collects the nodes of the supergate.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
254
Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level )
Alan Mishchenko committed
255 256 257
{
    Vec_Ptr_t * vNodes;
    int RetValue, i;
Alan Mishchenko committed
258
    assert( !Ivy_IsComplement(pObj) );
Alan Mishchenko committed
259 260 261 262
    // extend the storage
    if ( Vec_VecSize( vStore ) <= Level )
        Vec_VecPush( vStore, Level, 0 );
    // get the temporary array of nodes
263
    vNodes = Vec_VecEntry( vStore, Level );
Alan Mishchenko committed
264 265
    Vec_PtrClear( vNodes );
    // collect the nodes in the implication supergate
Alan Mishchenko committed
266
    RetValue = Ivy_NodeBalanceCone_rec( pObj, pObj, vNodes );
Alan Mishchenko committed
267 268
    assert( vNodes->nSize > 1 );
    // unmark the visited nodes
269
    Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, i )
Alan Mishchenko committed
270
        Ivy_Regular(pObj)->fMarkB = 0;
Alan Mishchenko committed
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
    // 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;
}

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

  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
293
int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper )
Alan Mishchenko committed
294
{
Alan Mishchenko committed
295
    Ivy_Obj_t * pObjRight, * pObjLeft;
Alan Mishchenko committed
296 297 298 299 300 301
    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;
302
    pObjRight = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, Current );
Alan Mishchenko committed
303 304 305 306
    // go through the nodes to the left of this one
    for ( Current--; Current >= 0; Current-- )
    {
        // get the next node on the left
307
        pObjLeft = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, Current );
Alan Mishchenko committed
308
        // if the level of this node is different, quit the loop
Alan Mishchenko committed
309
        if ( Ivy_Regular(pObjLeft)->Level != Ivy_Regular(pObjRight)->Level )
Alan Mishchenko committed
310 311 312 313
            break;
    }
    Current++;    
    // get the node, for which the equality holds
314
    pObjLeft = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, Current );
Alan Mishchenko committed
315
    assert( Ivy_Regular(pObjLeft)->Level == Ivy_Regular(pObjRight)->Level );
Alan Mishchenko committed
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
    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
331
void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor )
Alan Mishchenko committed
332
{
Alan Mishchenko committed
333
    Ivy_Obj_t * pObj1, * pObj2, * pObj3, * pGhost;
Alan Mishchenko committed
334 335 336 337 338 339 340
    int RightBound, i;
    // get the right bound
    RightBound = Vec_PtrSize(vSuper) - 2;
    assert( LeftBound <= RightBound );
    if ( LeftBound == RightBound )
        return;
    // get the two last nodes
341 342
    pObj1 = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, RightBound + 1 );
    pObj2 = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, RightBound     );
Alan Mishchenko committed
343
    if ( Ivy_Regular(pObj1) == p->pConst1 || Ivy_Regular(pObj2) == p->pConst1 )
Alan Mishchenko committed
344 345 346 347
        return;
    // find the first node that can be shared
    for ( i = RightBound; i >= LeftBound; i-- )
    {
348
        pObj3 = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, i );
Alan Mishchenko committed
349
        if ( Ivy_Regular(pObj3) == p->pConst1 )
Alan Mishchenko committed
350 351 352 353 354
        {
            Vec_PtrWriteEntry( vSuper, i,          pObj2 );
            Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
            return;
        }
Alan Mishchenko committed
355 356
        pGhost = Ivy_ObjCreateGhost( p, pObj1, pObj3, fExor? IVY_EXOR : IVY_AND, IVY_INIT_NONE );
        if ( Ivy_TableLookup( p, pGhost ) )
Alan Mishchenko committed
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
        {
            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
    {
        int Choice = rand() % (RightBound - LeftBound + 1);
        pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice );
        if ( pObj3 == pObj2 )
            return;
        Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 );
        Vec_PtrWriteEntry( vSuper, RightBound,         pObj3 );
    }
*/
}

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

  Synopsis    [Inserts a new node in the order by levels.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
389
void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj )
Alan Mishchenko committed
390
{
Alan Mishchenko committed
391
    Ivy_Obj_t * pObj1, * pObj2;
Alan Mishchenko committed
392 393 394 395 396 397
    int i;
    if ( Vec_PtrPushUnique(vStore, pObj) )
        return;
    // find the p of the node
    for ( i = vStore->nSize-1; i > 0; i-- )
    {
398 399
        pObj1 = (Ivy_Obj_t *)vStore->pArray[i  ];
        pObj2 = (Ivy_Obj_t *)vStore->pArray[i-1];
Alan Mishchenko committed
400
        if ( Ivy_Regular(pObj1)->Level <= Ivy_Regular(pObj2)->Level )
Alan Mishchenko committed
401 402 403 404 405 406 407 408 409 410 411 412
            break;
        vStore->pArray[i  ] = pObj2;
        vStore->pArray[i-1] = pObj1;
    }
}


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


413 414
ABC_NAMESPACE_IMPL_END