00001
00021 #include "ivy.h"
00022
00026
00027 static int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel );
00028 static Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level );
00029 static int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper );
00030 static void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor );
00031 static void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj );
00032
00036
00048 Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel )
00049 {
00050 Ivy_Man_t * pNew;
00051 Ivy_Obj_t * pObj, * pDriver;
00052 Vec_Vec_t * vStore;
00053 int i, NewNodeId;
00054
00055 Ivy_ManCleanTravId( p );
00056
00057 pNew = Ivy_ManStart();
00058
00059 Ivy_ManConst1(p)->TravId = Ivy_EdgeFromNode( Ivy_ManConst1(pNew) );
00060 Ivy_ManForEachPi( p, pObj, i )
00061 pObj->TravId = Ivy_EdgeFromNode( Ivy_ObjCreatePi(pNew) );
00062
00063
00064
00065
00066 vStore = Vec_VecAlloc( 50 );
00067 Ivy_ManForEachPo( p, pObj, i )
00068 {
00069 pDriver = Ivy_ObjReal( Ivy_ObjChild0(pObj) );
00070 NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(pDriver), vStore, 0, fUpdateLevel );
00071 NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(pDriver) );
00072 Ivy_ObjCreatePo( pNew, Ivy_EdgeToNode(pNew, NewNodeId) );
00073 }
00074 Vec_VecFree( vStore );
00075 if ( i = Ivy_ManCleanup( pNew ) )
00076 {
00077
00078 }
00079
00080 if ( !Ivy_ManCheck(pNew) )
00081 printf( "Ivy_ManBalance(): The check has failed.\n" );
00082 return pNew;
00083 }
00084
00096 int Ivy_NodeCompareLevelsDecrease( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 )
00097 {
00098 int Diff = Ivy_Regular(*pp1)->Level - Ivy_Regular(*pp2)->Level;
00099 if ( Diff > 0 )
00100 return -1;
00101 if ( Diff < 0 )
00102 return 1;
00103 return 0;
00104 }
00105
00117 int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel )
00118 {
00119 Ivy_Obj_t * pObjNew;
00120 Vec_Ptr_t * vSuper;
00121 int i, NewNodeId;
00122 assert( !Ivy_IsComplement(pObjOld) );
00123 assert( !Ivy_ObjIsBuf(pObjOld) );
00124
00125 if ( Ivy_ObjIsConst1(pObjOld) )
00126 return pObjOld->TravId;
00127 if ( pObjOld->TravId )
00128 return pObjOld->TravId;
00129 assert( Ivy_ObjIsNode(pObjOld) );
00130
00131 vSuper = Ivy_NodeBalanceCone( pObjOld, vStore, Level );
00132 if ( vSuper->nSize == 0 )
00133 {
00134 pObjOld->TravId = Ivy_EdgeFromNode( Ivy_ManConst0(pNew) );
00135 return pObjOld->TravId;
00136 }
00137 if ( vSuper->nSize < 2 )
00138 printf( "BUG!\n" );
00139
00140 for ( i = 0; i < vSuper->nSize; i++ )
00141 {
00142 NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel );
00143 NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(vSuper->pArray[i]) );
00144 vSuper->pArray[i] = Ivy_EdgeToNode( pNew, NewNodeId );
00145 }
00146
00147 pObjNew = Ivy_NodeBalanceBuildSuper( pNew, vSuper, Ivy_ObjType(pObjOld), fUpdateLevel );
00148 vSuper->nSize = 0;
00149
00150 assert( pObjOld->TravId == 0 );
00151 pObjOld->TravId = Ivy_EdgeFromNode( pObjNew );
00152
00153 return pObjOld->TravId;
00154 }
00155
00167 Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel )
00168 {
00169 Ivy_Obj_t * pObj1, * pObj2;
00170 int LeftBound;
00171 assert( vSuper->nSize > 1 );
00172
00173 Vec_PtrSort( vSuper, Ivy_NodeCompareLevelsDecrease );
00174
00175 while ( vSuper->nSize > 1 )
00176 {
00177
00178 LeftBound = (!fUpdateLevel)? 0 : Ivy_NodeBalanceFindLeft( vSuper );
00179
00180 Ivy_NodeBalancePermute( p, vSuper, LeftBound, Type == IVY_EXOR );
00181
00182 pObj1 = Vec_PtrPop(vSuper);
00183 pObj2 = Vec_PtrPop(vSuper);
00184 Ivy_NodeBalancePushUniqueOrderByLevel( vSuper, Ivy_Oper(p, pObj1, pObj2, Type) );
00185 }
00186 return Vec_PtrEntry(vSuper, 0);
00187 }
00188
00200 int Ivy_NodeBalanceCone_rec( Ivy_Obj_t * pRoot, Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper )
00201 {
00202 int RetValue1, RetValue2, i;
00203
00204 if ( Ivy_Regular(pObj)->fMarkB )
00205 {
00206
00207 for ( i = 0; i < vSuper->nSize; i++ )
00208 if ( vSuper->pArray[i] == pObj )
00209 return 1;
00210
00211 for ( i = 0; i < vSuper->nSize; i++ )
00212 if ( vSuper->pArray[i] == Ivy_Not(pObj) )
00213 return -1;
00214 assert( 0 );
00215 return 0;
00216 }
00217
00218 if ( pObj != pRoot && (Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Ivy_ObjType(pRoot) || Ivy_ObjRefs(pObj) > 1) )
00219 {
00220 Vec_PtrPush( vSuper, pObj );
00221 Ivy_Regular(pObj)->fMarkB = 1;
00222 return 0;
00223 }
00224 assert( !Ivy_IsComplement(pObj) );
00225 assert( Ivy_ObjIsNode(pObj) );
00226
00227 RetValue1 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild0(pObj) ), vSuper );
00228 RetValue2 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild1(pObj) ), vSuper );
00229 if ( RetValue1 == -1 || RetValue2 == -1 )
00230 return -1;
00231
00232 return RetValue1 || RetValue2;
00233 }
00234
00246 Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level )
00247 {
00248 Vec_Ptr_t * vNodes;
00249 int RetValue, i;
00250 assert( !Ivy_IsComplement(pObj) );
00251
00252 if ( Vec_VecSize( vStore ) <= Level )
00253 Vec_VecPush( vStore, Level, 0 );
00254
00255 vNodes = Vec_VecEntry( vStore, Level );
00256 Vec_PtrClear( vNodes );
00257
00258 RetValue = Ivy_NodeBalanceCone_rec( pObj, pObj, vNodes );
00259 assert( vNodes->nSize > 1 );
00260
00261 Vec_PtrForEachEntry( vNodes, pObj, i )
00262 Ivy_Regular(pObj)->fMarkB = 0;
00263
00264
00265 if ( RetValue == -1 )
00266 vNodes->nSize = 0;
00267 return vNodes;
00268 }
00269
00285 int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper )
00286 {
00287 Ivy_Obj_t * pObjRight, * pObjLeft;
00288 int Current;
00289
00290 if ( Vec_PtrSize(vSuper) < 3 )
00291 return 0;
00292
00293 Current = Vec_PtrSize(vSuper) - 2;
00294 pObjRight = Vec_PtrEntry( vSuper, Current );
00295
00296 for ( Current--; Current >= 0; Current-- )
00297 {
00298
00299 pObjLeft = Vec_PtrEntry( vSuper, Current );
00300
00301 if ( Ivy_Regular(pObjLeft)->Level != Ivy_Regular(pObjRight)->Level )
00302 break;
00303 }
00304 Current++;
00305
00306 pObjLeft = Vec_PtrEntry( vSuper, Current );
00307 assert( Ivy_Regular(pObjLeft)->Level == Ivy_Regular(pObjRight)->Level );
00308 return Current;
00309 }
00310
00323 void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor )
00324 {
00325 Ivy_Obj_t * pObj1, * pObj2, * pObj3, * pGhost;
00326 int RightBound, i;
00327
00328 RightBound = Vec_PtrSize(vSuper) - 2;
00329 assert( LeftBound <= RightBound );
00330 if ( LeftBound == RightBound )
00331 return;
00332
00333 pObj1 = Vec_PtrEntry( vSuper, RightBound + 1 );
00334 pObj2 = Vec_PtrEntry( vSuper, RightBound );
00335 if ( Ivy_Regular(pObj1) == p->pConst1 || Ivy_Regular(pObj2) == p->pConst1 )
00336 return;
00337
00338 for ( i = RightBound; i >= LeftBound; i-- )
00339 {
00340 pObj3 = Vec_PtrEntry( vSuper, i );
00341 if ( Ivy_Regular(pObj3) == p->pConst1 )
00342 {
00343 Vec_PtrWriteEntry( vSuper, i, pObj2 );
00344 Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
00345 return;
00346 }
00347 pGhost = Ivy_ObjCreateGhost( p, pObj1, pObj3, fExor? IVY_EXOR : IVY_AND, IVY_INIT_NONE );
00348 if ( Ivy_TableLookup( p, pGhost ) )
00349 {
00350 if ( pObj3 == pObj2 )
00351 return;
00352 Vec_PtrWriteEntry( vSuper, i, pObj2 );
00353 Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
00354 return;
00355 }
00356 }
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 }
00369
00381 void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj )
00382 {
00383 Ivy_Obj_t * pObj1, * pObj2;
00384 int i;
00385 if ( Vec_PtrPushUnique(vStore, pObj) )
00386 return;
00387
00388 for ( i = vStore->nSize-1; i > 0; i-- )
00389 {
00390 pObj1 = vStore->pArray[i ];
00391 pObj2 = vStore->pArray[i-1];
00392 if ( Ivy_Regular(pObj1)->Level <= Ivy_Regular(pObj2)->Level )
00393 break;
00394 vStore->pArray[i ] = pObj2;
00395 vStore->pArray[i-1] = pObj1;
00396 }
00397 }
00398
00399
00403
00404