00001
00021 #include "ivy.h"
00022 #include "deco.h"
00023 #include "rwt.h"
00024
00028
00029 static int Ivy_NodeRewriteSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUseZeroCost );
00030 static void Ivy_GraphPrepare( Dec_Graph_t * pGraph, Ivy_Cut_t * pCut, Vec_Ptr_t * vFanins, char * pPerm );
00031 static unsigned Ivy_CutGetTruth( Ivy_Man_t * p, Ivy_Obj_t * pObj, int * pNums, int nNums );
00032 static Dec_Graph_t * Rwt_CutEvaluateSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, char * pPerm, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int * pGainBest, unsigned uTruth );
00033 static int Ivy_GraphToNetworkSeqCountSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax );
00034 static Ivy_Obj_t * Ivy_GraphToNetworkSeq( Ivy_Man_t * p, Dec_Graph_t * pGraph );
00035 static void Ivy_GraphUpdateNetworkSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain );
00036 static Ivy_Store_t * Ivy_CutComputeForNode( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves );
00037
00038 static inline int Ivy_CutHashValue( int NodeId ) { return 1 << (NodeId % 31); }
00039
00043
00044
00045
00046
00047
00048
00060 int Ivy_ManRewriteSeq( Ivy_Man_t * p, int fUseZeroCost, int fVerbose )
00061 {
00062 Rwt_Man_t * pManRwt;
00063 Ivy_Obj_t * pNode;
00064 int i, nNodes, nGain;
00065 int clk, clkStart = clock();
00066
00067
00068 Ivy_ManForEachLatch( p, pNode, i )
00069 pNode->Init = IVY_INIT_DC;
00070
00071 pManRwt = Rwt_ManStart( 0 );
00072 p->pData = pManRwt;
00073 if ( pManRwt == NULL )
00074 return 0;
00075
00076 if ( p->fFanout == 0 )
00077 Ivy_ManStartFanout( p );
00078
00079 nNodes = Ivy_ManObjIdMax(p);
00080 Ivy_ManForEachNode( p, pNode, i )
00081 {
00082 assert( !Ivy_ObjIsBuf(pNode) );
00083 assert( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) );
00084 assert( !Ivy_ObjIsBuf(Ivy_ObjFanin1(pNode)) );
00085
00086
00087
00088
00089
00090 if ( i > nNodes )
00091 break;
00092
00093 nGain = Ivy_NodeRewriteSeq( p, pManRwt, pNode, fUseZeroCost );
00094 if ( nGain > 0 || nGain == 0 && fUseZeroCost )
00095 {
00096 Dec_Graph_t * pGraph = Rwt_ManReadDecs(pManRwt);
00097 int fCompl = Rwt_ManReadCompl(pManRwt);
00098
00099 clk = clock();
00100 if ( fCompl ) Dec_GraphComplement( pGraph );
00101 Ivy_GraphUpdateNetworkSeq( p, pNode, pGraph, nGain );
00102 if ( fCompl ) Dec_GraphComplement( pGraph );
00103 Rwt_ManAddTimeUpdate( pManRwt, clock() - clk );
00104 }
00105 }
00106 Rwt_ManAddTimeTotal( pManRwt, clock() - clkStart );
00107
00108 if ( fVerbose )
00109 Rwt_ManPrintStats( pManRwt );
00110
00111 Rwt_ManStop( pManRwt );
00112 p->pData = NULL;
00113
00114 Ivy_ManResetLevels( p );
00115
00116
00117
00118 if ( !Ivy_ManCheck(p) )
00119 printf( "Ivy_ManRewritePre(): The check has failed.\n" );
00120 return 1;
00121 }
00122
00123
00142 int Ivy_NodeRewriteSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUseZeroCost )
00143 {
00144 int fVeryVerbose = 0;
00145 Dec_Graph_t * pGraph;
00146 Ivy_Store_t * pStore;
00147 Ivy_Cut_t * pCut;
00148 Ivy_Obj_t * pFanin;
00149 Vec_Ptr_t * vFanout;
00150 unsigned uPhase, uTruthBest, uTruth;
00151 char * pPerm;
00152 int nNodesSaved, nNodesSaveCur;
00153 int i, c, GainCur, GainBest = -1;
00154 int clk, clk2;
00155
00156 p->nNodesConsidered++;
00157
00158 clk = clock();
00159 pStore = Ivy_CutComputeForNode( pMan, pNode, 5 );
00160 p->timeCut += clock() - clk;
00161
00162
00163 clk = clock();
00164 vFanout = Vec_PtrAlloc( 100 );
00165 for ( c = 1; c < pStore->nCuts; c++ )
00166 {
00167 pCut = pStore->pCuts + c;
00168
00169 if ( pCut->nSize != 4 )
00170 continue;
00171
00172 for ( i = 0; i < (int)pCut->nSize; i++ )
00173 if ( Ivy_ObjIsBuf( Ivy_ManObj(pMan, Ivy_LeafId(pCut->pArray[i])) ) )
00174 break;
00175 if ( i != pCut->nSize )
00176 {
00177 p->nCutsBad++;
00178 continue;
00179 }
00180 p->nCutsGood++;
00181
00182 clk2 = clock();
00183 uTruth = 0xFFFF & Ivy_CutGetTruth( pMan, pNode, pCut->pArray, pCut->nSize );
00184 p->timeTruth += clock() - clk2;
00185 pPerm = p->pPerms4[ p->pPerms[uTruth] ];
00186 uPhase = p->pPhases[uTruth];
00187
00188 Vec_PtrClear( p->vFaninsCur );
00189 Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 );
00190 for ( i = 0; i < (int)pCut->nSize; i++ )
00191 {
00192 pFanin = Ivy_ManObj( pMan, Ivy_LeafId( pCut->pArray[pPerm[i]] ) );
00193 assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) || Ivy_ObjIsConst1(pFanin) );
00194 pFanin = Ivy_NotCond(pFanin, ((uPhase & (1<<i)) > 0) );
00195 Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin );
00196 }
00197 clk2 = clock();
00198
00199 Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
00200 Ivy_ObjRefsInc( Ivy_Regular(pFanin) );
00201
00202 Ivy_ManIncrementTravId( pMan );
00203 nNodesSaved = Ivy_ObjMffcLabel( pMan, pNode );
00204
00205
00206
00207
00208 Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
00209 Ivy_ObjRefsDec( Ivy_Regular(pFanin) );
00210 p->timeMffc += clock() - clk2;
00211
00212
00213 clk2 = clock();
00214 pGraph = Rwt_CutEvaluateSeq( pMan, p, pNode, pCut, pPerm, p->vFaninsCur, nNodesSaved, &GainCur, uTruth );
00215 p->timeEval += clock() - clk2;
00216
00217
00218
00219 if ( pGraph != NULL && GainBest < GainCur )
00220 {
00221
00222 nNodesSaveCur = nNodesSaved;
00223 GainBest = GainCur;
00224 p->pGraph = pGraph;
00225 p->pCut = pCut;
00226 p->pPerm = pPerm;
00227 p->fCompl = ((uPhase & (1<<4)) > 0);
00228 uTruthBest = uTruth;
00229
00230 Vec_PtrClear( p->vFanins );
00231 Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
00232 Vec_PtrPush( p->vFanins, pFanin );
00233 }
00234 }
00235 Vec_PtrFree( vFanout );
00236 p->timeRes += clock() - clk;
00237
00238 if ( GainBest == -1 )
00239 return -1;
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 Ivy_GraphPrepare( p->pGraph, p->pCut, p->vFanins, p->pPerm );
00261
00262 p->nScores[p->pMap[uTruthBest]]++;
00263 p->nNodesGained += GainBest;
00264 if ( fUseZeroCost || GainBest > 0 )
00265 p->nNodesRewritten++;
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 if ( fVeryVerbose && GainBest > 0 )
00280 {
00281 printf( "Node %6d : ", Ivy_ObjId(pNode) );
00282 printf( "Fanins = %d. ", p->vFanins->nSize );
00283 printf( "Save = %d. ", nNodesSaveCur );
00284 printf( "Add = %d. ", nNodesSaveCur-GainBest );
00285 printf( "GAIN = %d. ", GainBest );
00286 printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 );
00287 printf( "Class = %d. ", p->pMap[uTruthBest] );
00288 printf( "\n" );
00289 }
00290 return GainBest;
00291 }
00292
00293
00305 Dec_Graph_t * Rwt_CutEvaluateSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, char * pPerm, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int * pGainBest, unsigned uTruth )
00306 {
00307 Vec_Ptr_t * vSubgraphs;
00308 Dec_Graph_t * pGraphBest, * pGraphCur;
00309 Rwt_Node_t * pNode;
00310 int nNodesAdded, GainBest, i;
00311
00312 vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] );
00313 p->nSubgraphs += vSubgraphs->nSize;
00314
00315 GainBest = -1;
00316 Vec_PtrForEachEntry( vSubgraphs, pNode, i )
00317 {
00318
00319 pGraphCur = (Dec_Graph_t *)pNode->pNext;
00320
00321
00322
00323
00324
00325
00326 Ivy_GraphPrepare( pGraphCur, pCut, vFaninsCur, pPerm );
00327
00328
00329 nNodesAdded = Ivy_GraphToNetworkSeqCountSeq( pMan, pRoot, pGraphCur, nNodesSaved );
00330 if ( nNodesAdded == -1 )
00331 continue;
00332 assert( nNodesSaved >= nNodesAdded );
00333
00334 if ( GainBest < nNodesSaved - nNodesAdded )
00335 {
00336 GainBest = nNodesSaved - nNodesAdded;
00337 pGraphBest = pGraphCur;
00338 }
00339 }
00340 if ( GainBest == -1 )
00341 return NULL;
00342 *pGainBest = GainBest;
00343 return pGraphBest;
00344 }
00345
00357 void Ivy_GraphPrepare( Dec_Graph_t * pGraph, Ivy_Cut_t * pCut, Vec_Ptr_t * vFanins, char * pPerm )
00358 {
00359 Dec_Node_t * pNode, * pNode0, * pNode1;
00360 int i;
00361 assert( Dec_GraphLeaveNum(pGraph) == pCut->nSize );
00362 assert( Vec_PtrSize(vFanins) == pCut->nSize );
00363
00364 Dec_GraphForEachLeaf( pGraph, pNode, i )
00365 {
00366 pNode->pFunc = Vec_PtrEntry( vFanins, i );
00367 pNode->nLat2 = Ivy_LeafLat( pCut->pArray[pPerm[i]] );
00368 }
00369
00370 Dec_GraphForEachNode( pGraph, pNode, i )
00371 {
00372
00373 pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node );
00374 pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node );
00375
00376 pNode->nLat2 = IVY_MIN( pNode0->nLat2, pNode1->nLat2 );
00377 pNode->nLat0 = pNode0->nLat2 - pNode->nLat2;
00378 pNode->nLat1 = pNode1->nLat2 - pNode->nLat2;
00379 }
00380 }
00381
00396 int Ivy_GraphToNetworkSeqCountSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax )
00397 {
00398 Dec_Node_t * pNode, * pNode0, * pNode1;
00399 Ivy_Obj_t * pAnd, * pAnd0, * pAnd1;
00400 int i, k, Counter, fCompl;
00401
00402 if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) )
00403 return 0;
00404
00405 Counter = 0;
00406 Dec_GraphForEachNode( pGraph, pNode, i )
00407 {
00408
00409 pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node );
00410 pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node );
00411
00412 pAnd0 = pNode0->pFunc;
00413 pAnd1 = pNode1->pFunc;
00414
00415 for ( k = 0; pAnd0 && k < (int)pNode->nLat0; k++ )
00416 {
00417 fCompl = Ivy_IsComplement(pAnd0);
00418 pAnd0 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Regular(pAnd0), NULL, IVY_LATCH, IVY_INIT_DC) );
00419 if ( pAnd0 )
00420 pAnd0 = Ivy_NotCond( pAnd0, fCompl );
00421 }
00422 for ( k = 0; pAnd1 && k < (int)pNode->nLat1; k++ )
00423 {
00424 fCompl = Ivy_IsComplement(pAnd1);
00425 pAnd1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Regular(pAnd1), NULL, IVY_LATCH, IVY_INIT_DC) );
00426 if ( pAnd1 )
00427 pAnd1 = Ivy_NotCond( pAnd1, fCompl );
00428 }
00429
00430 if ( pAnd0 && pAnd1 )
00431 {
00432
00433 pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl );
00434 pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl );
00435 assert( !Ivy_ObjIsLatch(Ivy_Regular(pAnd0)) || !Ivy_ObjIsLatch(Ivy_Regular(pAnd1)) );
00436 if ( Ivy_Regular(pAnd0) == Ivy_Regular(pAnd1) || Ivy_ObjIsConst1(Ivy_Regular(pAnd0)) || Ivy_ObjIsConst1(Ivy_Regular(pAnd1)) )
00437 pAnd = Ivy_And( p, pAnd0, pAnd1 );
00438 else
00439 pAnd = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) );
00440
00441 if ( Ivy_Regular(pAnd) == pRoot )
00442 return -1;
00443 }
00444 else
00445 pAnd = NULL;
00446
00447 if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(p, Ivy_Regular(pAnd)) )
00448 {
00449 if ( ++Counter > NodeMax )
00450 return -1;
00451 }
00452 pNode->pFunc = pAnd;
00453 }
00454 return Counter;
00455 }
00456
00457
00470 Ivy_Obj_t * Ivy_GraphToNetworkSeq( Ivy_Man_t * p, Dec_Graph_t * pGraph )
00471 {
00472 Ivy_Obj_t * pAnd0, * pAnd1;
00473 Dec_Node_t * pNode;
00474 int i, k;
00475
00476 if ( Dec_GraphIsConst(pGraph) )
00477 return Ivy_NotCond( Ivy_ManConst1(p), Dec_GraphIsComplement(pGraph) );
00478
00479 if ( Dec_GraphIsVar(pGraph) )
00480 {
00481
00482 pNode = Dec_GraphVar(pGraph);
00483
00484 for ( k = 0; k < (int)pNode->nLat2; k++ )
00485 pNode->pFunc = Ivy_Latch( p, pNode->pFunc, IVY_INIT_DC );
00486 return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) );
00487 }
00488
00489 Dec_GraphForEachNode( pGraph, pNode, i )
00490 {
00491 pAnd0 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl );
00492 pAnd1 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl );
00493
00494 for ( k = 0; k < (int)pNode->nLat0; k++ )
00495 pAnd0 = Ivy_Latch( p, pAnd0, IVY_INIT_DC );
00496 for ( k = 0; k < (int)pNode->nLat1; k++ )
00497 pAnd1 = Ivy_Latch( p, pAnd1, IVY_INIT_DC );
00498
00499 pNode->pFunc = Ivy_And( p, pAnd0, pAnd1 );
00500 }
00501
00502 for ( k = 0; k < (int)pNode->nLat2; k++ )
00503 pNode->pFunc = Ivy_Latch( p, pNode->pFunc, IVY_INIT_DC );
00504
00505 return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) );
00506 }
00507
00519 void Ivy_GraphUpdateNetworkSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain )
00520 {
00521 Ivy_Obj_t * pRootNew;
00522 int nNodesNew, nNodesOld;
00523 nNodesOld = Ivy_ManNodeNum(p);
00524
00525 pRootNew = Ivy_GraphToNetworkSeq( p, pGraph );
00526 Ivy_ObjReplace( p, pRoot, pRootNew, 1, 0, 0 );
00527
00528 nNodesNew = Ivy_ManNodeNum(p);
00529 assert( nGain <= nNodesOld - nNodesNew );
00530
00531 Ivy_ManPropagateBuffers( p, 0 );
00532 }
00533
00534
00535
00536
00537
00538
00539
00540
00541
00553 unsigned Ivy_CutGetTruth_rec( Ivy_Man_t * p, int Leaf, int * pNums, int nNums )
00554 {
00555 static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
00556 unsigned uTruth0, uTruth1;
00557 Ivy_Obj_t * pObj;
00558 int i;
00559 for ( i = 0; i < nNums; i++ )
00560 if ( Leaf == pNums[i] )
00561 return uMasks[i];
00562 pObj = Ivy_ManObj( p, Ivy_LeafId(Leaf) );
00563 if ( Ivy_ObjIsLatch(pObj) )
00564 {
00565 assert( !Ivy_ObjFaninC0(pObj) );
00566 Leaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pObj), Ivy_LeafLat(Leaf) + 1 );
00567 return Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums );
00568 }
00569 assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) );
00570 Leaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pObj), Ivy_LeafLat(Leaf) );
00571 uTruth0 = Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums );
00572 if ( Ivy_ObjFaninC0(pObj) )
00573 uTruth0 = ~uTruth0;
00574 if ( Ivy_ObjIsBuf(pObj) )
00575 return uTruth0;
00576 Leaf = Ivy_LeafCreate( Ivy_ObjFaninId1(pObj), Ivy_LeafLat(Leaf) );
00577 uTruth1 = Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums );
00578 if ( Ivy_ObjFaninC1(pObj) )
00579 uTruth1 = ~uTruth1;
00580 return uTruth0 & uTruth1;
00581 }
00582
00583
00595 unsigned Ivy_CutGetTruth( Ivy_Man_t * p, Ivy_Obj_t * pObj, int * pNums, int nNums )
00596 {
00597 assert( Ivy_ObjIsNode(pObj) );
00598 assert( nNums < 6 );
00599 return Ivy_CutGetTruth_rec( p, Ivy_LeafCreate(pObj->Id, 0), pNums, nNums );
00600 }
00601
00602
00603
00604
00605
00617 static inline int Ivy_CutPrescreen( Ivy_Cut_t * pCut, int Id0, int Id1 )
00618 {
00619 int i;
00620 if ( pCut->nSize < pCut->nSizeMax )
00621 return 1;
00622 for ( i = 0; i < pCut->nSize; i++ )
00623 if ( pCut->pArray[i] == Id0 || pCut->pArray[i] == Id1 )
00624 return 1;
00625 return 0;
00626 }
00627
00639 static inline int Ivy_CutDeriveNew2( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 )
00640 {
00641 unsigned uHash = 0;
00642 int i, k;
00643 assert( pCut->nSize > 0 );
00644 assert( IdNew0 < IdNew1 );
00645 for ( i = k = 0; i < pCut->nSize; i++ )
00646 {
00647 if ( pCut->pArray[i] == IdOld )
00648 continue;
00649 if ( IdNew0 >= 0 )
00650 {
00651 if ( IdNew0 <= pCut->pArray[i] )
00652 {
00653 if ( IdNew0 < pCut->pArray[i] )
00654 {
00655 if ( k == pCut->nSizeMax )
00656 return 0;
00657 pCutNew->pArray[ k++ ] = IdNew0;
00658 uHash |= Ivy_CutHashValue( IdNew0 );
00659 }
00660 IdNew0 = -1;
00661 }
00662 }
00663 if ( IdNew1 >= 0 )
00664 {
00665 if ( IdNew1 <= pCut->pArray[i] )
00666 {
00667 if ( IdNew1 < pCut->pArray[i] )
00668 {
00669 if ( k == pCut->nSizeMax )
00670 return 0;
00671 pCutNew->pArray[ k++ ] = IdNew1;
00672 uHash |= Ivy_CutHashValue( IdNew1 );
00673 }
00674 IdNew1 = -1;
00675 }
00676 }
00677 if ( k == pCut->nSizeMax )
00678 return 0;
00679 pCutNew->pArray[ k++ ] = pCut->pArray[i];
00680 uHash |= Ivy_CutHashValue( pCut->pArray[i] );
00681 }
00682 if ( IdNew0 >= 0 )
00683 {
00684 if ( k == pCut->nSizeMax )
00685 return 0;
00686 pCutNew->pArray[ k++ ] = IdNew0;
00687 uHash |= Ivy_CutHashValue( IdNew0 );
00688 }
00689 if ( IdNew1 >= 0 )
00690 {
00691 if ( k == pCut->nSizeMax )
00692 return 0;
00693 pCutNew->pArray[ k++ ] = IdNew1;
00694 uHash |= Ivy_CutHashValue( IdNew1 );
00695 }
00696 pCutNew->nSize = k;
00697 pCutNew->uHash = uHash;
00698 assert( pCutNew->nSize <= pCut->nSizeMax );
00699 for ( i = 1; i < pCutNew->nSize; i++ )
00700 assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] );
00701 return 1;
00702 }
00703
00715 static inline int Ivy_CutDeriveNew( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 )
00716 {
00717 unsigned uHash = 0;
00718 int i, k;
00719 assert( pCut->nSize > 0 );
00720 assert( IdNew0 < IdNew1 );
00721 for ( i = k = 0; i < pCut->nSize; i++ )
00722 {
00723 if ( pCut->pArray[i] == IdOld )
00724 continue;
00725 if ( IdNew0 <= pCut->pArray[i] )
00726 {
00727 if ( IdNew0 < pCut->pArray[i] )
00728 {
00729 pCutNew->pArray[ k++ ] = IdNew0;
00730 uHash |= Ivy_CutHashValue( IdNew0 );
00731 }
00732 IdNew0 = 0x7FFFFFFF;
00733 }
00734 if ( IdNew1 <= pCut->pArray[i] )
00735 {
00736 if ( IdNew1 < pCut->pArray[i] )
00737 {
00738 pCutNew->pArray[ k++ ] = IdNew1;
00739 uHash |= Ivy_CutHashValue( IdNew1 );
00740 }
00741 IdNew1 = 0x7FFFFFFF;
00742 }
00743 pCutNew->pArray[ k++ ] = pCut->pArray[i];
00744 uHash |= Ivy_CutHashValue( pCut->pArray[i] );
00745 }
00746 if ( IdNew0 < 0x7FFFFFFF )
00747 {
00748 pCutNew->pArray[ k++ ] = IdNew0;
00749 uHash |= Ivy_CutHashValue( IdNew0 );
00750 }
00751 if ( IdNew1 < 0x7FFFFFFF )
00752 {
00753 pCutNew->pArray[ k++ ] = IdNew1;
00754 uHash |= Ivy_CutHashValue( IdNew1 );
00755 }
00756 pCutNew->nSize = k;
00757 pCutNew->uHash = uHash;
00758 assert( pCutNew->nSize <= pCut->nSizeMax );
00759
00760
00761 return 1;
00762 }
00763
00775 static inline unsigned Ivy_NodeCutHash( Ivy_Cut_t * pCut )
00776 {
00777 int i;
00778 pCut->uHash = 0;
00779 for ( i = 0; i < pCut->nSize; i++ )
00780 pCut->uHash |= (1 << (pCut->pArray[i] % 31));
00781 return pCut->uHash;
00782 }
00783
00795 static inline int Ivy_CutDeriveNew3( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 )
00796 {
00797 int i, k;
00798 assert( pCut->nSize > 0 );
00799 assert( IdNew0 < IdNew1 );
00800 for ( i = k = 0; i < pCut->nSize; i++ )
00801 {
00802 if ( pCut->pArray[i] == IdOld )
00803 continue;
00804 if ( IdNew0 <= pCut->pArray[i] )
00805 {
00806 if ( IdNew0 < pCut->pArray[i] )
00807 pCutNew->pArray[ k++ ] = IdNew0;
00808 IdNew0 = 0x7FFFFFFF;
00809 }
00810 if ( IdNew1 <= pCut->pArray[i] )
00811 {
00812 if ( IdNew1 < pCut->pArray[i] )
00813 pCutNew->pArray[ k++ ] = IdNew1;
00814 IdNew1 = 0x7FFFFFFF;
00815 }
00816 pCutNew->pArray[ k++ ] = pCut->pArray[i];
00817 }
00818 if ( IdNew0 < 0x7FFFFFFF )
00819 pCutNew->pArray[ k++ ] = IdNew0;
00820 if ( IdNew1 < 0x7FFFFFFF )
00821 pCutNew->pArray[ k++ ] = IdNew1;
00822 pCutNew->nSize = k;
00823 assert( pCutNew->nSize <= pCut->nSizeMax );
00824 Ivy_NodeCutHash( pCutNew );
00825 return 1;
00826 }
00827
00839 static inline int Ivy_CutCheckDominance( Ivy_Cut_t * pDom, Ivy_Cut_t * pCut )
00840 {
00841 int i, k;
00842 for ( i = 0; i < pDom->nSize; i++ )
00843 {
00844 assert( i==0 || pDom->pArray[i-1] < pDom->pArray[i] );
00845 for ( k = 0; k < pCut->nSize; k++ )
00846 if ( pDom->pArray[i] == pCut->pArray[k] )
00847 break;
00848 if ( k == pCut->nSize )
00849 return 0;
00850 }
00851
00852 return 1;
00853 }
00854
00866 int Ivy_CutFindOrAddFilter( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew )
00867 {
00868 Ivy_Cut_t * pCut;
00869 int i, k;
00870 assert( pCutNew->uHash );
00871
00872 for ( i = 0; i < pCutStore->nCuts; i++ )
00873 {
00874 pCut = pCutStore->pCuts + i;
00875 if ( pCut->nSize == 0 )
00876 continue;
00877 if ( pCut->nSize == pCutNew->nSize )
00878 {
00879 if ( pCut->uHash == pCutNew->uHash )
00880 {
00881 for ( k = 0; k < pCutNew->nSize; k++ )
00882 if ( pCut->pArray[k] != pCutNew->pArray[k] )
00883 break;
00884 if ( k == pCutNew->nSize )
00885 return 1;
00886 }
00887 continue;
00888 }
00889 if ( pCut->nSize < pCutNew->nSize )
00890 {
00891
00892 if ( (pCut->uHash & pCutNew->uHash) != pCut->uHash )
00893 continue;
00894
00895 if ( Ivy_CutCheckDominance( pCut, pCutNew ) )
00896 return 1;
00897 continue;
00898 }
00899
00900
00901
00902 if ( (pCut->uHash & pCutNew->uHash) != pCutNew->uHash )
00903 continue;
00904
00905 if ( Ivy_CutCheckDominance( pCutNew, pCut ) )
00906 {
00907
00908 pCut->nSize = 0;
00909 }
00910 }
00911 assert( pCutStore->nCuts < pCutStore->nCutsMax );
00912
00913 pCut = pCutStore->pCuts + pCutStore->nCuts++;
00914 *pCut = *pCutNew;
00915 return 0;
00916 }
00917
00929 void Ivy_CutCompactAll( Ivy_Store_t * pCutStore )
00930 {
00931 Ivy_Cut_t * pCut;
00932 int i, k;
00933 pCutStore->nCutsM = 0;
00934 for ( i = k = 0; i < pCutStore->nCuts; i++ )
00935 {
00936 pCut = pCutStore->pCuts + i;
00937 if ( pCut->nSize == 0 )
00938 continue;
00939 if ( pCut->nSize < pCut->nSizeMax )
00940 pCutStore->nCutsM++;
00941 pCutStore->pCuts[k++] = *pCut;
00942 }
00943 pCutStore->nCuts = k;
00944 }
00945
00957 void Ivy_CutPrintForNode( Ivy_Cut_t * pCut )
00958 {
00959 int i;
00960 assert( pCut->nSize > 0 );
00961 printf( "%d : {", pCut->nSize );
00962 for ( i = 0; i < pCut->nSize; i++ )
00963 printf( " %d", pCut->pArray[i] );
00964 printf( " }\n" );
00965 }
00966
00978 void Ivy_CutPrintForNodes( Ivy_Store_t * pCutStore )
00979 {
00980 int i;
00981 printf( "Node %d\n", pCutStore->pCuts[0].pArray[0] );
00982 for ( i = 0; i < pCutStore->nCuts; i++ )
00983 Ivy_CutPrintForNode( pCutStore->pCuts + i );
00984 }
00985
00997 static inline int Ivy_CutReadLeaf( Ivy_Obj_t * pFanin )
00998 {
00999 int nLats, iLeaf;
01000 assert( !Ivy_IsComplement(pFanin) );
01001 if ( !Ivy_ObjIsLatch(pFanin) )
01002 return Ivy_LeafCreate( pFanin->Id, 0 );
01003 iLeaf = Ivy_CutReadLeaf(Ivy_ObjFanin0(pFanin));
01004 nLats = Ivy_LeafLat(iLeaf);
01005 assert( nLats < IVY_LEAF_MASK );
01006 return 1 + iLeaf;
01007 }
01008
01020 Ivy_Store_t * Ivy_CutComputeForNode( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves )
01021 {
01022 static Ivy_Store_t CutStore, * pCutStore = &CutStore;
01023 Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut;
01024 Ivy_Man_t * pMan = p;
01025 Ivy_Obj_t * pLeaf;
01026 int i, k, Temp, nLats, iLeaf0, iLeaf1;
01027
01028 assert( nLeaves <= IVY_CUT_INPUT );
01029
01030
01031 pCutStore->nCuts = 0;
01032 pCutStore->nCutsMax = IVY_CUT_LIMIT;
01033
01034 pCutNew->uHash = 0;
01035 pCutNew->nSize = 1;
01036 pCutNew->nSizeMax = nLeaves;
01037 pCutNew->pArray[0] = Ivy_LeafCreate( pObj->Id, 0 );
01038 pCutNew->uHash = Ivy_CutHashValue( pCutNew->pArray[0] );
01039
01040 pCutStore->pCuts[pCutStore->nCuts++] = *pCutNew;
01041 assert( pCutStore->nCuts == 1 );
01042
01043
01044 for ( i = 0; i < pCutStore->nCuts; i++ )
01045 {
01046
01047 pCut = pCutStore->pCuts + i;
01048 if ( pCut->nSize == 0 )
01049 continue;
01050 for ( k = 0; k < pCut->nSize; k++ )
01051 {
01052 pLeaf = Ivy_ManObj( p, Ivy_LeafId(pCut->pArray[k]) );
01053 if ( Ivy_ObjIsCi(pLeaf) || Ivy_ObjIsConst1(pLeaf) )
01054 continue;
01055 assert( Ivy_ObjIsNode(pLeaf) );
01056 nLats = Ivy_LeafLat(pCut->pArray[k]);
01057
01058
01059 iLeaf0 = Ivy_CutReadLeaf( Ivy_ObjFanin0(pLeaf) );
01060 iLeaf1 = Ivy_CutReadLeaf( Ivy_ObjFanin1(pLeaf) );
01061 assert( nLats + Ivy_LeafLat(iLeaf0) < IVY_LEAF_MASK && nLats + Ivy_LeafLat(iLeaf1) < IVY_LEAF_MASK );
01062 iLeaf0 = nLats + iLeaf0;
01063 iLeaf1 = nLats + iLeaf1;
01064 if ( !Ivy_CutPrescreen( pCut, iLeaf0, iLeaf1 ) )
01065 continue;
01066
01067 if ( iLeaf0 > iLeaf1 )
01068 Temp = iLeaf0, iLeaf0 = iLeaf1, iLeaf1 = Temp;
01069
01070 if ( !Ivy_CutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf0, iLeaf1 ) )
01071 continue;
01072
01073 Ivy_CutFindOrAddFilter( pCutStore, pCutNew );
01074 if ( pCutStore->nCuts == IVY_CUT_LIMIT )
01075 break;
01076 }
01077 if ( pCutStore->nCuts == IVY_CUT_LIMIT )
01078 break;
01079 }
01080 if ( pCutStore->nCuts == IVY_CUT_LIMIT )
01081 pCutStore->fSatur = 1;
01082 else
01083 pCutStore->fSatur = 0;
01084
01085 Ivy_CutCompactAll( pCutStore );
01086
01087
01088 return pCutStore;
01089 }
01090
01102 void Ivy_CutComputeAll( Ivy_Man_t * p, int nInputs )
01103 {
01104 Ivy_Store_t * pStore;
01105 Ivy_Obj_t * pObj;
01106 int i, nCutsTotal, nCutsTotalM, nNodeTotal, nNodeOver;
01107 int clk = clock();
01108 if ( nInputs > IVY_CUT_INPUT )
01109 {
01110 printf( "Cannot compute cuts for more than %d inputs.\n", IVY_CUT_INPUT );
01111 return;
01112 }
01113 nNodeTotal = nNodeOver = 0;
01114 nCutsTotal = nCutsTotalM = -Ivy_ManNodeNum(p);
01115 Ivy_ManForEachObj( p, pObj, i )
01116 {
01117 if ( !Ivy_ObjIsNode(pObj) )
01118 continue;
01119 pStore = Ivy_CutComputeForNode( p, pObj, nInputs );
01120 nCutsTotal += pStore->nCuts;
01121 nCutsTotalM += pStore->nCutsM;
01122 nNodeOver += pStore->fSatur;
01123 nNodeTotal++;
01124 }
01125 printf( "All = %6d. Minus = %6d. Triv = %6d. Node = %6d. Satur = %6d. ",
01126 nCutsTotal, nCutsTotalM, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver );
01127 PRT( "Time", clock() - clk );
01128 }
01129
01133
01134