/**Function************************************************************* Synopsis [Performs truth table computation.] Description [This procedure cannot be used while recording oracle because it will overwrite Num0 and Num1.] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_TruthNCanonicize( Cut_Cut_t * pCut ) { unsigned uTruth; unsigned * uCanon2; char * pPhases2; assert( pCut->nVarsMax < 6 ); // get the direct truth table uTruth = *Cut_CutReadTruth(pCut); // compute the direct truth table Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 ); // uCanon[0] = uCanon2[0]; // uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0]; // uPhases[0] = pPhases2[0]; pCut->uCanon0 = uCanon2[0]; pCut->Num0 = pPhases2[0]; // get the complemented truth table uTruth = ~*Cut_CutReadTruth(pCut); // compute the direct truth table Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 ); // uCanon[0] = uCanon2[0]; // uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0]; // uPhases[0] = pPhases2[0]; pCut->uCanon1 = uCanon2[0]; pCut->Num1 = pPhases2[0]; }
/**Function************************************************************* Synopsis [ Given a node, evaluate its cuts and save the best one ] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rewrite_NodeRewrite( Mig_Man_t * pMig, Rewrite_Man_t * p, Cut_Man_t * pManCut, Mig_Obj_t * pNode, Cut_Cut_t * pCut, int fUpdateLevel ) { Gra_Graph_t * pGraph; Mig_Obj_t * pFanin; unsigned uPhase; unsigned uTruthBest = 0; unsigned uTruth; char * pPerm; int Required, nNodesSaved, nNodesSaveCur = -1; int i, GainCur = -1, GainBest = -1; Required = fUpdateLevel ? Mig_ObjRequiredLevel(pMig, pNode) : ABC_INFINITY; // triv cut is omitted for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) { if ( pCut->nLeaves < 4 ) continue; // NPN conditions uTruth = 0xFFFF & *Cut_CutReadTruth(pCut); pPerm = p->pPerms4[ (int)p->pPerms[uTruth] ]; uPhase = p->pPhases[uTruth]; // collect fanin nodes Vec_PtrClear( p->vFaninsCur ); Vec_PtrFill( p->vFaninsCur, (int)pCut->nLeaves, 0 ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) { pFanin = Mig_ManObj( pMig, pCut->pLeaves[(int)pPerm[i]] ); if( pFanin == NULL ) break; //assert( pFanin ); // bad cut condition-> fanin may be removed pFanin = Mig_NotCond( pFanin, ((uPhase & (1<<i)) > 0) ); Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); } if ( i != (int)pCut->nLeaves ) continue; // bad cut: fanin is removed // 1. mark boundary 2. mark MFFC 3.recover boundary Vec_PtrForEachEntry( Mig_Obj_t *, p->vFaninsCur, pFanin, i ) Mig_Regular(pFanin)->vFanouts.nSize++; Mig_ManIncTravId( pMig ); nNodesSaved = Mig_NodeMffcLabelMig( pMig, pNode ); Vec_PtrForEachEntry( Mig_Obj_t *, p->vFaninsCur, pFanin, i ) Mig_Regular(pFanin)->vFanouts.nSize--; // evaluate the cut pGraph = Rewrite_CutEvaluate( pMig, p, pNode, pCut, nNodesSaved, &GainCur, Required, 0xFFFF ); if( pGraph != NULL && GainBest < GainCur ) { nNodesSaveCur = nNodesSaved; GainBest = GainCur; p->pGraph = pGraph; p->fCompl = ((uPhase & (1<<4)) > 0 ); uTruthBest = 0xFFFF & *Cut_CutReadTruth(pCut); Vec_PtrClear( p->vFanins ); Vec_PtrForEachEntry( Mig_Obj_t *, p->vFaninsCur, pFanin, i ) Vec_PtrPush( p->vFanins, pFanin ); } }
/**Function************************************************************* Synopsis [Performs truth table computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_TruthComputeOld( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ) { static unsigned uTruth0[8], uTruth1[8]; int nTruthWords = Cut_TruthWords( pCut->nVarsMax ); unsigned * pTruthRes; int i, uPhase; // permute the first table uPhase = Cut_TruthPhase( pCut, pCut0 ); Extra_TruthExpand( pCut->nVarsMax, nTruthWords, Cut_CutReadTruth(pCut0), uPhase, uTruth0 ); if ( fCompl0 ) { for ( i = 0; i < nTruthWords; i++ ) uTruth0[i] = ~uTruth0[i]; } // permute the second table uPhase = Cut_TruthPhase( pCut, pCut1 ); Extra_TruthExpand( pCut->nVarsMax, nTruthWords, Cut_CutReadTruth(pCut1), uPhase, uTruth1 ); if ( fCompl1 ) { for ( i = 0; i < nTruthWords; i++ ) uTruth1[i] = ~uTruth1[i]; } // write the resulting table pTruthRes = Cut_CutReadTruth(pCut); if ( pCut->fCompl ) { for ( i = 0; i < nTruthWords; i++ ) pTruthRes[i] = ~(uTruth0[i] & uTruth1[i]); } else { for ( i = 0; i < nTruthWords; i++ ) pTruthRes[i] = uTruth0[i] & uTruth1[i]; } }
/**Function************************************************************* Synopsis [Performs truth table computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ) { // permute the first table if ( fCompl0 ) Extra_TruthNot( p->puTemp[0], Cut_CutReadTruth(pCut0), pCut->nVarsMax ); else Extra_TruthCopy( p->puTemp[0], Cut_CutReadTruth(pCut0), pCut->nVarsMax ); Extra_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nLeaves, pCut->nVarsMax, Cut_TruthPhase(pCut, pCut0) ); // permute the second table if ( fCompl1 ) Extra_TruthNot( p->puTemp[1], Cut_CutReadTruth(pCut1), pCut->nVarsMax ); else Extra_TruthCopy( p->puTemp[1], Cut_CutReadTruth(pCut1), pCut->nVarsMax ); Extra_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nLeaves, pCut->nVarsMax, Cut_TruthPhase(pCut, pCut1) ); // produce the resulting table if ( pCut->fCompl ) Extra_TruthNand( Cut_CutReadTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nVarsMax ); else Extra_TruthAnd( Cut_CutReadTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nVarsMax ); // Ivy_TruthTestOne( *Cut_CutReadTruth(pCut) ); // quit if no fancy computation is needed if ( !p->pParams->fFancy ) return; if ( pCut->nLeaves != 7 ) return; // count the total number of truth tables computed nTotal++; // MAPPING INTO ALTERA 6-2 LOGIC BLOCKS // call this procedure to find the minimum number of common variables in the cofactors // if this number is less or equal than 3, the cut can be implemented using the 6-2 logic block if ( Extra_TruthMinCofSuppOverlap( Cut_CutReadTruth(pCut), pCut->nVarsMax, NULL ) <= 4 ) nGood++; // MAPPING INTO ACTEL 2x2 CELLS // call this procedure to see if a semi-canonical form can be found in the lookup table // (if it exists, then a two-level 3-input LUT implementation of the cut exists) // Before this procedure is called, cell manager should be defined by calling // Cut_CellLoad (make sure file "cells22_daomap_iwls.txt" is available in the working dir) // if ( Cut_CellIsRunning() && pCut->nVarsMax <= 9 ) // nGood += Cut_CellTruthLookup( Cut_CutReadTruth(pCut), pCut->nVarsMax ); }
/**Function************************************************************* Synopsis [Performs rewriting for one node.] Description [This procedure considers all the cuts computed for the node and tries to rewrite each of them using the "forest" of different AIG structures precomputed and stored in the RWR manager. Determines the best rewriting and computes the gain in the number of AIG nodes in the final network. In the end, p->vFanins contains information about the best cut that can be used for rewriting, while p->pGraph gives the decomposition dag (represented using decomposition graph data structure). Returns gain in the number of nodes or -1 if node cannot be rewritten.] SideEffects [] SeeAlso [] ***********************************************************************/ int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUpdateLevel, int fUseZeros, int fPlaceEnable ) { int fVeryVerbose = 0; Dec_Graph_t * pGraph; Cut_Cut_t * pCut;//, * pTemp; Abc_Obj_t * pFanin; unsigned uPhase, uTruthBest, uTruth; char * pPerm; int Required, nNodesSaved, nNodesSaveCur; int i, GainCur, GainBest = -1; int clk, clk2;//, Counter; p->nNodesConsidered++; // get the required times Required = fUpdateLevel? Abc_ObjRequiredLevel(pNode) : ABC_INFINITY; // get the node's cuts clk = clock(); pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode, 0, 0 ); assert( pCut != NULL ); p->timeCut += clock() - clk; //printf( " %d", Rwr_CutCountNumNodes(pNode, pCut) ); /* Counter = 0; for ( pTemp = pCut->pNext; pTemp; pTemp = pTemp->pNext ) Counter++; printf( "%d ", Counter ); */ // go through the cuts clk = clock(); for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) { // consider only 4-input cuts if ( pCut->nLeaves < 4 ) continue; // Cut_CutPrint( pCut, 0 ), printf( "\n" ); // get the fanin permutation uTruth = 0xFFFF & *Cut_CutReadTruth(pCut); pPerm = p->pPerms4[ p->pPerms[uTruth] ]; uPhase = p->pPhases[uTruth]; // collect fanins with the corresponding permutation/phase Vec_PtrClear( p->vFaninsCur ); Vec_PtrFill( p->vFaninsCur, (int)pCut->nLeaves, 0 ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) { pFanin = Abc_NtkObj( pNode->pNtk, pCut->pLeaves[pPerm[i]] ); if ( pFanin == NULL ) break; pFanin = Abc_ObjNotCond(pFanin, ((uPhase & (1<<i)) > 0) ); Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); } if ( i != (int)pCut->nLeaves ) { p->nCutsBad++; continue; } p->nCutsGood++; { int Counter = 0; Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) if ( Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) == 1 ) Counter++; if ( Counter > 2 ) continue; } clk2 = clock(); /* printf( "Considering: (" ); Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) printf( "%d ", Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) ); printf( ")\n" ); */ // mark the fanin boundary Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) Abc_ObjRegular(pFanin)->vFanouts.nSize++; // label MFFC with current ID Abc_NtkIncrementTravId( pNode->pNtk ); nNodesSaved = Abc_NodeMffcLabelAig( pNode ); // unmark the fanin boundary Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) Abc_ObjRegular(pFanin)->vFanouts.nSize--; p->timeMffc += clock() - clk2; // evaluate the cut clk2 = clock(); pGraph = Rwr_CutEvaluate( p, pNode, pCut, p->vFaninsCur, nNodesSaved, Required, &GainCur, fPlaceEnable ); p->timeEval += clock() - clk2; // check if the cut is better than the current best one if ( pGraph != NULL && GainBest < GainCur ) { // save this form nNodesSaveCur = nNodesSaved; GainBest = GainCur; p->pGraph = pGraph; p->fCompl = ((uPhase & (1<<4)) > 0); uTruthBest = 0xFFFF & *Cut_CutReadTruth(pCut); // collect fanins in the Vec_PtrClear( p->vFanins ); Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) Vec_PtrPush( p->vFanins, pFanin ); } } p->timeRes += clock() - clk; if ( GainBest == -1 ) return -1; /* if ( GainBest > 0 ) { printf( "Class %d ", p->pMap[uTruthBest] ); printf( "Gain = %d. Node %d : ", GainBest, pNode->Id ); Vec_PtrForEachEntry( p->vFanins, pFanin, i ) printf( "%d ", Abc_ObjRegular(pFanin)->Id ); Dec_GraphPrint( stdout, p->pGraph, NULL, NULL ); printf( "\n" ); } */ // printf( "%d", nNodesSaveCur - GainBest ); /* if ( GainBest > 0 ) { if ( Rwr_CutIsBoolean( pNode, p->vFanins ) ) printf( "b" ); else { printf( "Node %d : ", pNode->Id ); Vec_PtrForEachEntry( p->vFanins, pFanin, i ) printf( "%d ", Abc_ObjRegular(pFanin)->Id ); printf( "a" ); } } */ /* if ( GainBest > 0 ) if ( p->fCompl ) printf( "c" ); else printf( "." ); */ // copy the leaves Vec_PtrForEachEntry( p->vFanins, pFanin, i ) Dec_GraphNode(p->pGraph, i)->pFunc = pFanin; /* printf( "(" ); Vec_PtrForEachEntry( p->vFanins, pFanin, i ) printf( " %d", Abc_ObjRegular(pFanin)->vFanouts.nSize - 1 ); printf( " ) " ); */ // printf( "%d ", Rwr_NodeGetDepth_rec( pNode, p->vFanins ) ); p->nScores[p->pMap[uTruthBest]]++; p->nNodesGained += GainBest; if ( fUseZeros || GainBest > 0 ) { p->nNodesRewritten++; } // report the progress if ( fVeryVerbose && GainBest > 0 ) { printf( "Node %6s : ", Abc_ObjName(pNode) ); printf( "Fanins = %d. ", p->vFanins->nSize ); printf( "Save = %d. ", nNodesSaveCur ); printf( "Add = %d. ", nNodesSaveCur-GainBest ); printf( "GAIN = %d. ", GainBest ); printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 ); printf( "Class = %d. ", p->pMap[uTruthBest] ); printf( "\n" ); } return GainBest; }
/**Function************************************************************* Synopsis [Evaluates the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, int fPlaceEnable ) { Vec_Ptr_t * vSubgraphs; Dec_Graph_t * pGraphBest, * pGraphCur; Rwr_Node_t * pNode, * pFanin; int nNodesAdded, GainBest, i, k; unsigned uTruth; float CostBest;//, CostCur; // find the matching class of subgraphs uTruth = 0xFFFF & *Cut_CutReadTruth(pCut); vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] ); p->nSubgraphs += vSubgraphs->nSize; // determine the best subgraph GainBest = -1; CostBest = ABC_INFINITY; Vec_PtrForEachEntry( vSubgraphs, pNode, i ) { // get the current graph pGraphCur = (Dec_Graph_t *)pNode->pNext; // copy the leaves Vec_PtrForEachEntry( vFaninsCur, pFanin, k ) Dec_GraphNode(pGraphCur, k)->pFunc = pFanin; // detect how many unlabeled nodes will be reused nNodesAdded = Dec_GraphToNetworkCount( pRoot, pGraphCur, nNodesSaved, LevelMax ); if ( nNodesAdded == -1 ) continue; assert( nNodesSaved >= nNodesAdded ); /* // evaluate the cut if ( fPlaceEnable ) { extern float Abc_PlaceEvaluateCut( Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins ); float Alpha = 0.5; // ??? float PlaceCost; // get the placement cost of the cut PlaceCost = Abc_PlaceEvaluateCut( pRoot, vFaninsCur ); // get the weigted cost of the cut CostCur = nNodesSaved - nNodesAdded + Alpha * PlaceCost; // do not allow uphill moves if ( nNodesSaved - nNodesAdded < 0 ) continue; // decide what cut to use if ( CostBest > CostCur ) { GainBest = nNodesSaved - nNodesAdded; // pure node cost CostBest = CostCur; // cost with placement pGraphBest = pGraphCur; // subgraph to be used for rewriting // score the graph if ( nNodesSaved - nNodesAdded > 0 ) { pNode->nScore++; pNode->nGain += GainBest; pNode->nAdded += nNodesAdded; } } } else */ { // count the gain at this node if ( GainBest < nNodesSaved - nNodesAdded ) { GainBest = nNodesSaved - nNodesAdded; pGraphBest = pGraphCur; // score the graph if ( nNodesSaved - nNodesAdded > 0 ) { pNode->nScore++; pNode->nGain += GainBest; pNode->nAdded += nNodesAdded; } } } }
/**Function************************************************************* Synopsis [Computes the truth table of the composition of cuts.] Description [Inputs are: - a factor cut (truth table is stored inside) - a node in the factor cut - a tree cut to be substituted (truth table is stored inside) - the resulting cut (truth table will be filled in). Note that all cuts, including the resulting one, should be already computed and the nodes should be stored in the ascending order.] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_TruthCompose( Cut_Cut_t * pCutF, int Node, Cut_Cut_t * pCutT, Cut_Cut_t * pCutRes ) { static unsigned uCof0[1<<(CUT_CELL_MVAR-5)]; static unsigned uCof1[1<<(CUT_CELL_MVAR-5)]; static unsigned uTemp[1<<(CUT_CELL_MVAR-5)]; unsigned * pIn, * pOut, * pTemp; unsigned uPhase; int NodeIndex, i, k; // sanity checks assert( pCutF->nVarsMax == pCutT->nVarsMax ); assert( pCutF->nVarsMax == pCutRes->nVarsMax ); assert( pCutF->nVarsMax <= CUT_CELL_MVAR ); // the factor cut (pCutF) should have its nodes sorted in the ascending order assert( pCutF->nLeaves <= pCutF->nVarsMax ); for ( i = 0; i < (int)pCutF->nLeaves - 1; i++ ) assert( pCutF->pLeaves[i] < pCutF->pLeaves[i+1] ); // the tree cut (pCutT) should have its nodes sorted in the ascending order assert( pCutT->nLeaves <= pCutT->nVarsMax ); for ( i = 0; i < (int)pCutT->nLeaves - 1; i++ ) assert( pCutT->pLeaves[i] < pCutT->pLeaves[i+1] ); // the resulting cut (pCutRes) should have its nodes sorted in the ascending order assert( pCutRes->nLeaves <= pCutRes->nVarsMax ); for ( i = 0; i < (int)pCutRes->nLeaves - 1; i++ ) assert( pCutRes->pLeaves[i] < pCutRes->pLeaves[i+1] ); // make sure that every node in pCutF (except Node) appears in pCutRes for ( i = 0; i < (int)pCutF->nLeaves; i++ ) { if ( pCutF->pLeaves[i] == Node ) continue; for ( k = 0; k < (int)pCutRes->nLeaves; k++ ) if ( pCutF->pLeaves[i] == pCutRes->pLeaves[k] ) break; assert( k < (int)pCutRes->nLeaves ); // node i from pCutF is not found in pCutRes!!! } // make sure that every node in pCutT appears in pCutRes for ( i = 0; i < (int)pCutT->nLeaves; i++ ) { for ( k = 0; k < (int)pCutRes->nLeaves; k++ ) if ( pCutT->pLeaves[i] == pCutRes->pLeaves[k] ) break; assert( k < (int)pCutRes->nLeaves ); // node i from pCutT is not found in pCutRes!!! } // find the index of the given node in the factor cut NodeIndex = -1; for ( NodeIndex = 0; NodeIndex < (int)pCutF->nLeaves; NodeIndex++ ) if ( pCutF->pLeaves[NodeIndex] == Node ) break; assert( NodeIndex >= 0 ); // Node should be in pCutF // copy the truth table Extra_TruthCopy( uTemp, Cut_CutReadTruth(pCutF), pCutF->nLeaves ); // bubble-move the NodeIndex variable to be the last one (the most significant one) pIn = uTemp; pOut = uCof0; // uCof0 is used for temporary storage here for ( i = NodeIndex; i < (int)pCutF->nLeaves - 1; i++ ) { Extra_TruthSwapAdjacentVars( pOut, pIn, pCutF->nLeaves, i ); pTemp = pIn; pIn = pOut; pOut = pTemp; } if ( (pCutF->nLeaves - 1 - NodeIndex) & 1 ) Extra_TruthCopy( pOut, pIn, pCutF->nLeaves ); // the result of stretching is in uTemp // cofactor the factor cut with respect to the node Extra_TruthCopy( uCof0, uTemp, pCutF->nLeaves ); Extra_TruthCofactor0( uCof0, pCutF->nLeaves, pCutF->nLeaves-1 ); Extra_TruthCopy( uCof1, uTemp, pCutF->nLeaves ); Extra_TruthCofactor1( uCof1, pCutF->nLeaves, pCutF->nLeaves-1 ); // temporarily shrink the factor cut's variables by removing Node for ( i = NodeIndex; i < (int)pCutF->nLeaves - 1; i++ ) pCutF->pLeaves[i] = pCutF->pLeaves[i+1]; pCutF->nLeaves--; // spread out the cofactors' truth tables to the same var order as the resulting cut uPhase = Cut_TruthPhase(pCutRes, pCutF); assert( Extra_WordCountOnes(uPhase) == (int)pCutF->nLeaves ); Extra_TruthStretch( uTemp, uCof0, pCutF->nLeaves, pCutF->nVarsMax, uPhase ); Extra_TruthCopy( uCof0, uTemp, pCutF->nVarsMax ); Extra_TruthStretch( uTemp, uCof1, pCutF->nLeaves, pCutF->nVarsMax, uPhase ); Extra_TruthCopy( uCof1, uTemp, pCutF->nVarsMax ); // spread out the tree cut's truth table to the same var order as the resulting cut uPhase = Cut_TruthPhase(pCutRes, pCutT); assert( Extra_WordCountOnes(uPhase) == (int)pCutT->nLeaves ); Extra_TruthStretch( uTemp, Cut_CutReadTruth(pCutT), pCutT->nLeaves, pCutT->nVarsMax, uPhase ); // create the resulting truth table pTemp = Cut_CutReadTruth(pCutRes); for ( i = Extra_TruthWordNum(pCutRes->nLeaves)-1; i >= 0; i-- ) pTemp[i] = (uCof0[i] & ~uTemp[i]) | (uCof1[i] & uTemp[i]); // undo the removal of the node from the cut for ( i = (int)pCutF->nLeaves - 1; i >= NodeIndex; --i ) pCutF->pLeaves[i+1] = pCutF->pLeaves[i]; pCutF->pLeaves[NodeIndex] = Node; pCutF->nLeaves++; }
/**Function************************************************************* Synopsis [Performs rewriting for one node.] Description [This procedure considers all the cuts computed for the node and tries to rewrite each of them using the "forest" of different AIG structures precomputed and stored in the RWR manager. Determines the best rewriting and computes the gain in the number of AIG nodes in the final network. In the end, p->vFanins contains information about the best cut that can be used for rewriting, while p->pGraph gives the decomposition dag (represented using decomposition graph data structure). Returns gain in the number of nodes or -1 if node cannot be rewritten.] SideEffects [] SeeAlso [] ***********************************************************************/ int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUpdateLevel, int fUseZeros, int fPlaceEnable ) { int fVeryVerbose = 0; Dec_Graph_t * pGraph; Cut_Cut_t * pCut;//, * pTemp; Abc_Obj_t * pFanin; unsigned uPhase; unsigned uTruthBest = 0; // Suppress "might be used uninitialized" unsigned uTruth; char * pPerm; int Required, nNodesSaved; int nNodesSaveCur = -1; // Suppress "might be used uninitialized" int i, GainCur, GainBest = -1; int clk, clk2;//, Counter; p->nNodesConsidered++; // get the required times Required = fUpdateLevel? Abc_ObjRequiredLevel(pNode) : ABC_INFINITY; // get the node's cuts clk = clock(); pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode, 0, 0 ); assert( pCut != NULL ); p->timeCut += clock() - clk; //printf( " %d", Rwr_CutCountNumNodes(pNode, pCut) ); /* Counter = 0; for ( pTemp = pCut->pNext; pTemp; pTemp = pTemp->pNext ) Counter++; printf( "%d ", Counter ); */ // go through the cuts clk = clock(); for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) { // consider only 4-input cuts if ( pCut->nLeaves < 4 ) continue; // Cut_CutPrint( pCut, 0 ), printf( "\n" ); // get the fanin permutation uTruth = 0xFFFF & *Cut_CutReadTruth(pCut); pPerm = p->pPerms4[ (int)p->pPerms[uTruth] ]; uPhase = p->pPhases[uTruth]; // collect fanins with the corresponding permutation/phase Vec_PtrClear( p->vFaninsCur ); Vec_PtrFill( p->vFaninsCur, (int)pCut->nLeaves, 0 ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) { pFanin = Abc_NtkObj( pNode->pNtk, pCut->pLeaves[(int)pPerm[i]] ); if ( pFanin == NULL ) break; pFanin = Abc_ObjNotCond(pFanin, ((uPhase & (1<<i)) > 0) ); Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); } if ( i != (int)pCut->nLeaves ) { p->nCutsBad++; continue; } p->nCutsGood++; { int Counter = 0; Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i ) if ( Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) == 1 ) Counter++; if ( Counter > 2 ) continue; } clk2 = clock(); /* printf( "Considering: (" ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i ) printf( "%d ", Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) ); printf( ")\n" ); */ // mark the fanin boundary Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i ) Abc_ObjRegular(pFanin)->vFanouts.nSize++; // label MFFC with current ID Abc_NtkIncrementTravId( pNode->pNtk ); nNodesSaved = Abc_NodeMffcLabelAig( pNode ); // unmark the fanin boundary Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i ) Abc_ObjRegular(pFanin)->vFanouts.nSize--; p->timeMffc += clock() - clk2; // evaluate the cut clk2 = clock(); pGraph = Rwr_CutEvaluate( p, pNode, pCut, p->vFaninsCur, nNodesSaved, Required, &GainCur, fPlaceEnable ); p->timeEval += clock() - clk2; // check if the cut is better than the current best one if ( pGraph != NULL && GainBest < GainCur ) { // save this form nNodesSaveCur = nNodesSaved; GainBest = GainCur; p->pGraph = pGraph; p->fCompl = ((uPhase & (1<<4)) > 0); uTruthBest = 0xFFFF & *Cut_CutReadTruth(pCut); // collect fanins in the Vec_PtrClear( p->vFanins ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i ) Vec_PtrPush( p->vFanins, pFanin ); } }