00001
00021 #include "ivy.h"
00022 #include "deco.h"
00023 #include "rwt.h"
00024
00028
00029 static unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums );
00030 static int Ivy_NodeRewrite( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost );
00031 static Dec_Graph_t * Rwt_CutEvaluate( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot,
00032 Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth );
00033
00034 static int Ivy_GraphToNetworkCount( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax );
00035 static void Ivy_GraphUpdateNetwork( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain );
00036
00040
00052 int Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose )
00053 {
00054 Rwt_Man_t * pManRwt;
00055 Ivy_Obj_t * pNode;
00056 int i, nNodes, nGain;
00057 int clk, clkStart = clock();
00058
00059 pManRwt = Rwt_ManStart( 0 );
00060 p->pData = pManRwt;
00061 if ( pManRwt == NULL )
00062 return 0;
00063
00064 if ( fUpdateLevel && p->fFanout == 0 )
00065 Ivy_ManStartFanout( p );
00066
00067 if ( fUpdateLevel )
00068 Ivy_ManRequiredLevels( p );
00069
00070
00071
00072 nNodes = Ivy_ManObjIdMax(p);
00073 Ivy_ManForEachNode( p, pNode, i )
00074 {
00075
00076 Ivy_NodeFixBufferFanins( p, pNode, 1 );
00077 if ( Ivy_ObjIsBuf(pNode) )
00078 continue;
00079
00080 if ( i > nNodes )
00081 break;
00082
00083 nGain = Ivy_NodeRewrite( p, pManRwt, pNode, fUpdateLevel, fUseZeroCost );
00084 if ( nGain > 0 || nGain == 0 && fUseZeroCost )
00085 {
00086 Dec_Graph_t * pGraph = Rwt_ManReadDecs(pManRwt);
00087 int fCompl = Rwt_ManReadCompl(pManRwt);
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 clk = clock();
00106 if ( fCompl ) Dec_GraphComplement( pGraph );
00107 Ivy_GraphUpdateNetwork( p, pNode, pGraph, fUpdateLevel, nGain );
00108 if ( fCompl ) Dec_GraphComplement( pGraph );
00109 Rwt_ManAddTimeUpdate( pManRwt, clock() - clk );
00110 }
00111 }
00112 Rwt_ManAddTimeTotal( pManRwt, clock() - clkStart );
00113
00114 if ( fVerbose )
00115 Rwt_ManPrintStats( pManRwt );
00116
00117 Rwt_ManStop( pManRwt );
00118 p->pData = NULL;
00119
00120 if ( fUpdateLevel )
00121 Vec_IntFree( p->vRequired ), p->vRequired = NULL;
00122 else
00123 Ivy_ManResetLevels( p );
00124
00125 if ( i = Ivy_ManCleanup(p) )
00126 printf( "Cleanup after rewriting removed %d dangling nodes.\n", i );
00127 if ( !Ivy_ManCheck(p) )
00128 printf( "Ivy_ManRewritePre(): The check has failed.\n" );
00129 return 1;
00130 }
00131
00150 int Ivy_NodeRewrite( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost )
00151 {
00152 int fVeryVerbose = 0;
00153 Dec_Graph_t * pGraph;
00154 Ivy_Store_t * pStore;
00155 Ivy_Cut_t * pCut;
00156 Ivy_Obj_t * pFanin;
00157 unsigned uPhase, uTruthBest, uTruth;
00158 char * pPerm;
00159 int Required, nNodesSaved, nNodesSaveCur;
00160 int i, c, GainCur, GainBest = -1;
00161 int clk, clk2;
00162
00163 p->nNodesConsidered++;
00164
00165 Required = fUpdateLevel? Vec_IntEntry( pMan->vRequired, pNode->Id ) : 1000000;
00166
00167 clk = clock();
00168 pStore = Ivy_NodeFindCutsAll( pMan, pNode, 5 );
00169 p->timeCut += clock() - clk;
00170
00171
00172 clk = clock();
00173 for ( c = 1; c < pStore->nCuts; c++ )
00174 {
00175 pCut = pStore->pCuts + c;
00176
00177 if ( pCut->nSize != 4 )
00178 continue;
00179
00180 for ( i = 0; i < (int)pCut->nSize; i++ )
00181 if ( Ivy_ObjIsBuf( Ivy_ManObj(pMan, pCut->pArray[i]) ) )
00182 break;
00183 if ( i != pCut->nSize )
00184 {
00185 p->nCutsBad++;
00186 continue;
00187 }
00188 p->nCutsGood++;
00189
00190 clk2 = clock();
00191 uTruth = 0xFFFF & Ivy_NodeGetTruth( pNode, pCut->pArray, pCut->nSize );
00192 p->timeTruth += clock() - clk2;
00193 pPerm = p->pPerms4[ p->pPerms[uTruth] ];
00194 uPhase = p->pPhases[uTruth];
00195
00196 Vec_PtrClear( p->vFaninsCur );
00197 Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 );
00198 for ( i = 0; i < (int)pCut->nSize; i++ )
00199 {
00200 pFanin = Ivy_ManObj( pMan, pCut->pArray[pPerm[i]] );
00201 assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) );
00202 pFanin = Ivy_NotCond(pFanin, ((uPhase & (1<<i)) > 0) );
00203 Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin );
00204 }
00205 clk2 = clock();
00206
00207
00208
00209
00210
00211
00212
00213 Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
00214 Ivy_ObjRefsInc( Ivy_Regular(pFanin) );
00215
00216 Ivy_ManIncrementTravId( pMan );
00217 nNodesSaved = Ivy_ObjMffcLabel( pMan, pNode );
00218
00219 Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
00220 Ivy_ObjRefsDec( Ivy_Regular(pFanin) );
00221 p->timeMffc += clock() - clk2;
00222
00223
00224 clk2 = clock();
00225 pGraph = Rwt_CutEvaluate( pMan, p, pNode, p->vFaninsCur, nNodesSaved, Required, &GainCur, uTruth );
00226 p->timeEval += clock() - clk2;
00227
00228
00229 if ( pGraph != NULL && GainBest < GainCur )
00230 {
00231
00232 nNodesSaveCur = nNodesSaved;
00233 GainBest = GainCur;
00234 p->pGraph = pGraph;
00235 p->fCompl = ((uPhase & (1<<4)) > 0);
00236 uTruthBest = uTruth;
00237
00238 Vec_PtrClear( p->vFanins );
00239 Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
00240 Vec_PtrPush( p->vFanins, pFanin );
00241 }
00242 }
00243 p->timeRes += clock() - clk;
00244
00245 if ( GainBest == -1 )
00246 return -1;
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 Vec_PtrForEachEntry( p->vFanins, pFanin, i )
00273 Dec_GraphNode(p->pGraph, i)->pFunc = pFanin;
00274
00275 p->nScores[p->pMap[uTruthBest]]++;
00276 p->nNodesGained += GainBest;
00277 if ( fUseZeroCost || GainBest > 0 )
00278 p->nNodesRewritten++;
00279
00280
00281 if ( fVeryVerbose && GainBest > 0 )
00282 {
00283 printf( "Node %6d : ", Ivy_ObjId(pNode) );
00284 printf( "Fanins = %d. ", p->vFanins->nSize );
00285 printf( "Save = %d. ", nNodesSaveCur );
00286 printf( "Add = %d. ", nNodesSaveCur-GainBest );
00287 printf( "GAIN = %d. ", GainBest );
00288 printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 );
00289 printf( "Class = %d. ", p->pMap[uTruthBest] );
00290 printf( "\n" );
00291 }
00292 return GainBest;
00293 }
00294
00306 unsigned Ivy_NodeGetTruth_rec( Ivy_Obj_t * pObj, int * pNums, int nNums )
00307 {
00308 static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
00309 unsigned uTruth0, uTruth1;
00310 int i;
00311 for ( i = 0; i < nNums; i++ )
00312 if ( pObj->Id == pNums[i] )
00313 return uMasks[i];
00314 assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) );
00315 uTruth0 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin0(pObj), pNums, nNums );
00316 if ( Ivy_ObjFaninC0(pObj) )
00317 uTruth0 = ~uTruth0;
00318 if ( Ivy_ObjIsBuf(pObj) )
00319 return uTruth0;
00320 uTruth1 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin1(pObj), pNums, nNums );
00321 if ( Ivy_ObjFaninC1(pObj) )
00322 uTruth1 = ~uTruth1;
00323 return uTruth0 & uTruth1;
00324 }
00325
00326
00338 unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums )
00339 {
00340 assert( nNums < 6 );
00341 return Ivy_NodeGetTruth_rec( pObj, pNums, nNums );
00342 }
00343
00355 Dec_Graph_t * Rwt_CutEvaluate( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth )
00356 {
00357 Vec_Ptr_t * vSubgraphs;
00358 Dec_Graph_t * pGraphBest, * pGraphCur;
00359 Rwt_Node_t * pNode, * pFanin;
00360 int nNodesAdded, GainBest, i, k;
00361
00362 vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] );
00363 p->nSubgraphs += vSubgraphs->nSize;
00364
00365 GainBest = -1;
00366 Vec_PtrForEachEntry( vSubgraphs, pNode, i )
00367 {
00368
00369 pGraphCur = (Dec_Graph_t *)pNode->pNext;
00370
00371 Vec_PtrForEachEntry( vFaninsCur, pFanin, k )
00372 Dec_GraphNode(pGraphCur, k)->pFunc = pFanin;
00373
00374 nNodesAdded = Ivy_GraphToNetworkCount( pMan, pRoot, pGraphCur, nNodesSaved, LevelMax );
00375 if ( nNodesAdded == -1 )
00376 continue;
00377 assert( nNodesSaved >= nNodesAdded );
00378
00379 if ( GainBest < nNodesSaved - nNodesAdded )
00380 {
00381 GainBest = nNodesSaved - nNodesAdded;
00382 pGraphBest = pGraphCur;
00383 }
00384 }
00385 if ( GainBest == -1 )
00386 return NULL;
00387 *pGainBest = GainBest;
00388 return pGraphBest;
00389 }
00390
00391
00406 int Ivy_GraphToNetworkCount( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax )
00407 {
00408 Dec_Node_t * pNode, * pNode0, * pNode1;
00409 Ivy_Obj_t * pAnd, * pAnd0, * pAnd1;
00410 int i, Counter, LevelNew, LevelOld;
00411
00412 if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) )
00413 return 0;
00414
00415 Dec_GraphForEachLeaf( pGraph, pNode, i )
00416 pNode->Level = Ivy_Regular(pNode->pFunc)->Level;
00417
00418 Counter = 0;
00419 Dec_GraphForEachNode( pGraph, pNode, i )
00420 {
00421
00422 pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node );
00423 pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node );
00424
00425 pAnd0 = pNode0->pFunc;
00426 pAnd1 = pNode1->pFunc;
00427 if ( pAnd0 && pAnd1 )
00428 {
00429
00430 pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl );
00431 pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl );
00432 pAnd = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) );
00433
00434 if ( Ivy_Regular(pAnd) == pRoot )
00435 return -1;
00436 }
00437 else
00438 pAnd = NULL;
00439
00440 if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(p, Ivy_Regular(pAnd)) )
00441 {
00442 if ( ++Counter > NodeMax )
00443 return -1;
00444 }
00445
00446 LevelNew = 1 + RWT_MAX( pNode0->Level, pNode1->Level );
00447 if ( pAnd )
00448 {
00449 if ( Ivy_Regular(pAnd) == p->pConst1 )
00450 LevelNew = 0;
00451 else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd0) )
00452 LevelNew = (int)Ivy_Regular(pAnd0)->Level;
00453 else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd1) )
00454 LevelNew = (int)Ivy_Regular(pAnd1)->Level;
00455 LevelOld = (int)Ivy_Regular(pAnd)->Level;
00456
00457 }
00458 if ( LevelNew > LevelMax )
00459 return -1;
00460 pNode->pFunc = pAnd;
00461 pNode->Level = LevelNew;
00462 }
00463 return Counter;
00464 }
00465
00478 Ivy_Obj_t * Ivy_GraphToNetwork( Ivy_Man_t * p, Dec_Graph_t * pGraph )
00479 {
00480 Ivy_Obj_t * pAnd0, * pAnd1;
00481 Dec_Node_t * pNode;
00482 int i;
00483
00484 if ( Dec_GraphIsConst(pGraph) )
00485 return Ivy_NotCond( Ivy_ManConst1(p), Dec_GraphIsComplement(pGraph) );
00486
00487 if ( Dec_GraphIsVar(pGraph) )
00488 return Ivy_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) );
00489
00490 Dec_GraphForEachNode( pGraph, pNode, i )
00491 {
00492 pAnd0 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl );
00493 pAnd1 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl );
00494 pNode->pFunc = Ivy_And( p, pAnd0, pAnd1 );
00495 }
00496
00497 return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) );
00498 }
00499
00511 void Ivy_GraphUpdateNetwork( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain )
00512 {
00513 Ivy_Obj_t * pRootNew;
00514 int nNodesNew, nNodesOld, Required;
00515 Required = fUpdateLevel? Vec_IntEntry( p->vRequired, pRoot->Id ) : 1000000;
00516 nNodesOld = Ivy_ManNodeNum(p);
00517
00518 pRootNew = Ivy_GraphToNetwork( p, pGraph );
00519 assert( (int)Ivy_Regular(pRootNew)->Level <= Required );
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533 Ivy_ObjReplace( p, pRoot, pRootNew, 1, 0, 1 );
00534
00535 nNodesNew = Ivy_ManNodeNum(p);
00536 assert( nGain <= nNodesOld - nNodesNew );
00537
00538 Ivy_ManPropagateBuffers( p, 1 );
00539 }
00540
00552 void Ivy_GraphUpdateNetwork3( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain )
00553 {
00554 Ivy_Obj_t * pRootNew, * pFanin;
00555 int nNodesNew, nNodesOld, i, nRefsOld;
00556 nNodesOld = Ivy_ManNodeNum(p);
00557
00558
00559
00560 Vec_PtrForEachEntry( ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i )
00561 Ivy_ObjRefsInc( Ivy_Regular(pFanin) );
00562
00563 nRefsOld = pRoot->nRefs;
00564 pRoot->nRefs = 0;
00565 Ivy_ObjDelete_rec( p, pRoot, 0 );
00566 pRoot->nRefs = nRefsOld;
00567
00568 Vec_PtrForEachEntry( ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i )
00569 Ivy_ObjRefsDec( Ivy_Regular(pFanin) );
00570
00571
00572
00573 pRootNew = Ivy_GraphToNetwork( p, pGraph );
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586 Ivy_ObjReplace( p, pRoot, pRootNew, 0, 0, 1 );
00587
00588
00589
00590 Vec_PtrForEachEntry( ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i )
00591 {
00592 pFanin = Ivy_Regular(pFanin);
00593 if ( !Ivy_ObjIsNone(pFanin) && Ivy_ObjRefs(pFanin) == 0 )
00594 Ivy_ObjDelete_rec( p, pFanin, 1 );
00595 }
00596
00597
00598
00599
00600 nNodesNew = Ivy_ManNodeNum(p);
00601 assert( nGain <= nNodesOld - nNodesNew );
00602 }
00603
00604
00608
00609