/**Function************************************************************* Synopsis [Collects used internal nodes in a topological order.] Description [Additionally considers objects in groups as a single object and collects them in a topological order together as single entity.] SideEffects [] SeeAlso [] ***********************************************************************/ void Sfm_NtkDfs_rec( Sfm_Ntk_t * p, int iNode, Vec_Int_t * vNodes, Vec_Wec_t * vGroups, Vec_Int_t * vGroupMap, Vec_Int_t * vBoxesLeft ) { int i, iFanin; if ( Sfm_ObjIsPi(p, iNode) ) return; if ( Sfm_ObjIsTravIdCurrent(p, iNode) ) return; if ( Vec_IntEntry(vGroupMap, iNode) >= 0 ) { int k, iGroup = Abc_Lit2Var( Vec_IntEntry(vGroupMap, iNode) ); Vec_Int_t * vGroup = Vec_WecEntry( vGroups, iGroup ); Vec_IntForEachEntry( vGroup, iNode, i ) assert( Sfm_ObjIsNode(p, iNode) ); Vec_IntForEachEntry( vGroup, iNode, i ) Sfm_ObjSetTravIdCurrent( p, iNode ); Vec_IntForEachEntry( vGroup, iNode, i ) Sfm_ObjForEachFanin( p, iNode, iFanin, k ) Sfm_NtkDfs_rec( p, iFanin, vNodes, vGroups, vGroupMap, vBoxesLeft ); Vec_IntForEachEntry( vGroup, iNode, i ) Vec_IntPush( vNodes, iNode ); Vec_IntPush( vBoxesLeft, iGroup ); } else { Sfm_ObjSetTravIdCurrent(p, iNode); Sfm_ObjForEachFanin( p, iNode, iFanin, i ) Sfm_NtkDfs_rec( p, iFanin, vNodes, vGroups, vGroupMap, vBoxesLeft ); Vec_IntPush( vNodes, iNode ); } }
int Sfm_ObjMffcSize( Sfm_Ntk_t * p, int iObj ) { int Count1, Count2; if ( Sfm_ObjIsPi(p, iObj) ) return 0; if ( Sfm_ObjFanoutNum(p, iObj) != 1 ) return 0; assert( Sfm_ObjIsNode( p, iObj ) ); Count1 = Sfm_ObjDeref( p, iObj ); Count2 = Sfm_ObjRef( p, iObj ); assert( Count1 == Count2 ); return Count1; }
int Sfm_NodeResub( Sfm_Ntk_t * p, int iNode ) { int i, iFanin; p->nNodesTried++; // prepare SAT solver if ( !Sfm_NtkCreateWindow( p, iNode, p->pPars->fVeryVerbose ) ) return 0; if ( !Sfm_NtkWindowToSolver( p ) ) return 0; // try replacing area critical fanins Sfm_ObjForEachFanin( p, iNode, iFanin, i ) if ( Sfm_ObjIsNode(p, iFanin) && Sfm_ObjFanoutNum(p, iFanin) == 1 ) { if ( Sfm_NodeResubSolve( p, iNode, i, 0 ) ) return 1; } if ( p->pPars->fArea ) return 0; // try removing redundant edges Sfm_ObjForEachFanin( p, iNode, iFanin, i ) if ( !(Sfm_ObjIsNode(p, iFanin) && Sfm_ObjFanoutNum(p, iFanin) == 1) ) { if ( Sfm_NodeResubSolve( p, iNode, i, 1 ) ) return 1; } /* // try replacing area critical fanins while adding two new fanins if ( Sfm_ObjFaninNum(p, iNode) < p->nFaninMax ) Abc_ObjForEachFanin( pNode, pFanin, i ) if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) { if ( Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) ) return 1; } */ return 0; }
int Sfm_ObjDeref_rec( Sfm_Ntk_t * p, int iObj ) { int i, iFanin, Value, Count; if ( Sfm_ObjIsPi(p, iObj) ) return 0; assert( Sfm_ObjIsNode(p, iObj) ); Value = Sfm_ObjRefDecrement(p, iObj); if ( Value > 0 ) return 0; assert( Value == 0 ); Count = 1; Sfm_ObjForEachFanin( p, iObj, iFanin, i ) Count += Sfm_ObjDeref_rec( p, iFanin ); return Count; }
void Sfm_NtkComputeRoots_rec( Sfm_Ntk_t * p, int iNode, int nLevelMax, Vec_Int_t * vRoots, Vec_Int_t * vTfo ) { int i, iFanout; assert( Sfm_ObjIsNode(p, iNode) ); if ( Sfm_ObjIsTravIdCurrent(p, iNode) ) return; Sfm_ObjSetTravIdCurrent(p, iNode); if ( iNode != p->iPivotNode ) Vec_IntPush( vTfo, iNode ); // check if the node should be the root if ( Sfm_NtkCheckRoot( p, iNode, nLevelMax ) ) Vec_IntPush( vRoots, iNode ); else // if not, explore its fanouts Sfm_ObjForEachFanout( p, iNode, iFanout, i ) Sfm_NtkComputeRoots_rec( p, iFanout, nLevelMax, vRoots, vTfo ); }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the MFFC size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_ObjRef_rec( Sfm_Ntk_t * p, int iObj ) { int i, iFanin, Value, Count; if ( Sfm_ObjIsPi(p, iObj) ) return 0; assert( Sfm_ObjIsNode(p, iObj) ); Value = Sfm_ObjRefIncrement(p, iObj); if ( Value > 1 ) return 0; assert( Value == 1 ); Count = 1; Sfm_ObjForEachFanin( p, iObj, iFanin, i ) Count += Sfm_ObjRef_rec( p, iFanin ); return Count; }
int Sfm_NtkCreateWindow( Sfm_Ntk_t * p, int iNode, int fVerbose ) { int i, k, iTemp; abctime clkDiv, clkWin = Abc_Clock(); assert( Sfm_ObjIsNode( p, iNode ) ); p->iPivotNode = iNode; Vec_IntClear( p->vNodes ); // internal Vec_IntClear( p->vDivs ); // divisors Vec_IntClear( p->vRoots ); // roots Vec_IntClear( p->vTfo ); // roots Vec_IntClear( p->vOrder ); // variable order // collect transitive fanin Sfm_NtkIncrementTravId( p ); if ( Sfm_NtkCollectTfi_rec( p, iNode, p->vNodes ) ) { p->nMaxDivs++; p->timeWin += Abc_Clock() - clkWin; return 0; } // create divisors clkDiv = Abc_Clock(); Vec_IntClear( p->vDivs ); Vec_IntAppend( p->vDivs, p->vNodes ); Vec_IntPop( p->vDivs ); // add non-topological divisors if ( Vec_IntSize(p->vDivs) < p->pPars->nWinSizeMax + 0 ) { Sfm_NtkIncrementTravId2( p ); Vec_IntForEachEntry( p->vDivs, iTemp, i ) if ( Vec_IntSize(p->vDivs) < p->pPars->nWinSizeMax + 0 ) // Sfm_NtkAddDivisors( p, iTemp, Sfm_ObjLevel(p, iNode) - 1 ); Sfm_NtkAddDivisors( p, iTemp, p->nLevelMax - Sfm_ObjLevelR(p, iNode) ); }
/**Function************************************************************* Synopsis [Performs resubstitution for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_NodeResubSolve( Sfm_Ntk_t * p, int iNode, int f, int fRemoveOnly ) { int fSkipUpdate = 0; int fVeryVerbose = 0;//p->pPars->fVeryVerbose && Vec_IntSize(p->vDivs) < 200;// || pNode->Id == 556; int i, iFanin, iVar = -1; word uTruth, uSign, uMask; abctime clk; assert( Sfm_ObjIsNode(p, iNode) ); assert( f >= 0 && f < Sfm_ObjFaninNum(p, iNode) ); p->nTryRemoves++; // report init stats if ( p->pPars->fVeryVerbose ) printf( "%5d : Lev =%3d. Leaf =%3d. Node =%3d. Div=%3d. Fanin =%4d (%d/%d). MFFC = %d\n", iNode, Sfm_ObjLevel(p, iNode), 0, Vec_IntSize(p->vNodes), Vec_IntSize(p->vDivs), Sfm_ObjFanin(p, iNode, f), f, Sfm_ObjFaninNum(p, iNode), Sfm_ObjMffcSize(p, Sfm_ObjFanin(p, iNode, f)) ); // clean simulation info p->nCexes = 0; Vec_WrdFill( p->vDivCexes, Vec_IntSize(p->vDivs), 0 ); // try removing the critical fanin Vec_IntClear( p->vDivIds ); Sfm_ObjForEachFanin( p, iNode, iFanin, i ) if ( i != f ) Vec_IntPush( p->vDivIds, Sfm_ObjSatVar(p, iFanin) ); clk = Abc_Clock(); uTruth = Sfm_ComputeInterpolant( p ); p->timeSat += Abc_Clock() - clk; // analyze outcomes if ( uTruth == SFM_SAT_UNDEC ) { p->nTimeOuts++; return 0; } if ( uTruth != SFM_SAT_SAT ) goto finish; if ( fRemoveOnly || p->pPars->fRrOnly || Vec_IntSize(p->vDivs) == 0 ) return 0; p->nTryResubs++; if ( fVeryVerbose ) { for ( i = 0; i < 9; i++ ) printf( " " ); for ( i = 0; i < Vec_IntSize(p->vDivs); i++ ) printf( "%d", i % 10 ); printf( "\n" ); } while ( 1 ) { if ( fVeryVerbose ) { printf( "%3d: %3d ", p->nCexes, iVar ); Vec_WrdForEachEntry( p->vDivCexes, uSign, i ) printf( "%d", Abc_InfoHasBit((unsigned *)&uSign, p->nCexes-1) ); printf( "\n" ); } // find the next divisor to try uMask = (~(word)0) >> (64 - p->nCexes); Vec_WrdForEachEntry( p->vDivCexes, uSign, iVar ) if ( uSign == uMask ) break; if ( iVar == Vec_IntSize(p->vDivs) ) return 0; // try replacing the critical fanin Vec_IntPush( p->vDivIds, Sfm_ObjSatVar(p, Vec_IntEntry(p->vDivs, iVar)) ); clk = Abc_Clock(); uTruth = Sfm_ComputeInterpolant( p ); p->timeSat += Abc_Clock() - clk; // analyze outcomes if ( uTruth == SFM_SAT_UNDEC ) { p->nTimeOuts++; return 0; } if ( uTruth != SFM_SAT_SAT ) goto finish; if ( p->nCexes == 64 ) return 0; // remove the last variable Vec_IntPop( p->vDivIds ); } finish: if ( p->pPars->fVeryVerbose ) { if ( iVar == -1 ) printf( "Node %d: Fanin %d (%d) can be removed. ", iNode, f, Sfm_ObjFanin(p, iNode, f) ); else printf( "Node %d: Fanin %d (%d) can be replaced by divisor %d (%d). ", iNode, f, Sfm_ObjFanin(p, iNode, f), iVar, Vec_IntEntry(p->vDivs, iVar) ); Kit_DsdPrintFromTruth( (unsigned *)&uTruth, Vec_IntSize(p->vDivIds) ); printf( "\n" ); } if ( iVar == -1 ) p->nRemoves++; else p->nResubs++; if ( fSkipUpdate ) return 0; // update the network Sfm_NtkUpdate( p, iNode, f, (iVar == -1 ? iVar : Vec_IntEntry(p->vDivs, iVar)), uTruth ); return 1; }