hopBalance.c 13.7 KB
Newer Older
Alan Mishchenko committed
1 2
/**CFile****************************************************************

Alan Mishchenko committed
3
  FileName    [hopBalance.c]
Alan Mishchenko committed
4 5 6 7 8 9 10 11 12 13 14 15 16

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Minimalistic And-Inverter Graph package.]

  Synopsis    [Algebraic AIG balancing.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

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

Alan Mishchenko committed
17
  Revision    [$Id: hopBalance.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 "hop.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 Hop_Obj_t * Hop_NodeBalance_rec( Hop_Man_t * pNew, Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel );
static Vec_Ptr_t * Hop_NodeBalanceCone( Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level );
static int         Hop_NodeBalanceFindLeft( Vec_Ptr_t * vSuper );
static void        Hop_NodeBalancePermute( Hop_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor );
static void        Hop_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Hop_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
Hop_Man_t * Hop_ManBalance( Hop_Man_t * p, int fUpdateLevel )
Alan Mishchenko committed
52
{
Alan Mishchenko committed
53 54
    Hop_Man_t * pNew;
    Hop_Obj_t * pObj, * pObjNew;
Alan Mishchenko committed
55 56 57
    Vec_Vec_t * vStore;
    int i;
    // create the new manager 
Alan Mishchenko committed
58
    pNew = Hop_ManStart();
Alan Mishchenko committed
59 60
    pNew->fRefCount = 0;
    // map the PI nodes
Alan Mishchenko committed
61 62 63 64
    Hop_ManCleanData( p );
    Hop_ManConst1(p)->pData = Hop_ManConst1(pNew);
    Hop_ManForEachPi( p, pObj, i )
        pObj->pData = Hop_ObjCreatePi(pNew);
Alan Mishchenko committed
65 66
    // balance the AIG
    vStore = Vec_VecAlloc( 50 );
Alan Mishchenko committed
67
    Hop_ManForEachPo( p, pObj, i )
Alan Mishchenko committed
68
    {
Alan Mishchenko committed
69 70
        pObjNew = Hop_NodeBalance_rec( pNew, Hop_ObjFanin0(pObj), vStore, 0, fUpdateLevel );
        Hop_ObjCreatePo( pNew, Hop_NotCond( pObjNew, Hop_ObjFaninC0(pObj) ) );
Alan Mishchenko committed
71 72 73
    }
    Vec_VecFree( vStore );
    // remove dangling nodes
Alan Mishchenko committed
74 75
//    Hop_ManCreateRefs( pNew );
//    if ( i = Hop_ManCleanup( pNew ) )
Alan Mishchenko committed
76 77
//        printf( "Cleanup after balancing removed %d dangling nodes.\n", i );
    // check the resulting AIG
Alan Mishchenko committed
78 79
    if ( !Hop_ManCheck(pNew) )
        printf( "Hop_ManBalance(): The check has failed.\n" );
Alan Mishchenko committed
80 81 82 83 84 85 86 87 88 89 90 91 92 93
    return pNew;
}

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

  Synopsis    [Returns the new node constructed.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
94
Hop_Obj_t * Hop_NodeBalance_rec( Hop_Man_t * pNew, Hop_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel )
Alan Mishchenko committed
95
{
Alan Mishchenko committed
96
    Hop_Obj_t * pObjNew;
Alan Mishchenko committed
97 98
    Vec_Ptr_t * vSuper;
    int i;
Alan Mishchenko committed
99
    assert( !Hop_IsComplement(pObjOld) );
Alan Mishchenko committed
100 101
    // return if the result is known
    if ( pObjOld->pData )
102
        return (Hop_Obj_t *)pObjOld->pData;
Alan Mishchenko committed
103
    assert( Hop_ObjIsNode(pObjOld) );
Alan Mishchenko committed
104
    // get the implication supergate
Alan Mishchenko committed
105
    vSuper = Hop_NodeBalanceCone( pObjOld, vStore, Level );
Alan Mishchenko committed
106 107
    // check if supergate contains two nodes in the opposite polarity
    if ( vSuper->nSize == 0 )
108
        return (Hop_Obj_t *)(pObjOld->pData = Hop_ManConst0(pNew));
Alan Mishchenko committed
109 110 111 112 113
    if ( Vec_PtrSize(vSuper) < 2 )
        printf( "BUG!\n" );
    // for each old node, derive the new well-balanced node
    for ( i = 0; i < Vec_PtrSize(vSuper); i++ )
    {
114 115
        pObjNew = Hop_NodeBalance_rec( pNew, Hop_Regular((Hop_Obj_t *)vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel );
        vSuper->pArray[i] = Hop_NotCond( pObjNew, Hop_IsComplement((Hop_Obj_t *)vSuper->pArray[i]) );
Alan Mishchenko committed
116 117
    }
    // build the supergate
Alan Mishchenko committed
118
    pObjNew = Hop_NodeBalanceBuildSuper( pNew, vSuper, Hop_ObjType(pObjOld), fUpdateLevel );
Alan Mishchenko committed
119
    // make sure the balanced node is not assigned
Alan Mishchenko committed
120
//    assert( pObjOld->Level >= Hop_Regular(pObjNew)->Level );
Alan Mishchenko committed
121
    assert( pObjOld->pData == NULL );
122
    return (Hop_Obj_t *)(pObjOld->pData = pObjNew);
Alan Mishchenko committed
123 124 125 126 127 128 129 130 131 132 133 134 135
}

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

  Synopsis    [Collects the nodes of the supergate.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
136
int Hop_NodeBalanceCone_rec( Hop_Obj_t * pRoot, Hop_Obj_t * pObj, Vec_Ptr_t * vSuper )
Alan Mishchenko committed
137 138 139
{
    int RetValue1, RetValue2, i;
    // check if the node is visited
Alan Mishchenko committed
140
    if ( Hop_Regular(pObj)->fMarkB )
Alan Mishchenko committed
141 142 143 144 145 146 147
    {
        // 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
148
            if ( vSuper->pArray[i] == Hop_Not(pObj) )
Alan Mishchenko committed
149 150 151 152 153
                return -1;
        assert( 0 );
        return 0;
    }
    // if the new node is complemented or a PI, another gate begins
Alan Mishchenko committed
154
    if ( pObj != pRoot && (Hop_IsComplement(pObj) || Hop_ObjType(pObj) != Hop_ObjType(pRoot) || Hop_ObjRefs(pObj) > 1 || Vec_PtrSize(vSuper) > 10000) )
Alan Mishchenko committed
155 156
    {
        Vec_PtrPush( vSuper, pObj );
Alan Mishchenko committed
157
        Hop_Regular(pObj)->fMarkB = 1;
Alan Mishchenko committed
158 159
        return 0;
    }
Alan Mishchenko committed
160 161
    assert( !Hop_IsComplement(pObj) );
    assert( Hop_ObjIsNode(pObj) );
Alan Mishchenko committed
162
    // go through the branches
Alan Mishchenko committed
163 164
    RetValue1 = Hop_NodeBalanceCone_rec( pRoot, Hop_ObjChild0(pObj), vSuper );
    RetValue2 = Hop_NodeBalanceCone_rec( pRoot, Hop_ObjChild1(pObj), vSuper );
Alan Mishchenko committed
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
    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
182
Vec_Ptr_t * Hop_NodeBalanceCone( Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level )
Alan Mishchenko committed
183 184 185
{
    Vec_Ptr_t * vNodes;
    int RetValue, i;
Alan Mishchenko committed
186
    assert( !Hop_IsComplement(pObj) );
Alan Mishchenko committed
187 188 189 190
    // extend the storage
    if ( Vec_VecSize( vStore ) <= Level )
        Vec_VecPush( vStore, Level, 0 );
    // get the temporary array of nodes
191
    vNodes = Vec_VecEntry( vStore, Level );
Alan Mishchenko committed
192 193
    Vec_PtrClear( vNodes );
    // collect the nodes in the implication supergate
Alan Mishchenko committed
194
    RetValue = Hop_NodeBalanceCone_rec( pObj, pObj, vNodes );
Alan Mishchenko committed
195 196
    assert( vNodes->nSize > 1 );
    // unmark the visited nodes
197
    Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i )
Alan Mishchenko committed
198
        Hop_Regular(pObj)->fMarkB = 0;
Alan Mishchenko committed
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
    // 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    [Procedure used for sorting the nodes in decreasing order of levels.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
217
int Hop_NodeCompareLevelsDecrease( Hop_Obj_t ** pp1, Hop_Obj_t ** pp2 )
Alan Mishchenko committed
218
{
Alan Mishchenko committed
219
    int Diff = Hop_ObjLevel(Hop_Regular(*pp1)) - Hop_ObjLevel(Hop_Regular(*pp2));
Alan Mishchenko committed
220 221 222 223
    if ( Diff > 0 )
        return -1;
    if ( Diff < 0 ) 
        return 1;
224 225 226 227 228
    Diff = Hop_Regular(*pp1)->Id - Hop_Regular(*pp2)->Id;
    if ( Diff > 0 )
        return -1;
    if ( Diff < 0 ) 
        return 1;
Alan Mishchenko committed
229 230 231 232 233 234 235 236 237 238 239 240 241 242
    return 0; 
}

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

  Synopsis    [Builds implication supergate.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
243
Hop_Obj_t * Hop_NodeBalanceBuildSuper( Hop_Man_t * p, Vec_Ptr_t * vSuper, Hop_Type_t Type, int fUpdateLevel )
Alan Mishchenko committed
244
{
Alan Mishchenko committed
245
    Hop_Obj_t * pObj1, * pObj2;
Alan Mishchenko committed
246 247 248
    int LeftBound;
    assert( vSuper->nSize > 1 );
    // sort the new nodes by level in the decreasing order
249
    Vec_PtrSort( vSuper, (int (*)(void))Hop_NodeCompareLevelsDecrease );
Alan Mishchenko committed
250 251 252 253
    // balance the nodes
    while ( vSuper->nSize > 1 )
    {
        // find the left bound on the node to be paired
Alan Mishchenko committed
254
        LeftBound = (!fUpdateLevel)? 0 : Hop_NodeBalanceFindLeft( vSuper );
Alan Mishchenko committed
255
        // find the node that can be shared (if no such node, randomize choice)
Alan Mishchenko committed
256
        Hop_NodeBalancePermute( p, vSuper, LeftBound, Type == AIG_EXOR );
Alan Mishchenko committed
257
        // pull out the last two nodes
258 259
        pObj1 = (Hop_Obj_t *)Vec_PtrPop(vSuper);
        pObj2 = (Hop_Obj_t *)Vec_PtrPop(vSuper);
Alan Mishchenko committed
260
        Hop_NodeBalancePushUniqueOrderByLevel( vSuper, Hop_Oper(p, pObj1, pObj2, Type) );
Alan Mishchenko committed
261
    }
262
    return (Hop_Obj_t *)Vec_PtrEntry(vSuper, 0);
Alan Mishchenko committed
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
}

/**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
280
int Hop_NodeBalanceFindLeft( Vec_Ptr_t * vSuper )
Alan Mishchenko committed
281
{
Alan Mishchenko committed
282
    Hop_Obj_t * pObjRight, * pObjLeft;
Alan Mishchenko committed
283 284 285 286 287 288
    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;
289
    pObjRight = (Hop_Obj_t *)Vec_PtrEntry( vSuper, Current );
Alan Mishchenko committed
290 291 292 293
    // go through the nodes to the left of this one
    for ( Current--; Current >= 0; Current-- )
    {
        // get the next node on the left
294
        pObjLeft = (Hop_Obj_t *)Vec_PtrEntry( vSuper, Current );
Alan Mishchenko committed
295
        // if the level of this node is different, quit the loop
Alan Mishchenko committed
296
        if ( Hop_ObjLevel(Hop_Regular(pObjLeft)) != Hop_ObjLevel(Hop_Regular(pObjRight)) )
Alan Mishchenko committed
297 298 299 300
            break;
    }
    Current++;    
    // get the node, for which the equality holds
301
    pObjLeft = (Hop_Obj_t *)Vec_PtrEntry( vSuper, Current );
Alan Mishchenko committed
302
    assert( Hop_ObjLevel(Hop_Regular(pObjLeft)) == Hop_ObjLevel(Hop_Regular(pObjRight)) );
Alan Mishchenko committed
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
    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
318
void Hop_NodeBalancePermute( Hop_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor )
Alan Mishchenko committed
319
{
Alan Mishchenko committed
320
    Hop_Obj_t * pObj1, * pObj2, * pObj3, * pGhost;
Alan Mishchenko committed
321 322 323 324 325 326 327
    int RightBound, i;
    // get the right bound
    RightBound = Vec_PtrSize(vSuper) - 2;
    assert( LeftBound <= RightBound );
    if ( LeftBound == RightBound )
        return;
    // get the two last nodes
328 329
    pObj1 = (Hop_Obj_t *)Vec_PtrEntry( vSuper, RightBound + 1 );
    pObj2 = (Hop_Obj_t *)Vec_PtrEntry( vSuper, RightBound     );
Alan Mishchenko committed
330
    if ( Hop_Regular(pObj1) == p->pConst1 || Hop_Regular(pObj2) == p->pConst1 )
Alan Mishchenko committed
331 332 333 334
        return;
    // find the first node that can be shared
    for ( i = RightBound; i >= LeftBound; i-- )
    {
335
        pObj3 = (Hop_Obj_t *)Vec_PtrEntry( vSuper, i );
Alan Mishchenko committed
336
        if ( Hop_Regular(pObj3) == p->pConst1 )
Alan Mishchenko committed
337 338 339 340 341
        {
            Vec_PtrWriteEntry( vSuper, i,          pObj2 );
            Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
            return;
        }
Alan Mishchenko committed
342 343
        pGhost = Hop_ObjCreateGhost( p, pObj1, pObj3, fExor? AIG_EXOR : AIG_AND );
        if ( Hop_TableLookup( p, pGhost ) )
Alan Mishchenko committed
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
        {
            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
376
void Hop_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Hop_Obj_t * pObj )
Alan Mishchenko committed
377
{
Alan Mishchenko committed
378
    Hop_Obj_t * pObj1, * pObj2;
Alan Mishchenko committed
379 380 381 382 383 384
    int i;
    if ( Vec_PtrPushUnique(vStore, pObj) )
        return;
    // find the p of the node
    for ( i = vStore->nSize-1; i > 0; i-- )
    {
385 386
        pObj1 = (Hop_Obj_t *)vStore->pArray[i  ];
        pObj2 = (Hop_Obj_t *)vStore->pArray[i-1];
Alan Mishchenko committed
387
        if ( Hop_ObjLevel(Hop_Regular(pObj1)) <= Hop_ObjLevel(Hop_Regular(pObj2)) )
Alan Mishchenko committed
388 389 390 391 392 393 394 395 396 397 398 399
            break;
        vStore->pArray[i  ] = pObj2;
        vStore->pArray[i-1] = pObj1;
    }
}


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


400 401
ABC_NAMESPACE_IMPL_END