diff options
Diffstat (limited to 'src/opt')
-rw-r--r-- | src/opt/cut/cut.h | 2 | ||||
-rw-r--r-- | src/opt/cut/cutNode.c | 7 | ||||
-rw-r--r-- | src/opt/lpk/lpkAbcDsd.c | 7 | ||||
-rw-r--r-- | src/opt/lpk/lpkCore.c | 4 | ||||
-rw-r--r-- | src/opt/mfs/mfs.h | 1 | ||||
-rw-r--r-- | src/opt/mfs/mfsCore.c | 248 | ||||
-rw-r--r-- | src/opt/mfs/mfsCore_.c | 388 | ||||
-rw-r--r-- | src/opt/mfs/mfsInt.h | 5 | ||||
-rw-r--r-- | src/opt/mfs/mfsMan.c | 25 | ||||
-rw-r--r-- | src/opt/mfs/mfsResub.c | 67 | ||||
-rw-r--r-- | src/opt/mfs/mfsResub_.c | 560 | ||||
-rw-r--r-- | src/opt/sim/simSwitch.c | 2 |
12 files changed, 1295 insertions, 21 deletions
diff --git a/src/opt/cut/cut.h b/src/opt/cut/cut.h index dee05dfc..faa249f2 100644 --- a/src/opt/cut/cut.h +++ b/src/opt/cut/cut.h @@ -64,8 +64,10 @@ struct Cut_ParamsStruct_t_ int fGlobal; // compute only global cuts int fLocal; // compute only local cuts int fRecord; // record the cut computation flow + int fRecordAig; // record the cut functions int fFancy; // perform fancy computations int fMap; // computes delay of FPGA mapping with cuts + int fAdjust; // removed useless fanouts of XORs/MUXes int fVerbose; // the verbosiness flag }; diff --git a/src/opt/cut/cutNode.c b/src/opt/cut/cutNode.c index 2d17020b..633219fd 100644 --- a/src/opt/cut/cutNode.c +++ b/src/opt/cut/cutNode.c @@ -393,6 +393,13 @@ p->timeMerge += clock() - clk; Vec_IntPush( p->vCutPairs, ((pCut->Num1 << 16) | pCut->Num0) ); Vec_IntWriteEntry( p->vNodeCuts, Node, Vec_IntSize(p->vCutPairs) - Vec_IntEntry(p->vNodeStarts, Node) ); } + if ( p->pParams->fRecordAig ) + { + extern void Aig_RManRecord( unsigned * pTruth, int nVarsInit ); + Cut_ListForEachCut( pList, pCut ) + if ( Cut_CutReadLeaveNum(pCut) > 4 ) + Aig_RManRecord( Cut_CutReadTruth(pCut), Cut_CutReadLeaveNum(pCut) ); + } // check if the node is over the list if ( p->nNodeCuts == p->pParams->nKeepMax ) p->nCutsLimit++; diff --git a/src/opt/lpk/lpkAbcDsd.c b/src/opt/lpk/lpkAbcDsd.c index 46d9179a..a1cd9def 100644 --- a/src/opt/lpk/lpkAbcDsd.c +++ b/src/opt/lpk/lpkAbcDsd.c @@ -287,7 +287,12 @@ void Lpk_FunCompareBoundSets( Lpk_Fun_t * p, Vec_Int_t * vBSets, int nCofDepth, if ( (uBoundSet & uLateArrSupp) ) // skip those boundsets that are late arriving continue; if ( fVerbose ) -Lpk_PrintSetOne( uBoundSet ); +{ +Lpk_PrintSetOne( uBoundSet & 0xFFFF ); +//printf( "\n" ); +//Lpk_PrintSetOne( uBoundSet >> 16 ); +//printf( "\n" ); +} assert( (uBoundSet & (uBoundSet >> 16)) == 0 ); nVarsBS = Kit_WordCountOnes( uBoundSet & 0xFFFF ); if ( nVarsBS == 1 ) diff --git a/src/opt/lpk/lpkCore.c b/src/opt/lpk/lpkCore.c index 78356d81..d8dd15b7 100644 --- a/src/opt/lpk/lpkCore.c +++ b/src/opt/lpk/lpkCore.c @@ -387,6 +387,10 @@ p->timeCuts += clock() - clk; p->nCutsUseful += p->nEvals; for ( i = 0; i < p->nEvals; i++ ) { + if ( p->pObj->Id == 1478 ) + { + int x = 0; + } // get the cut pCut = p->pCuts + p->pEvals[i]; if ( p->pPars->fFirst && i == 1 ) diff --git a/src/opt/mfs/mfs.h b/src/opt/mfs/mfs.h index 9550a31b..bddb9328 100644 --- a/src/opt/mfs/mfs.h +++ b/src/opt/mfs/mfs.h @@ -54,6 +54,7 @@ struct Mfs_Par_t_ int fSwapEdge; // performs edge swapping int fOneHotness; // adds one-hotness conditions int fDelay; // performs optimization for delay + int fPower; // performs power-aware optimization int fVerbose; // enable basic stats int fVeryVerbose; // enable detailed stats }; diff --git a/src/opt/mfs/mfsCore.c b/src/opt/mfs/mfsCore.c index 3444bab1..e8820acd 100644 --- a/src/opt/mfs/mfsCore.c +++ b/src/opt/mfs/mfsCore.c @@ -9,7 +9,7 @@ Synopsis [Core procedures of this package.] Author [Alan Mishchenko] - + Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] @@ -24,6 +24,8 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +extern int Abc_NtkMfsSolveSatResub( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int fOnlyRemove, int fSkipUpdate ); + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -33,7 +35,7 @@ Synopsis [] Description [] - + SideEffects [] SeeAlso [] @@ -57,13 +59,176 @@ void Abc_NtkMfsParsDefault( Mfs_Par_t * pPars ) pPars->fVerbose = 0; pPars->fVeryVerbose = 0; } +/* +int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + float * pProbab = (float *)p->vProbs->pArray; + int i; + // try replacing area critical fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( pProbab[pFanin->Id] >= 0.4 ) + { + if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) + return 1; + } else if ( pProbab[pFanin->Id] >= 0.3 ) + { + if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) ) + return 1; + } + } + return 0; +} +*/ + +int Abc_WinNode(Mfs_Man_t * p, Abc_Obj_t *pNode) +{ +// int clk; +// Abc_Obj_t * pFanin; + float * pProbab = (float *)p->vProbs->pArray; +// int i; + + p->nNodesTried++; + // prepare data structure for this node + Mfs_ManClean( p ); + // compute window roots, window support, and window nodes + p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax ); + p->vSupp = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); + p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); + if ( p->pPars->nWinSizeMax && Vec_PtrSize(p->vNodes) > p->pPars->nWinSizeMax ) + return 1; + // compute the divisors of the window + p->vDivs = Abc_MfsComputeDivisors( p, pNode, Abc_ObjRequiredLevel(pNode) - 1 ); + p->nTotalDivs += Vec_PtrSize(p->vDivs); + // construct AIG for the window + p->pAigWin = Abc_NtkConstructAig( p, pNode ); + // translate it into CNF + p->pCnf = Cnf_DeriveSimple( p->pAigWin, 1 + Vec_PtrSize(p->vDivs) ); + // create the SAT problem + p->pSat = Abc_MfsCreateSolverResub( p, NULL, 0, 0 ); + if ( p->pSat == NULL ) + { + p->nNodesBad++; + return 1; + } + return 0; +} + +/* +int Abc_NtkMfsPowerResubNode( Mfs_Man_t * p, Abc_Obj_t * pNode ) +{ + int clk; + Abc_Obj_t * pFanin; + float * pProbab = (float *)p->vProbs->pArray; + int i; + + if (Abc_WinNode(p, pNode) // something wrong + return 1; + + // solve the SAT problem + // Abc_NtkMfsEdgePower( p, pNode ); + // try replacing area critical fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pProbab[pFanin->Id] >= 0.37 && Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) + return 1; + + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pProbab[pFanin->Id] >= 0.1 && Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) ) + return 1; + + if ( Abc_ObjFaninNum(pNode) == p->nFaninMax ) + return 0; + + // try replacing area critical fanins while adding two new fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pProbab[pFanin->Id] >= 0.37 && Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) ) + return 1; + } + return 0; + + return 1; +} +*/ + +Abc_NtkMfsPowerResub( Mfs_Man_t * p, Mfs_Par_t * pPars) +{ + int i, k; + Abc_Obj_t *pFanin, *pNode; + Abc_Ntk_t *pNtk = p->pNtk; + int nFaninMax = Abc_NtkGetFaninMax(p->pNtk); + float * pProbab = (float *)p->vProbs->pArray; + + Abc_NtkForEachNode( pNtk, pNode, k ) + { + if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax ) + continue; + if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax ) + continue; + if (Abc_WinNode(p, pNode) ) // something wrong + continue; + + // solve the SAT problem + // Abc_NtkMfsEdgePower( p, pNode ); + // try replacing area critical fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pProbab[pFanin->Id] >= 0.35 && Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) + continue; + } + + Abc_NtkForEachNode( pNtk, pNode, k ) + { + if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax ) + continue; + if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax ) + continue; + if (Abc_WinNode(p, pNode) ) // something wrong + continue; + + // solve the SAT problem + // Abc_NtkMfsEdgePower( p, pNode ); + // try replacing area critical fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pProbab[pFanin->Id] >= 0.35 && Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) + continue; + } + + Abc_NtkForEachNode( pNtk, pNode, k ) + { + if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax ) + continue; + if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax ) + continue; + if (Abc_WinNode(p, pNode) ) // something wrong + continue; + + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pProbab[pFanin->Id] >= 0.2 && Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) ) + continue; + } +/* + Abc_NtkForEachNode( pNtk, pNode, k ) + { + if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax ) + continue; + if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax - 2) + continue; + if (Abc_WinNode(p, pNode) ) // something wrong + continue; + + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pProbab[pFanin->Id] >= 0.37 && Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) ) + continue; + } +*/ +} /**Function************************************************************* Synopsis [] Description [] - + SideEffects [] SeeAlso [] @@ -74,7 +239,7 @@ int Abc_NtkMfsResub( Mfs_Man_t * p, Abc_Obj_t * pNode ) int clk; p->nNodesTried++; // prepare data structure for this node - Mfs_ManClean( p ); + Mfs_ManClean( p ); // compute window roots, window support, and window nodes clk = clock(); p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax ); @@ -105,7 +270,9 @@ clk = clock(); return 1; } // solve the SAT problem - if ( p->pPars->fSwapEdge ) + if ( p->pPars->fPower ) + Abc_NtkMfsEdgePower( p, pNode ); + else if ( p->pPars->fSwapEdge ) Abc_NtkMfsEdgeSwapEval( p, pNode ); else { @@ -122,7 +289,7 @@ p->timeSat += clock() - clk; Synopsis [] Description [] - + SideEffects [] SeeAlso [] @@ -132,7 +299,8 @@ int Abc_NtkMfsNode( Mfs_Man_t * p, Abc_Obj_t * pNode ) { Hop_Obj_t * pObj; int RetValue; - extern Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare ); + float dProb; + extern Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb ); int nGain, clk; p->nNodesTried++; @@ -173,14 +341,15 @@ p->timeSat += clock() - clk; } // minimize the local function of the node using bi-decomposition assert( p->nFanins == Abc_ObjFaninNum(pNode) ); - pObj = Abc_NodeIfNodeResyn( p->pManDec, pNode->pNtk->pManFunc, pNode->pData, p->nFanins, p->vTruth, p->uCare ); + dProb = p->pPars->fPower? ((float *)p->vProbs->pArray)[pNode->Id] : -1.0; + pObj = Abc_NodeIfNodeResyn( p->pManDec, pNode->pNtk->pManFunc, pNode->pData, p->nFanins, p->vTruth, p->uCare, dProb ); nGain = Hop_DagSize(pNode->pData) - Hop_DagSize(pObj); if ( nGain >= 0 ) { p->nNodesDec++; p->nNodesGained += nGain; p->nNodesGainedLevel += nGain; - pNode->pData = pObj; + pNode->pData = pObj; } return 1; } @@ -190,7 +359,7 @@ p->timeSat += clock() - clk; Synopsis [] Description [] - + SideEffects [] SeeAlso [] @@ -198,7 +367,7 @@ p->timeSat += clock() - clk; ***********************************************************************/ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) { - extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters ); + extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); Bdc_Par_t Pars = {0}, * pDecPars = &Pars; ProgressBar * pProgress; @@ -242,16 +411,32 @@ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) p = Mfs_ManAlloc( pPars ); p->pNtk = pNtk; p->nFaninMax = nFaninMax; + + // precomputer power-aware metrics + if ( pPars->fPower ) + { + extern Vec_Int_t * Abc_NtkPowerEstimate( Abc_Ntk_t * pNtk, int fProbOne ); + if ( pPars->fResub ) + p->vProbs = Abc_NtkPowerEstimate( pNtk, 0 ); + else + p->vProbs = Abc_NtkPowerEstimate( pNtk, 1 ); +#if 0 + printf( "Total switching before = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); +#else + p->TotalSwitchingBeg = Abc_NtkMfsTotalSwitching(pNtk); +#endif + } + if ( pNtk->pExcare ) { Abc_Ntk_t * pTemp; if ( Abc_NtkPiNum(pNtk->pExcare) != Abc_NtkCiNum(pNtk) ) - printf( "The PI count of careset (%d) and logic network (%d) differ. Careset is not used.\n", + printf( "The PI count of careset (%d) and logic network (%d) differ. Careset is not used.\n", Abc_NtkPiNum(pNtk->pExcare), Abc_NtkCiNum(pNtk) ); else { pTemp = Abc_NtkStrash( pNtk->pExcare, 0, 0, 0 ); - p->pCare = Abc_NtkToDar( pTemp, 0 ); + p->pCare = Abc_NtkToDar( pTemp, 0, 0 ); Abc_NtkDelete( pTemp ); p->vSuppsInv = Aig_ManSupportsInverse( p->pCare ); } @@ -273,7 +458,7 @@ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pData = (void *)(PORT_PTRUINT_T)i; } - + // compute levels Abc_NtkLevel( pNtk ); Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel ); @@ -284,6 +469,14 @@ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) p->nTotalEdgesBeg = nTotalEdgesBeg; if ( pPars->fResub ) { +#if 0 + printf( "TotalSwitching (%7.2f --> ", Abc_NtkMfsTotalSwitching(pNtk) ); +#endif + if (pPars->fPower) + { + Abc_NtkMfsPowerResub( p, pPars); + } else + { pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pObj, i ) { @@ -299,9 +492,15 @@ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) Abc_NtkMfsNode( p, pObj ); } Extra_ProgressBarStop( pProgress ); +#if 0 + printf( " %7.2f )\n", Abc_NtkMfsTotalSwitching(pNtk) ); +#endif } - else + } else { +#if 0 + printf( "Total switching before = %7.2f, ----> ", Abc_NtkMfsTotalSwitching(pNtk) ); +#endif pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); vLevels = Abc_NtkLevelize( pNtk ); Vec_VecForEachLevelStart( vLevels, vNodes, k, 1 ) @@ -320,22 +519,27 @@ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) continue; if ( pPars->fResub ) Abc_NtkMfsResub( p, pObj ); - else + else Abc_NtkMfsNode( p, pObj ); } nNodes += Vec_PtrSize(vNodes); if ( pPars->fVerbose ) { - printf( "Lev = %2d. Node = %5d. Ave gain = %5.2f. Ave conf = %5.2f. T/o = %6.2f %% ", + /* + printf( "Lev = %2d. Node = %5d. Ave gain = %5.2f. Ave conf = %5.2f. T/o = %6.2f %% ", k, Vec_PtrSize(vNodes), 1.0*p->nNodesGainedLevel/Vec_PtrSize(vNodes), 1.0*p->nTotConfLevel/Vec_PtrSize(vNodes), 100.0*p->nTimeOutsLevel/Vec_PtrSize(vNodes) ); PRT( "Time", clock() - clk2 ); + */ } } Extra_ProgressBarStop( pProgress ); Vec_VecFree( vLevels ); +#if 0 + printf( " %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); +#endif } Abc_NtkStopReverseLevels( pNtk ); @@ -357,6 +561,16 @@ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) pObj->pData = NULL; } + if ( pPars->fPower ) + { +#if 1 + p->TotalSwitchingEnd = Abc_NtkMfsTotalSwitching(pNtk); +// printf( "Total switching after = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); +#else + printf( "Total switching after = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); +#endif + } + // free the manager p->timeTotal = clock() - clk; Mfs_ManStop( p ); diff --git a/src/opt/mfs/mfsCore_.c b/src/opt/mfs/mfsCore_.c new file mode 100644 index 00000000..66b497f6 --- /dev/null +++ b/src/opt/mfs/mfsCore_.c @@ -0,0 +1,388 @@ +/**CFile**************************************************************** + + FileName [mfsCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [The good old minimization with complete don't-cares.] + + Synopsis [Core procedures of this package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: mfsCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mfsInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMfsParsDefault( Mfs_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Mfs_Par_t) ); + pPars->nWinTfoLevs = 2; + pPars->nFanoutsMax = 10; + pPars->nDepthMax = 20; + pPars->nDivMax = 250; + pPars->nWinSizeMax = 300; + pPars->nGrowthLevel = 0; + pPars->nBTLimit = 5000; + pPars->fResub = 1; + pPars->fArea = 0; + pPars->fMoreEffort = 0; + pPars->fSwapEdge = 0; + pPars->fOneHotness = 0; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsResub( Mfs_Man_t * p, Abc_Obj_t * pNode ) +{ + int clk; + p->nNodesTried++; + // prepare data structure for this node + Mfs_ManClean( p ); + // compute window roots, window support, and window nodes +clk = clock(); + p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax ); + p->vSupp = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); + p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); +p->timeWin += clock() - clk; + if ( p->pPars->nWinSizeMax && Vec_PtrSize(p->vNodes) > p->pPars->nWinSizeMax ) + return 1; + // compute the divisors of the window +clk = clock(); + p->vDivs = Abc_MfsComputeDivisors( p, pNode, Abc_ObjRequiredLevel(pNode) - 1 ); + p->nTotalDivs += Vec_PtrSize(p->vDivs); +p->timeDiv += clock() - clk; + // construct AIG for the window +clk = clock(); + p->pAigWin = Abc_NtkConstructAig( p, pNode ); +p->timeAig += clock() - clk; + // translate it into CNF +clk = clock(); + p->pCnf = Cnf_DeriveSimple( p->pAigWin, 1 + Vec_PtrSize(p->vDivs) ); +p->timeCnf += clock() - clk; + // create the SAT problem +clk = clock(); + p->pSat = Abc_MfsCreateSolverResub( p, NULL, 0, 0 ); + if ( p->pSat == NULL ) + { + p->nNodesBad++; + return 1; + } + // solve the SAT problem + if ( p->pPars->fPower ) + Abc_NtkMfsEdgePower( p, pNode ); + else if ( p->pPars->fSwapEdge ) + Abc_NtkMfsEdgeSwapEval( p, pNode ); + else + { + Abc_NtkMfsResubNode( p, pNode ); + if ( p->pPars->fMoreEffort ) + Abc_NtkMfsResubNode2( p, pNode ); + } +p->timeSat += clock() - clk; + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsNode( Mfs_Man_t * p, Abc_Obj_t * pNode ) +{ + Hop_Obj_t * pObj; + int RetValue; + float dProb; + extern Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb ); + + int nGain, clk; + p->nNodesTried++; + // prepare data structure for this node + Mfs_ManClean( p ); + // compute window roots, window support, and window nodes +clk = clock(); + p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax ); + p->vSupp = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); + p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); +p->timeWin += clock() - clk; + // count the number of patterns +// p->dTotalRatios += Abc_NtkConstraintRatio( p, pNode ); + // construct AIG for the window +clk = clock(); + p->pAigWin = Abc_NtkConstructAig( p, pNode ); +p->timeAig += clock() - clk; + // translate it into CNF +clk = clock(); + p->pCnf = Cnf_DeriveSimple( p->pAigWin, Abc_ObjFaninNum(pNode) ); +p->timeCnf += clock() - clk; + // create the SAT problem +clk = clock(); + p->pSat = Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 ); + if ( p->pSat && p->pPars->fOneHotness ) + Abc_NtkAddOneHotness( p ); + if ( p->pSat == NULL ) + return 0; + // solve the SAT problem + RetValue = Abc_NtkMfsSolveSat( p, pNode ); + p->nTotConfLevel += p->pSat->stats.conflicts; +p->timeSat += clock() - clk; + if ( RetValue == 0 ) + { + p->nTimeOutsLevel++; + p->nTimeOuts++; + return 0; + } + // minimize the local function of the node using bi-decomposition + assert( p->nFanins == Abc_ObjFaninNum(pNode) ); + dProb = p->pPars->fPower? ((float *)p->vProbs->pArray)[pNode->Id] : -1.0; + pObj = Abc_NodeIfNodeResyn( p->pManDec, pNode->pNtk->pManFunc, pNode->pData, p->nFanins, p->vTruth, p->uCare, dProb ); + nGain = Hop_DagSize(pNode->pData) - Hop_DagSize(pObj); + if ( nGain >= 0 ) + { + p->nNodesDec++; + p->nNodesGained += nGain; + p->nNodesGainedLevel += nGain; + pNode->pData = pObj; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) +{ + extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); + + Bdc_Par_t Pars = {0}, * pDecPars = &Pars; + ProgressBar * pProgress; + Mfs_Man_t * p; + Abc_Obj_t * pObj; + Vec_Vec_t * vLevels; + Vec_Ptr_t * vNodes; + int i, k, nNodes, nFaninMax, clk = clock(), clk2; + int nTotalNodesBeg = Abc_NtkNodeNum(pNtk); + int nTotalEdgesBeg = Abc_NtkGetTotalFanins(pNtk); + + assert( Abc_NtkIsLogic(pNtk) ); + nFaninMax = Abc_NtkGetFaninMax(pNtk); + if ( pPars->fResub ) + { + if ( nFaninMax > 8 ) + { + printf( "Nodes with more than %d fanins will node be processed.\n", 8 ); + nFaninMax = 8; + } + } + else + { + if ( nFaninMax > MFS_FANIN_MAX ) + { + printf( "Nodes with more than %d fanins will node be processed.\n", MFS_FANIN_MAX ); + nFaninMax = MFS_FANIN_MAX; + } + } + // perform the network sweep + Abc_NtkSweep( pNtk, 0 ); + // convert into the AIG + if ( !Abc_NtkToAig(pNtk) ) + { + fprintf( stdout, "Converting to AIGs has failed.\n" ); + return 0; + } + assert( Abc_NtkHasAig(pNtk) ); + + // start the manager + p = Mfs_ManAlloc( pPars ); + p->pNtk = pNtk; + p->nFaninMax = nFaninMax; + + // precomputer power-aware metrics + if ( pPars->fPower ) + { + extern Vec_Int_t * Abc_NtkPowerEstimate( Abc_Ntk_t * pNtk, int fProbOne ); + if ( pPars->fResub ) + p->vProbs = Abc_NtkPowerEstimate( pNtk, 0 ); + else + p->vProbs = Abc_NtkPowerEstimate( pNtk, 1 ); + printf( "Total switching before = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); + } + + if ( pNtk->pExcare ) + { + Abc_Ntk_t * pTemp; + if ( Abc_NtkPiNum(pNtk->pExcare) != Abc_NtkCiNum(pNtk) ) + printf( "The PI count of careset (%d) and logic network (%d) differ. Careset is not used.\n", + Abc_NtkPiNum(pNtk->pExcare), Abc_NtkCiNum(pNtk) ); + else + { + pTemp = Abc_NtkStrash( pNtk->pExcare, 0, 0, 0 ); + p->pCare = Abc_NtkToDar( pTemp, 0, 0 ); + Abc_NtkDelete( pTemp ); + p->vSuppsInv = Aig_ManSupportsInverse( p->pCare ); + } + } + if ( p->pCare != NULL ) + printf( "Performing optimization with %d external care clauses.\n", Aig_ManPoNum(p->pCare) ); + // prepare the BDC manager + if ( !pPars->fResub ) + { + pDecPars->nVarsMax = (nFaninMax < 3) ? 3 : nFaninMax; + pDecPars->fVerbose = pPars->fVerbose; + p->vTruth = Vec_IntAlloc( 0 ); + p->pManDec = Bdc_ManAlloc( pDecPars ); + } + + // label the register outputs + if ( p->pCare ) + { + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pData = (void *)(PORT_PTRUINT_T)i; + } + + // compute levels + Abc_NtkLevel( pNtk ); + Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel ); + + // compute don't-cares for each node + nNodes = 0; + p->nTotalNodesBeg = nTotalNodesBeg; + p->nTotalEdgesBeg = nTotalEdgesBeg; + if ( pPars->fResub ) + { + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( p->pPars->nDepthMax && (int)pObj->Level > p->pPars->nDepthMax ) + continue; + if ( Abc_ObjFaninNum(pObj) < 2 || Abc_ObjFaninNum(pObj) > nFaninMax ) + continue; + if ( !p->pPars->fVeryVerbose ) + Extra_ProgressBarUpdate( pProgress, i, NULL ); + if ( pPars->fResub ) + Abc_NtkMfsResub( p, pObj ); + else + Abc_NtkMfsNode( p, pObj ); + } + Extra_ProgressBarStop( pProgress ); + } + else + { + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); + vLevels = Abc_NtkLevelize( pNtk ); + Vec_VecForEachLevelStart( vLevels, vNodes, k, 1 ) + { + if ( !p->pPars->fVeryVerbose ) + Extra_ProgressBarUpdate( pProgress, nNodes, NULL ); + p->nNodesGainedLevel = 0; + p->nTotConfLevel = 0; + p->nTimeOutsLevel = 0; + clk2 = clock(); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + if ( p->pPars->nDepthMax && (int)pObj->Level > p->pPars->nDepthMax ) + break; + if ( Abc_ObjFaninNum(pObj) < 2 || Abc_ObjFaninNum(pObj) > nFaninMax ) + continue; + if ( pPars->fResub ) + Abc_NtkMfsResub( p, pObj ); + else + Abc_NtkMfsNode( p, pObj ); + } + nNodes += Vec_PtrSize(vNodes); + if ( pPars->fVerbose ) + { + printf( "Lev = %2d. Node = %5d. Ave gain = %5.2f. Ave conf = %5.2f. T/o = %6.2f %% ", + k, Vec_PtrSize(vNodes), + 1.0*p->nNodesGainedLevel/Vec_PtrSize(vNodes), + 1.0*p->nTotConfLevel/Vec_PtrSize(vNodes), + 100.0*p->nTimeOutsLevel/Vec_PtrSize(vNodes) ); + PRT( "Time", clock() - clk2 ); + } + } + Extra_ProgressBarStop( pProgress ); + Vec_VecFree( vLevels ); + } + Abc_NtkStopReverseLevels( pNtk ); + + // perform the sweeping + if ( !pPars->fResub ) + { + extern void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose ); +// Abc_NtkSweep( pNtk, 0 ); +// Abc_NtkBidecResyn( pNtk, 0 ); + } + + p->nTotalNodesEnd = Abc_NtkNodeNum(pNtk); + p->nTotalEdgesEnd = Abc_NtkGetTotalFanins(pNtk); + + // undo labesl + if ( p->pCare ) + { + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pData = NULL; + } + if ( pPars->fPower ) + printf( "Total switching after = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); + + // free the manager + p->timeTotal = clock() - clk; + Mfs_ManStop( p ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/opt/mfs/mfsInt.h b/src/opt/mfs/mfsInt.h index df8a4848..9eb6e4a4 100644 --- a/src/opt/mfs/mfsInt.h +++ b/src/opt/mfs/mfsInt.h @@ -81,6 +81,8 @@ struct Mfs_Man_t_ Vec_Ptr_t * vFanins; // the new set of fanins int nTotConfLim; // total conflict limit int nTotConfLevel; // total conflicts on this level + // switching activity + Vec_Int_t * vProbs; // the result of solving int nFanins; // the number of fanins int nWords; // the number of words @@ -102,6 +104,8 @@ struct Mfs_Man_t_ int nTotalNodesEnd; int nTotalEdgesBeg; int nTotalEdgesEnd; + float TotalSwitchingBeg; + float TotalSwitchingEnd; // statistics int timeWin; int timeDiv; @@ -137,6 +141,7 @@ extern void Mfs_ManClean( Mfs_Man_t * p ); /*=== mfsResub.c ==========================================================*/ extern void Abc_NtkMfsPrintResubStats( Mfs_Man_t * p ); extern int Abc_NtkMfsEdgeSwapEval( Mfs_Man_t * p, Abc_Obj_t * pNode ); +extern int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode ); extern int Abc_NtkMfsResubNode( Mfs_Man_t * p, Abc_Obj_t * pNode ); extern int Abc_NtkMfsResubNode2( Mfs_Man_t * p, Abc_Obj_t * pNode ); /*=== mfsSat.c ==========================================================*/ diff --git a/src/opt/mfs/mfsMan.c b/src/opt/mfs/mfsMan.c index d0642368..9a043ed8 100644 --- a/src/opt/mfs/mfsMan.c +++ b/src/opt/mfs/mfsMan.c @@ -108,6 +108,7 @@ void Mfs_ManPrint( Mfs_Man_t * p ) { if ( p->pPars->fResub ) { +/* printf( "Reduction in nodes = %5d. (%.2f %%) ", p->nTotalNodesBeg-p->nTotalNodesEnd, 100.0*(p->nTotalNodesBeg-p->nTotalNodesEnd)/p->nTotalNodesBeg ); @@ -123,6 +124,28 @@ void Mfs_ManPrint( Mfs_Man_t * p ) else Abc_NtkMfsPrintResubStats( p ); // printf( "Average ratio of DCs in the resubed nodes = %.2f.\n", 1.0*p->nDcMints/(64 * p->nNodesResub) ); +*/ + printf( "@@@------- Node( %4d, %4.2f%% ), ", + p->nTotalNodesBeg-p->nTotalNodesEnd, + 100.0*(p->nTotalNodesBeg-p->nTotalNodesEnd)/p->nTotalNodesBeg ); + printf( "Edge( %4d, %4.2f%% ), ", + p->nTotalEdgesBeg-p->nTotalEdgesEnd, + 100.0*(p->nTotalEdgesBeg-p->nTotalEdgesEnd)/p->nTotalEdgesBeg ); + if (p->pPars->fPower) + printf( "Power( %5.2f, %4.2f%%) ", + p->TotalSwitchingBeg - p->TotalSwitchingEnd, + 100.0*(p->TotalSwitchingBeg-p->TotalSwitchingEnd)/p->TotalSwitchingBeg ); + printf( "\n" ); +#if 0 + printf( "Nodes = %d. Try = %d. Resub = %d. Div = %d. SAT calls = %d. Timeouts = %d.\n", + Abc_NtkNodeNum(p->pNtk), p->nNodesTried, p->nNodesResub, p->nTotalDivs, p->nSatCalls, p->nTimeOuts ); +#endif + if ( p->pPars->fSwapEdge ) + printf( "Swappable edges = %d. Total edges = %d. Ratio = %5.2f.\n", + p->nNodesResub, Abc_NtkGetTotalFanins(p->pNtk), 1.00 * p->nNodesResub / Abc_NtkGetTotalFanins(p->pNtk) ); + else + Abc_NtkMfsPrintResubStats( p ); +// printf( "Average ratio of DCs in the resubed nodes = %.2f.\n", 1.0*p->nDcMints/(64 * p->nNodesResub) ); } else { @@ -168,6 +191,8 @@ void Mfs_ManStop( Mfs_Man_t * p ) Aig_ManStop( p->pCare ); if ( p->vSuppsInv ) Vec_VecFree( (Vec_Vec_t *)p->vSuppsInv ); + if ( p->vProbs ) + Vec_IntFree( p->vProbs ); Mfs_ManClean( p ); Int_ManFree( p->pMan ); Vec_IntFree( p->vMem ); diff --git a/src/opt/mfs/mfsResub.c b/src/opt/mfs/mfsResub.c index b6c7299b..e9ea2c40 100644 --- a/src/opt/mfs/mfsResub.c +++ b/src/opt/mfs/mfsResub.c @@ -80,8 +80,8 @@ void Abc_NtkMfsPrintResubStats( Mfs_Man_t * p ) nAreaExpanse += (int)(Abc_ObjFaninNum(pNode) < nFaninMax); } } - printf( "Total area-critical fanins = %d. Belonging to expandable nodes = %d.\n", - nAreaCrits, nAreaExpanse ); +// printf( "Total area-critical fanins = %d. Belonging to expandable nodes = %d.\n", +// nAreaCrits, nAreaExpanse ); } /**Function************************************************************* @@ -209,6 +209,8 @@ p->timeInt += clock() - clk; iVar = -1; while ( 1 ) { + float * pProbab = (float *)(p->vProbs? p->vProbs->pArray : NULL); + assert( (pProbab != NULL) == p->pPars->fPower ); if ( fVeryVerbose ) { printf( "%3d: %2d ", p->nCexes, iVar ); @@ -225,6 +227,13 @@ p->timeInt += clock() - clk; assert( nWords <= p->nDivWords ); for ( iVar = 0; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ ) { + if ( p->pPars->fPower ) + { + Abc_Obj_t * pDiv = Vec_PtrEntry(p->vDivs, iVar); + // only accept the divisor if it is "cool" + if ( pProbab[Abc_ObjId(pDiv)] >= 0.15 ) + continue; + } pData = Vec_PtrEntry( p->vDivCexes, iVar ); for ( w = 0; w < nWords; w++ ) if ( pData[w] != ~0 ) @@ -345,6 +354,10 @@ p->timeInt += clock() - clk; iVar = iVar2 = -1; while ( 1 ) { +#if 1 // sjang + float * pProbab = (float *)(p->vProbs? p->vProbs->pArray : NULL); + assert( (pProbab != NULL) == p->pPars->fPower ); +#endif if ( fVeryVerbose ) { printf( "%3d: %2d %2d ", p->nCexes, iVar, iVar2 ); @@ -363,9 +376,27 @@ p->timeInt += clock() - clk; for ( iVar = 1; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ ) { pData = Vec_PtrEntry( p->vDivCexes, iVar ); +#if 1 // sjang + if ( p->pPars->fPower ) + { + Abc_Obj_t * pDiv = Vec_PtrEntry(p->vDivs, iVar); + // only accept the divisor if it is "cool" + if ( pProbab[Abc_ObjId(pDiv)] >= 0.12 ) + continue; + } +#endif for ( iVar2 = 0; iVar2 < iVar; iVar2++ ) { pData2 = Vec_PtrEntry( p->vDivCexes, iVar2 ); +#if 1 // sjang + if ( p->pPars->fPower ) + { + Abc_Obj_t * pDiv = Vec_PtrEntry(p->vDivs, iVar2); + // only accept the divisor if it is "cool" + if ( pProbab[Abc_ObjId(pDiv)] >= 0.12 ) + continue; + } +#endif for ( w = 0; w < nWords; w++ ) if ( (pData[w] | pData2[w]) != ~0 ) break; @@ -434,6 +465,38 @@ int Abc_NtkMfsEdgeSwapEval( Mfs_Man_t * p, Abc_Obj_t * pNode ) /**Function************************************************************* + Synopsis [Evaluates the possibility of replacing given edge by another edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + float * pProbab = (float *)p->vProbs->pArray; + int i; + // try replacing area critical fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( pProbab[pFanin->Id] >= 0.35 ) + { + if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) + return 1; + } else if ( pProbab[pFanin->Id] >= 0.25 ) // sjang + { + if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) ) + return 1; + } + } + return 0; +} + +/**Function************************************************************* + Synopsis [Performs resubstitution for the node.] Description [] diff --git a/src/opt/mfs/mfsResub_.c b/src/opt/mfs/mfsResub_.c new file mode 100644 index 00000000..47600b30 --- /dev/null +++ b/src/opt/mfs/mfsResub_.c @@ -0,0 +1,560 @@ +/**CFile**************************************************************** + + FileName [mfsResub.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [The good old minimization with complete don't-cares.] + + Synopsis [Procedures to perform resubstitution.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: mfsResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mfsInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Updates the network after resubstitution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMfsUpdateNetwork( Mfs_Man_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc ) +{ + Abc_Obj_t * pObjNew, * pFanin; + int k; + // create the new node + pObjNew = Abc_NtkCreateNode( pObj->pNtk ); + pObjNew->pData = pFunc; + Vec_PtrForEachEntry( vFanins, pFanin, k ) + Abc_ObjAddFanin( pObjNew, pFanin ); + // replace the old node by the new node +//printf( "Replacing node " ); Abc_ObjPrint( stdout, pObj ); +//printf( "Inserting node " ); Abc_ObjPrint( stdout, pObjNew ); + // update the level of the node + Abc_NtkUpdate( pObj, pObjNew, p->vLevels ); +} + +/**Function************************************************************* + + Synopsis [Prints resub candidate stats.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMfsPrintResubStats( Mfs_Man_t * p ) +{ + Abc_Obj_t * pFanin, * pNode; + int i, k, nAreaCrits = 0, nAreaExpanse = 0; + int nFaninMax = Abc_NtkGetFaninMax(p->pNtk); + Abc_NtkForEachNode( p->pNtk, pNode, i ) + Abc_ObjForEachFanin( pNode, pFanin, k ) + { + if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) + { + nAreaCrits++; + nAreaExpanse += (int)(Abc_ObjFaninNum(pNode) < nFaninMax); + } + } + printf( "Total area-critical fanins = %d. Belonging to expandable nodes = %d.\n", + nAreaCrits, nAreaExpanse ); +} + +/**Function************************************************************* + + Synopsis [Tries resubstitution.] + + Description [Returns 1 if it is feasible, or 0 if c-ex is found.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsTryResubOnce( Mfs_Man_t * p, int * pCands, int nCands ) +{ + unsigned * pData; + int RetValue, iVar, i; + p->nSatCalls++; + RetValue = sat_solver_solve( p->pSat, pCands, pCands + nCands, (sint64)p->pPars->nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); +// assert( RetValue == l_False || RetValue == l_True ); + if ( RetValue == l_False ) + return 1; + if ( RetValue != l_True ) + { + p->nTimeOuts++; + return -1; + } + p->nSatCexes++; + // store the counter-example + Vec_IntForEachEntry( p->vProjVars, iVar, i ) + { + pData = Vec_PtrEntry( p->vDivCexes, i ); + if ( !sat_solver_var_value( p->pSat, iVar ) ) // remove 0s!!! + { + assert( Aig_InfoHasBit(pData, p->nCexes) ); + Aig_InfoXorBit( pData, p->nCexes ); + } + } + p->nCexes++; + return 0; +} + +/**Function************************************************************* + + Synopsis [Performs resubstitution for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsSolveSatResub( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int fOnlyRemove, int fSkipUpdate ) +{ + int fVeryVerbose = p->pPars->fVeryVerbose && Vec_PtrSize(p->vDivs) < 80; + unsigned * pData; + int pCands[MFS_FANIN_MAX]; + int RetValue, iVar, i, nCands, nWords, w, clk; + Abc_Obj_t * pFanin; + Hop_Obj_t * pFunc; + assert( iFanin >= 0 ); + + // clean simulation info + Vec_PtrFillSimInfo( p->vDivCexes, 0, p->nDivWords ); + p->nCexes = 0; + if ( fVeryVerbose ) + { + printf( "\n" ); + printf( "Node %5d : Level = %2d. Divs = %3d. Fanin = %d (out of %d). MFFC = %d\n", + pNode->Id, pNode->Level, Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode), + iFanin, Abc_ObjFaninNum(pNode), + Abc_ObjFanoutNum(Abc_ObjFanin(pNode, iFanin)) == 1 ? Abc_NodeMffcLabel(Abc_ObjFanin(pNode, iFanin)) : 0 ); + } + + // try fanins without the critical fanin + nCands = 0; + Vec_PtrClear( p->vFanins ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( i == iFanin ) + continue; + Vec_PtrPush( p->vFanins, pFanin ); + iVar = Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode) + i; + pCands[nCands++] = toLitCond( Vec_IntEntry( p->vProjVars, iVar ), 1 ); + } + RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands ); + if ( RetValue == -1 ) + return 0; + if ( RetValue == 1 ) + { + if ( fVeryVerbose ) + printf( "Node %d: Fanin %d can be removed.\n", pNode->Id, iFanin ); + p->nNodesResub++; + p->nNodesGainedLevel++; + if ( fSkipUpdate ) + return 1; +clk = clock(); + // derive the function + pFunc = Abc_NtkMfsInterplate( p, pCands, nCands ); + if ( pFunc == NULL ) + return 0; + // update the network + Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc ); +p->timeInt += clock() - clk; + return 1; + } + + if ( fOnlyRemove ) + return 0; + + if ( fVeryVerbose ) + { + for ( i = 0; i < 8; i++ ) + printf( " " ); + for ( i = 0; i < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); i++ ) + printf( "%d", i % 10 ); + for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) + if ( i == iFanin ) + printf( "*" ); + else + printf( "%c", 'a' + i ); + printf( "\n" ); + } + iVar = -1; + while ( 1 ) + { + float * pProbab = (float *)(p->vProbs? p->vProbs->pArray : NULL); + assert( (pProbab != NULL) == p->pPars->fPower ); + if ( fVeryVerbose ) + { + printf( "%3d: %2d ", p->nCexes, iVar ); + for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ ) + { + pData = Vec_PtrEntry( p->vDivCexes, i ); + printf( "%d", Aig_InfoHasBit(pData, p->nCexes-1) ); + } + printf( "\n" ); + } + + // find the next divisor to try + nWords = Aig_BitWordNum(p->nCexes); + assert( nWords <= p->nDivWords ); + for ( iVar = 0; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ ) + { + if ( p->pPars->fPower ) + { + Abc_Obj_t * pDiv = Vec_PtrEntry(p->vDivs, iVar); + // only accept the divisor if it is "cool" + if ( pProbab[Abc_ObjId(pDiv)] >= 0.2 ) + continue; + } + pData = Vec_PtrEntry( p->vDivCexes, iVar ); + for ( w = 0; w < nWords; w++ ) + if ( pData[w] != ~0 ) + break; + if ( w == nWords ) + break; + } + if ( iVar == Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode) ) + return 0; + + pCands[nCands] = toLitCond( Vec_IntEntry(p->vProjVars, iVar), 1 ); + RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands+1 ); + if ( RetValue == -1 ) + return 0; + if ( RetValue == 1 ) + { + if ( fVeryVerbose ) + printf( "Node %d: Fanin %d can be replaced by divisor %d.\n", pNode->Id, iFanin, iVar ); + p->nNodesResub++; + p->nNodesGainedLevel++; + if ( fSkipUpdate ) + return 1; +clk = clock(); + // derive the function + pFunc = Abc_NtkMfsInterplate( p, pCands, nCands+1 ); + if ( pFunc == NULL ) + return 0; + // update the network + Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar) ); + Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc ); +p->timeInt += clock() - clk; + return 1; + } + if ( p->nCexes >= p->pPars->nDivMax ) + break; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Performs resubstitution for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsSolveSatResub2( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int iFanin2 ) +{ + int fVeryVerbose = p->pPars->fVeryVerbose && Vec_PtrSize(p->vDivs) < 80; + unsigned * pData, * pData2; + int pCands[MFS_FANIN_MAX]; + int RetValue, iVar, iVar2, i, w, nCands, clk, nWords, fBreak; + Abc_Obj_t * pFanin; + Hop_Obj_t * pFunc; + assert( iFanin >= 0 ); + assert( iFanin2 >= 0 || iFanin2 == -1 ); + + // clean simulation info + Vec_PtrFillSimInfo( p->vDivCexes, 0, p->nDivWords ); + p->nCexes = 0; + if ( fVeryVerbose ) + { + printf( "\n" ); + printf( "Node %5d : Level = %2d. Divs = %3d. Fanins = %d/%d (out of %d). MFFC = %d\n", + pNode->Id, pNode->Level, Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode), + iFanin, iFanin2, Abc_ObjFaninNum(pNode), + Abc_ObjFanoutNum(Abc_ObjFanin(pNode, iFanin)) == 1 ? Abc_NodeMffcLabel(Abc_ObjFanin(pNode, iFanin)) : 0 ); + } + + // try fanins without the critical fanin + nCands = 0; + Vec_PtrClear( p->vFanins ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( i == iFanin || i == iFanin2 ) + continue; + Vec_PtrPush( p->vFanins, pFanin ); + iVar = Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode) + i; + pCands[nCands++] = toLitCond( Vec_IntEntry( p->vProjVars, iVar ), 1 ); + } + RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands ); + if ( RetValue == -1 ) + return 0; + if ( RetValue == 1 ) + { + if ( fVeryVerbose ) + printf( "Node %d: Fanins %d/%d can be removed.\n", pNode->Id, iFanin, iFanin2 ); + p->nNodesResub++; + p->nNodesGainedLevel++; +clk = clock(); + // derive the function + pFunc = Abc_NtkMfsInterplate( p, pCands, nCands ); + if ( pFunc == NULL ) + return 0; + // update the network + Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc ); +p->timeInt += clock() - clk; + return 1; + } + + if ( fVeryVerbose ) + { + for ( i = 0; i < 11; i++ ) + printf( " " ); + for ( i = 0; i < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); i++ ) + printf( "%d", i % 10 ); + for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) + if ( i == iFanin || i == iFanin2 ) + printf( "*" ); + else + printf( "%c", 'a' + i ); + printf( "\n" ); + } + iVar = iVar2 = -1; + while ( 1 ) + { + if ( fVeryVerbose ) + { + printf( "%3d: %2d %2d ", p->nCexes, iVar, iVar2 ); + for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ ) + { + pData = Vec_PtrEntry( p->vDivCexes, i ); + printf( "%d", Aig_InfoHasBit(pData, p->nCexes-1) ); + } + printf( "\n" ); + } + + // find the next divisor to try + nWords = Aig_BitWordNum(p->nCexes); + assert( nWords <= p->nDivWords ); + fBreak = 0; + for ( iVar = 1; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ ) + { + pData = Vec_PtrEntry( p->vDivCexes, iVar ); + for ( iVar2 = 0; iVar2 < iVar; iVar2++ ) + { + pData2 = Vec_PtrEntry( p->vDivCexes, iVar2 ); + for ( w = 0; w < nWords; w++ ) + if ( (pData[w] | pData2[w]) != ~0 ) + break; + if ( w == nWords ) + { + fBreak = 1; + break; + } + } + if ( fBreak ) + break; + } + if ( iVar == Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode) ) + return 0; + + pCands[nCands] = toLitCond( Vec_IntEntry(p->vProjVars, iVar2), 1 ); + pCands[nCands+1] = toLitCond( Vec_IntEntry(p->vProjVars, iVar), 1 ); + RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands+2 ); + if ( RetValue == -1 ) + return 0; + if ( RetValue == 1 ) + { + if ( fVeryVerbose ) + printf( "Node %d: Fanins %d/%d can be replaced by divisors %d/%d.\n", pNode->Id, iFanin, iFanin2, iVar, iVar2 ); + p->nNodesResub++; + p->nNodesGainedLevel++; +clk = clock(); + // derive the function + pFunc = Abc_NtkMfsInterplate( p, pCands, nCands+2 ); + if ( pFunc == NULL ) + return 0; + // update the network + Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar2) ); + Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar) ); + assert( Vec_PtrSize(p->vFanins) == nCands + 2 ); + Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc ); +p->timeInt += clock() - clk; + return 1; + } + if ( p->nCexes >= p->pPars->nDivMax ) + break; + } + return 0; +} + + +/**Function************************************************************* + + Synopsis [Evaluates the possibility of replacing given edge by another edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsEdgeSwapEval( Mfs_Man_t * p, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + int i; + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 1 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Evaluates the possibility of replacing given edge by another edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + float * pProbab = (float *)p->vProbs->pArray; + int i; + // try replacing area critical fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pProbab[pFanin->Id] >= 0.4 ) + { + if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Performs resubstitution for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsResubNode( Mfs_Man_t * p, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + int i; + // try replacing area critical fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) + { + if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) + return 1; + } + // try removing redundant edges + if ( !p->pPars->fArea ) + { + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( Abc_ObjIsCi(pFanin) || Abc_ObjFanoutNum(pFanin) != 1 ) + { + if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) ) + return 1; + } + } + if ( Abc_ObjFaninNum(pNode) == p->nFaninMax ) + return 0; + // try replacing area critical fanins while adding two new fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) + { + if ( Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) ) + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Performs resubstitution for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsResubNode2( Mfs_Man_t * p, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin, * pFanin2; + int i, k; +/* + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) + { + if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) + return 1; + } +*/ + if ( Abc_ObjFaninNum(pNode) < 2 ) + return 0; + // try replacing one area critical fanin and one other fanin while adding two new fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) + { + // consider second fanin to remove at the same time + Abc_ObjForEachFanin( pNode, pFanin2, k ) + { + if ( i != k && Abc_NtkMfsSolveSatResub2( p, pNode, i, k ) ) + return 1; + } + } + } + return 0; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/opt/sim/simSwitch.c b/src/opt/sim/simSwitch.c index 218d4d59..baabc320 100644 --- a/src/opt/sim/simSwitch.c +++ b/src/opt/sim/simSwitch.c @@ -97,7 +97,7 @@ float Sim_ComputeSwitching( unsigned * pSimInfo, int nSimWords ) int nOnes, nTotal; nTotal = 32 * nSimWords; nOnes = Sim_UtilCountOnes( pSimInfo, nSimWords ); - return (float)2.0 * nOnes * (nTotal - nOnes) / nTotal / nTotal; + return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal; } //////////////////////////////////////////////////////////////////////// |