| /**CFile**************************************************************** |
| |
| FileName [lpkCore.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Fast Boolean matching for LUT structures.] |
| |
| Synopsis [] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - April 28, 2007.] |
| |
| Revision [$Id: lpkCore.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "lpkInt.h" |
| #include "bool/kit/cloud.h" |
| #include "base/main/main.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prepares the mapping manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Lpk_IfManStart( Lpk_Man_t * p ) |
| { |
| If_Par_t * pPars; |
| assert( p->pIfMan == NULL ); |
| // set defaults |
| pPars = ABC_ALLOC( If_Par_t, 1 ); |
| memset( pPars, 0, sizeof(If_Par_t) ); |
| // user-controlable paramters |
| pPars->nLutSize = p->pPars->nLutSize; |
| pPars->nCutsMax = 16; |
| pPars->nFlowIters = 0; // 1 |
| pPars->nAreaIters = 0; // 1 |
| pPars->DelayTarget = -1; |
| pPars->Epsilon = (float)0.005; |
| pPars->fPreprocess = 0; |
| pPars->fArea = 1; |
| pPars->fFancy = 0; |
| pPars->fExpRed = 0; // |
| pPars->fLatchPaths = 0; |
| pPars->fVerbose = 0; |
| // internal parameters |
| pPars->fTruth = 1; |
| pPars->fUsePerm = 0; |
| pPars->nLatchesCi = 0; |
| pPars->nLatchesCo = 0; |
| pPars->pLutLib = NULL; // Abc_FrameReadLibLut(); |
| pPars->pTimesArr = NULL; |
| pPars->pTimesArr = NULL; |
| pPars->fUseBdds = 0; |
| pPars->fUseSops = 0; |
| pPars->fUseCnfs = 0; |
| pPars->fUseMv = 0; |
| // start the mapping manager and set its parameters |
| p->pIfMan = If_ManStart( pPars ); |
| If_ManSetupSetAll( p->pIfMan, 1000 ); |
| p->pIfMan->pPars->pTimesArr = ABC_ALLOC( float, 32 ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns 1 if at least one entry has changed.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Lpk_NodeHasChanged( Lpk_Man_t * p, int iNode ) |
| { |
| Vec_Ptr_t * vNodes; |
| Abc_Obj_t * pTemp, * pTemp2; |
| int i; |
| vNodes = Vec_VecEntry( p->vVisited, iNode ); |
| if ( Vec_PtrSize(vNodes) == 0 ) |
| return 1; |
| Vec_PtrForEachEntryDouble( Abc_Obj_t *, Abc_Obj_t *, vNodes, pTemp, pTemp2, i ) |
| { |
| // check if the node has changed |
| pTemp = Abc_NtkObj( p->pNtk, (int)(ABC_PTRUINT_T)pTemp ); |
| if ( pTemp == NULL ) |
| return 1; |
| // check if the number of fanouts has changed |
| // if ( Abc_ObjFanoutNum(pTemp) != (int)Vec_PtrEntry(vNodes, i+1) ) |
| // return 1; |
| // i++; |
| } |
| return 0; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prepares the mapping manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Lpk_ExploreCut( Lpk_Man_t * p, Lpk_Cut_t * pCut, Kit_DsdNtk_t * pNtk ) |
| { |
| extern Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover ); |
| Kit_DsdObj_t * pRoot; |
| If_Obj_t * pDriver, * ppLeaves[16]; |
| Abc_Obj_t * pLeaf, * pObjNew; |
| int nGain, i; |
| abctime clk; |
| int nNodesBef; |
| // int nOldShared; |
| |
| // check special cases |
| pRoot = Kit_DsdNtkRoot( pNtk ); |
| if ( pRoot->Type == KIT_DSD_CONST1 ) |
| { |
| if ( Abc_LitIsCompl(pNtk->Root) ) |
| pObjNew = Abc_NtkCreateNodeConst0( p->pNtk ); |
| else |
| pObjNew = Abc_NtkCreateNodeConst1( p->pNtk ); |
| Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels ); |
| p->nGainTotal += pCut->nNodes - pCut->nNodesDup; |
| return 1; |
| } |
| if ( pRoot->Type == KIT_DSD_VAR ) |
| { |
| pObjNew = Abc_NtkObj( p->pNtk, pCut->pLeaves[ Abc_Lit2Var(pRoot->pFans[0]) ] ); |
| if ( Abc_LitIsCompl(pNtk->Root) ^ Abc_LitIsCompl(pRoot->pFans[0]) ) |
| pObjNew = Abc_NtkCreateNodeInv( p->pNtk, pObjNew ); |
| Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels ); |
| p->nGainTotal += pCut->nNodes - pCut->nNodesDup; |
| return 1; |
| } |
| assert( pRoot->Type == KIT_DSD_AND || pRoot->Type == KIT_DSD_XOR || pRoot->Type == KIT_DSD_PRIME ); |
| |
| // start the mapping manager |
| if ( p->pIfMan == NULL ) |
| Lpk_IfManStart( p ); |
| |
| // prepare the mapping manager |
| If_ManRestart( p->pIfMan ); |
| // create the PI variables |
| for ( i = 0; i < p->pPars->nVarsMax; i++ ) |
| ppLeaves[i] = If_ManCreateCi( p->pIfMan ); |
| // set the arrival times |
| Lpk_CutForEachLeaf( p->pNtk, pCut, pLeaf, i ) |
| p->pIfMan->pPars->pTimesArr[i] = (float)pLeaf->Level; |
| // prepare the PI cuts |
| If_ManSetupCiCutSets( p->pIfMan ); |
| // create the internal nodes |
| p->fCalledOnce = 0; |
| p->nCalledSRed = 0; |
| pDriver = Lpk_MapTree_rec( p, pNtk, ppLeaves, pNtk->Root, NULL ); |
| if ( pDriver == NULL ) |
| return 0; |
| // create the PO node |
| If_ManCreateCo( p->pIfMan, If_Regular(pDriver) ); |
| |
| // perform mapping |
| p->pIfMan->pPars->fAreaOnly = 1; |
| clk = Abc_Clock(); |
| If_ManPerformMappingComb( p->pIfMan ); |
| p->timeMap += Abc_Clock() - clk; |
| |
| // compute the gain in area |
| nGain = pCut->nNodes - pCut->nNodesDup - (int)p->pIfMan->AreaGlo; |
| if ( p->pPars->fVeryVerbose ) |
| printf( " Mffc = %2d. Mapped = %2d. Gain = %3d. Depth increase = %d. SReds = %d.\n", |
| pCut->nNodes - pCut->nNodesDup, (int)p->pIfMan->AreaGlo, nGain, (int)p->pIfMan->RequiredGlo - (int)p->pObj->Level, p->nCalledSRed ); |
| |
| // quit if there is no gain |
| if ( !(nGain > 0 || (p->pPars->fZeroCost && nGain == 0)) ) |
| return 0; |
| |
| // quit if depth increases too much |
| if ( (int)p->pIfMan->RequiredGlo > Abc_ObjRequiredLevel(p->pObj) ) |
| return 0; |
| |
| // perform replacement |
| p->nGainTotal += nGain; |
| p->nChanges++; |
| if ( p->nCalledSRed ) |
| p->nBenefited++; |
| |
| nNodesBef = Abc_NtkNodeNum(p->pNtk); |
| // prepare the mapping manager |
| If_ManCleanNodeCopy( p->pIfMan ); |
| If_ManCleanCutData( p->pIfMan ); |
| // set the PIs of the cut |
| Lpk_CutForEachLeaf( p->pNtk, pCut, pLeaf, i ) |
| If_ObjSetCopy( If_ManCi(p->pIfMan, i), pLeaf ); |
| // get the area of mapping |
| pObjNew = Abc_NodeFromIf_rec( p->pNtk, p->pIfMan, If_Regular(pDriver), p->vCover ); |
| pObjNew->pData = Hop_NotCond( (Hop_Obj_t *)pObjNew->pData, If_IsComplement(pDriver) ); |
| // perform replacement |
| Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels ); |
| //printf( "%3d : %d-%d=%d(%d) \n", p->nChanges, nNodesBef, Abc_NtkNodeNum(p->pNtk), nNodesBef-Abc_NtkNodeNum(p->pNtk), nGain ); |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs resynthesis for one node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Lpk_ResynthesizeNode( Lpk_Man_t * p ) |
| { |
| // static int Count = 0; |
| Kit_DsdNtk_t * pDsdNtk; |
| Lpk_Cut_t * pCut; |
| unsigned * pTruth; |
| int i, k, nSuppSize, nCutNodes, RetValue; |
| abctime clk; |
| |
| // compute the cuts |
| clk = Abc_Clock(); |
| if ( !Lpk_NodeCuts( p ) ) |
| { |
| p->timeCuts += Abc_Clock() - clk; |
| return 0; |
| } |
| p->timeCuts += Abc_Clock() - clk; |
| |
| //return 0; |
| |
| if ( p->pPars->fVeryVerbose ) |
| printf( "Node %5d : Mffc size = %5d. Cuts = %5d.\n", p->pObj->Id, p->nMffc, p->nEvals ); |
| // try the good cuts |
| p->nCutsTotal += p->nCuts; |
| p->nCutsUseful += p->nEvals; |
| for ( i = 0; i < p->nEvals; i++ ) |
| { |
| // get the cut |
| pCut = p->pCuts + p->pEvals[i]; |
| if ( p->pPars->fFirst && i == 1 ) |
| break; |
| |
| // skip bad cuts |
| // printf( "Mffc size = %d. ", Abc_NodeMffcLabel(p->pObj) ); |
| for ( k = 0; k < (int)pCut->nLeaves; k++ ) |
| Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize++; |
| nCutNodes = Abc_NodeMffcLabel(p->pObj); |
| // printf( "Mffc with cut = %d. ", nCutNodes ); |
| for ( k = 0; k < (int)pCut->nLeaves; k++ ) |
| Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize--; |
| // printf( "Mffc cut = %d. ", (int)pCut->nNodes - (int)pCut->nNodesDup ); |
| // printf( "\n" ); |
| if ( nCutNodes != (int)pCut->nNodes - (int)pCut->nNodesDup ) |
| continue; |
| |
| // compute the truth table |
| clk = Abc_Clock(); |
| pTruth = Lpk_CutTruth( p, pCut, 0 ); |
| nSuppSize = Extra_TruthSupportSize(pTruth, pCut->nLeaves); |
| p->timeTruth += Abc_Clock() - clk; |
| |
| pDsdNtk = Kit_DsdDecompose( pTruth, pCut->nLeaves ); |
| // Kit_DsdVerify( pDsdNtk, pTruth, pCut->nLeaves ); |
| // skip 16-input non-DSD because ISOP will not work |
| if ( Kit_DsdNtkRoot(pDsdNtk)->nFans == 16 ) |
| { |
| Kit_DsdNtkFree( pDsdNtk ); |
| continue; |
| } |
| |
| // if DSD has nodes that require splitting to fit them into LUTs |
| // we can skip those cuts that cannot lead to improvement |
| // (a full DSD network requires V = Nmin * (K-1) + 1 for improvement) |
| if ( Kit_DsdNonDsdSizeMax(pDsdNtk) > p->pPars->nLutSize && |
| nSuppSize >= ((int)pCut->nNodes - (int)pCut->nNodesDup - 1) * (p->pPars->nLutSize - 1) + 1 ) |
| { |
| Kit_DsdNtkFree( pDsdNtk ); |
| continue; |
| } |
| |
| if ( p->pPars->fVeryVerbose ) |
| { |
| // char * pFileName; |
| printf( " C%02d: L= %2d/%2d V= %2d/%d N= %d W= %4.2f ", |
| i, pCut->nLeaves, nSuppSize, pCut->nNodes, pCut->nNodesDup, pCut->nLuts, pCut->Weight ); |
| Kit_DsdPrint( stdout, pDsdNtk ); |
| Kit_DsdPrintFromTruth( pTruth, pCut->nLeaves ); |
| // pFileName = Kit_TruthDumpToFile( pTruth, pCut->nLeaves, Count++ ); |
| // printf( "Saved truth table in file \"%s\".\n", pFileName ); |
| } |
| |
| // update the network |
| clk = Abc_Clock(); |
| RetValue = Lpk_ExploreCut( p, pCut, pDsdNtk ); |
| p->timeEval += Abc_Clock() - clk; |
| Kit_DsdNtkFree( pDsdNtk ); |
| if ( RetValue ) |
| break; |
| } |
| return 1; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes supports of the cofactors of the function.] |
| |
| Description [This procedure should be called after Lpk_CutTruth(p,pCut,0)] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Lpk_ComputeSupports( Lpk_Man_t * p, Lpk_Cut_t * pCut, unsigned * pTruth ) |
| { |
| unsigned * pTruthInv; |
| int RetValue1, RetValue2; |
| pTruthInv = Lpk_CutTruth( p, pCut, 1 ); |
| RetValue1 = Kit_CreateCloudFromTruth( p->pDsdMan->dd, pTruth, pCut->nLeaves, p->vBddDir ); |
| RetValue2 = Kit_CreateCloudFromTruth( p->pDsdMan->dd, pTruthInv, pCut->nLeaves, p->vBddInv ); |
| if ( RetValue1 && RetValue2 && Vec_IntSize(p->vBddDir) > 1 && Vec_IntSize(p->vBddInv) > 1 ) |
| Kit_TruthCofSupports( p->vBddDir, p->vBddInv, pCut->nLeaves, p->vMemory, p->puSupps ); |
| else |
| p->puSupps[0] = p->puSupps[1] = 0; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs resynthesis for one node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Lpk_ResynthesizeNodeNew( Lpk_Man_t * p ) |
| { |
| // static int Count = 0; |
| Abc_Obj_t * pObjNew, * pLeaf; |
| Lpk_Cut_t * pCut; |
| unsigned * pTruth; |
| int nNodesBef, nNodesAft, nCutNodes; |
| int i, k; |
| abctime clk; |
| int Required = Abc_ObjRequiredLevel(p->pObj); |
| // CloudNode * pFun2;//, * pFun1; |
| |
| // compute the cuts |
| clk = Abc_Clock(); |
| if ( !Lpk_NodeCuts( p ) ) |
| { |
| p->timeCuts += Abc_Clock() - clk; |
| return 0; |
| } |
| p->timeCuts += Abc_Clock() - clk; |
| |
| if ( p->pPars->fVeryVerbose ) |
| printf( "Node %5d : Mffc size = %5d. Cuts = %5d. Level = %2d. Req = %2d.\n", |
| p->pObj->Id, p->nMffc, p->nEvals, p->pObj->Level, Required ); |
| // try the good cuts |
| p->nCutsTotal += p->nCuts; |
| p->nCutsUseful += p->nEvals; |
| for ( i = 0; i < p->nEvals; i++ ) |
| { |
| // get the cut |
| pCut = p->pCuts + p->pEvals[i]; |
| if ( p->pPars->fFirst && i == 1 ) |
| break; |
| // if ( pCut->Weight < 1.05 ) |
| // continue; |
| |
| // skip bad cuts |
| // printf( "Mffc size = %d. ", Abc_NodeMffcLabel(p->pObj) ); |
| for ( k = 0; k < (int)pCut->nLeaves; k++ ) |
| Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize++; |
| nCutNodes = Abc_NodeMffcLabel(p->pObj); |
| // printf( "Mffc with cut = %d. ", nCutNodes ); |
| for ( k = 0; k < (int)pCut->nLeaves; k++ ) |
| Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize--; |
| // printf( "Mffc cut = %d. ", (int)pCut->nNodes - (int)pCut->nNodesDup ); |
| // printf( "\n" ); |
| if ( nCutNodes != (int)pCut->nNodes - (int)pCut->nNodesDup ) |
| continue; |
| |
| // collect nodes into the array |
| Vec_PtrClear( p->vLeaves ); |
| for ( k = 0; k < (int)pCut->nLeaves; k++ ) |
| Vec_PtrPush( p->vLeaves, Abc_NtkObj(p->pNtk, pCut->pLeaves[k]) ); |
| |
| // compute the truth table |
| clk = Abc_Clock(); |
| pTruth = Lpk_CutTruth( p, pCut, 0 ); |
| p->timeTruth += Abc_Clock() - clk; |
| clk = Abc_Clock(); |
| Lpk_ComputeSupports( p, pCut, pTruth ); |
| p->timeSupps += Abc_Clock() - clk; |
| //clk = Abc_Clock(); |
| // pFun1 = Lpk_CutTruthBdd( p, pCut ); |
| //p->timeTruth2 += Abc_Clock() - clk; |
| /* |
| clk = Abc_Clock(); |
| Cloud_Restart( p->pDsdMan->dd ); |
| pFun2 = Kit_TruthToCloud( p->pDsdMan->dd, pTruth, pCut->nLeaves ); |
| RetValue = Kit_CreateCloud( p->pDsdMan->dd, pFun2, p->vBddNodes ); |
| p->timeTruth3 += Abc_Clock() - clk; |
| */ |
| // if ( pFun1 != pFun2 ) |
| // printf( "Truth tables do not agree!\n" ); |
| // else |
| // printf( "Fine!\n" ); |
| |
| if ( p->pPars->fVeryVerbose ) |
| { |
| // char * pFileName; |
| int nSuppSize = Extra_TruthSupportSize( pTruth, pCut->nLeaves ); |
| printf( " C%02d: L= %2d/%2d V= %2d/%d N= %d W= %4.2f ", |
| i, pCut->nLeaves, nSuppSize, pCut->nNodes, pCut->nNodesDup, pCut->nLuts, pCut->Weight ); |
| Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pLeaf, k ) |
| printf( "%c=%d ", 'a'+k, Abc_ObjLevel(pLeaf) ); |
| printf( "\n" ); |
| Kit_DsdPrintFromTruth( pTruth, pCut->nLeaves ); |
| // pFileName = Kit_TruthDumpToFile( pTruth, pCut->nLeaves, Count++ ); |
| // printf( "Saved truth table in file \"%s\".\n", pFileName ); |
| } |
| |
| // update the network |
| nNodesBef = Abc_NtkNodeNum(p->pNtk); |
| clk = Abc_Clock(); |
| pObjNew = Lpk_Decompose( p, p->pNtk, p->vLeaves, pTruth, p->puSupps, p->pPars->nLutSize, |
| (int)pCut->nNodes - (int)pCut->nNodesDup - 1 + (int)(p->pPars->fZeroCost > 0), Required ); |
| p->timeEval += Abc_Clock() - clk; |
| nNodesAft = Abc_NtkNodeNum(p->pNtk); |
| |
| // perform replacement |
| if ( pObjNew ) |
| { |
| int nGain = (int)pCut->nNodes - (int)pCut->nNodesDup - (nNodesAft - nNodesBef); |
| assert( nGain >= 1 - p->pPars->fZeroCost ); |
| assert( Abc_ObjLevel(pObjNew) <= Required ); |
| /* |
| if ( nGain <= 0 ) |
| { |
| int x = 0; |
| } |
| if ( Abc_ObjLevel(pObjNew) > Required ) |
| { |
| int x = 0; |
| } |
| */ |
| p->nGainTotal += nGain; |
| p->nChanges++; |
| if ( p->pPars->fVeryVerbose ) |
| printf( "Performed resynthesis: Gain = %2d. Level = %2d. Req = %2d.\n", nGain, Abc_ObjLevel(pObjNew), Required ); |
| Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels ); |
| //printf( "%3d : %d-%d=%d(%d) \n", p->nChanges, nNodesBef, Abc_NtkNodeNum(p->pNtk), nNodesBef-Abc_NtkNodeNum(p->pNtk), nGain ); |
| break; |
| } |
| } |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs resynthesis for one network.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Lpk_Resynthesize( Abc_Ntk_t * pNtk, Lpk_Par_t * pPars ) |
| { |
| ProgressBar * pProgress = NULL; // Suppress "might be used uninitialized" |
| Lpk_Man_t * p; |
| Abc_Obj_t * pObj; |
| double Delta; |
| // int * pnFanouts, nObjMax; |
| int i, Iter, nNodes, nNodesPrev; |
| abctime clk = Abc_Clock(); |
| assert( Abc_NtkIsLogic(pNtk) ); |
| |
| // sweep dangling nodes as a preprocessing step |
| Abc_NtkSweep( pNtk, 0 ); |
| |
| // get the number of inputs |
| if ( Abc_FrameReadLibLut() ) |
| pPars->nLutSize = ((If_LibLut_t *)Abc_FrameReadLibLut())->LutMax; |
| else |
| pPars->nLutSize = Abc_NtkGetFaninMax( pNtk ); |
| if ( pPars->nLutSize > 6 ) |
| pPars->nLutSize = 6; |
| if ( pPars->nLutSize < 3 ) |
| pPars->nLutSize = 3; |
| // adjust the number of crossbars based on LUT size |
| if ( pPars->nVarsShared > pPars->nLutSize - 2 ) |
| pPars->nVarsShared = pPars->nLutSize - 2; |
| // get the max number of LUTs tried |
| pPars->nVarsMax = pPars->nLutsMax * (pPars->nLutSize - 1) + 1; // V = N * (K-1) + 1 |
| while ( pPars->nVarsMax > 16 ) |
| { |
| pPars->nLutsMax--; |
| pPars->nVarsMax = pPars->nLutsMax * (pPars->nLutSize - 1) + 1; |
| |
| } |
| if ( pPars->fVerbose ) |
| { |
| printf( "Resynthesis for %d %d-LUTs with %d non-MFFC LUTs, %d crossbars, and %d-input cuts.\n", |
| pPars->nLutsMax, pPars->nLutSize, pPars->nLutsOver, pPars->nVarsShared, pPars->nVarsMax ); |
| } |
| |
| |
| // convert into the AIG |
| if ( !Abc_NtkToAig(pNtk) ) |
| { |
| fprintf( stdout, "Converting to BDD has failed.\n" ); |
| return 0; |
| } |
| assert( Abc_NtkHasAig(pNtk) ); |
| |
| // set the number of levels |
| Abc_NtkLevel( pNtk ); |
| Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel ); |
| |
| // start the manager |
| p = Lpk_ManStart( pPars ); |
| p->pNtk = pNtk; |
| p->nNodesTotal = Abc_NtkNodeNum(pNtk); |
| p->vLevels = Vec_VecStart( pNtk->LevelMax ); |
| if ( p->pPars->fSatur ) |
| p->vVisited = Vec_VecStart( 0 ); |
| if ( pPars->fVerbose ) |
| { |
| p->nTotalNets = Abc_NtkGetTotalFanins(pNtk); |
| p->nTotalNodes = Abc_NtkNodeNum(pNtk); |
| } |
| /* |
| // save the number of fanouts of all objects |
| nObjMax = Abc_NtkObjNumMax( pNtk ); |
| pnFanouts = ABC_ALLOC( int, nObjMax ); |
| memset( pnFanouts, 0, sizeof(int) * nObjMax ); |
| Abc_NtkForEachObj( pNtk, pObj, i ) |
| pnFanouts[pObj->Id] = Abc_ObjFanoutNum(pObj); |
| */ |
| |
| // iterate over the network |
| nNodesPrev = p->nNodesTotal; |
| for ( Iter = 1; ; Iter++ ) |
| { |
| // expand storage for changed nodes |
| if ( p->pPars->fSatur ) |
| Vec_VecExpand( p->vVisited, Abc_NtkObjNumMax(pNtk) + 1 ); |
| |
| // consider all nodes |
| nNodes = Abc_NtkObjNumMax(pNtk); |
| if ( !pPars->fVeryVerbose ) |
| pProgress = Extra_ProgressBarStart( stdout, nNodes ); |
| Abc_NtkForEachNode( pNtk, pObj, i ) |
| { |
| // skip all except the final node |
| if ( pPars->fFirst ) |
| { |
| if ( !Abc_ObjIsCo(Abc_ObjFanout0(pObj)) ) |
| continue; |
| } |
| if ( i >= nNodes ) |
| break; |
| if ( !pPars->fVeryVerbose ) |
| Extra_ProgressBarUpdate( pProgress, i, NULL ); |
| // skip the nodes that did not change |
| if ( p->pPars->fSatur && !Lpk_NodeHasChanged(p, pObj->Id) ) |
| continue; |
| // resynthesize |
| p->pObj = pObj; |
| if ( p->pPars->fOldAlgo ) |
| Lpk_ResynthesizeNode( p ); |
| else |
| Lpk_ResynthesizeNodeNew( p ); |
| } |
| if ( !pPars->fVeryVerbose ) |
| Extra_ProgressBarStop( pProgress ); |
| |
| // check the increase |
| Delta = 100.00 * (nNodesPrev - Abc_NtkNodeNum(pNtk)) / p->nNodesTotal; |
| if ( Delta < 0.05 ) |
| break; |
| nNodesPrev = Abc_NtkNodeNum(pNtk); |
| if ( !p->pPars->fSatur ) |
| break; |
| |
| if ( pPars->fFirst ) |
| break; |
| } |
| Abc_NtkStopReverseLevels( pNtk ); |
| /* |
| // report the fanout changes |
| Abc_NtkForEachObj( pNtk, pObj, i ) |
| { |
| if ( i >= nObjMax ) |
| continue; |
| if ( Abc_ObjFanoutNum(pObj) - pnFanouts[pObj->Id] == 0 ) |
| continue; |
| printf( "%d ", Abc_ObjFanoutNum(pObj) - pnFanouts[pObj->Id] ); |
| } |
| printf( "\n" ); |
| */ |
| |
| if ( pPars->fVerbose ) |
| { |
| // Cloud_PrintInfo( p->pDsdMan->dd ); |
| p->nTotalNets2 = Abc_NtkGetTotalFanins(pNtk); |
| p->nTotalNodes2 = Abc_NtkNodeNum(pNtk); |
| printf( "Node gain = %5d. (%.2f %%) ", |
| p->nTotalNodes-p->nTotalNodes2, 100.0*(p->nTotalNodes-p->nTotalNodes2)/p->nTotalNodes ); |
| printf( "Edge gain = %5d. (%.2f %%) ", |
| p->nTotalNets-p->nTotalNets2, 100.0*(p->nTotalNets-p->nTotalNets2)/p->nTotalNets ); |
| printf( "Muxes = %4d. Dsds = %4d.", p->nMuxes, p->nDsds ); |
| printf( "\n" ); |
| printf( "Nodes = %5d (%3d) Cuts = %5d (%4d) Changes = %5d Iter = %2d Benefit = %d.\n", |
| p->nNodesTotal, p->nNodesOver, p->nCutsTotal, p->nCutsUseful, p->nChanges, Iter, p->nBenefited ); |
| |
| printf( "Non-DSD:" ); |
| for ( i = 3; i <= pPars->nVarsMax; i++ ) |
| if ( p->nBlocks[i] ) |
| printf( " %d=%d", i, p->nBlocks[i] ); |
| printf( "\n" ); |
| |
| p->timeTotal = Abc_Clock() - clk; |
| p->timeEval = p->timeEval - p->timeMap; |
| p->timeOther = p->timeTotal - p->timeCuts - p->timeTruth - p->timeEval - p->timeMap; |
| ABC_PRTP( "Cuts ", p->timeCuts, p->timeTotal ); |
| ABC_PRTP( "Truth ", p->timeTruth, p->timeTotal ); |
| ABC_PRTP( "CSupps", p->timeSupps, p->timeTotal ); |
| ABC_PRTP( "Eval ", p->timeEval, p->timeTotal ); |
| ABC_PRTP( " MuxAn", p->timeEvalMuxAn, p->timeEval ); |
| ABC_PRTP( " MuxSp", p->timeEvalMuxSp, p->timeEval ); |
| ABC_PRTP( " DsdAn", p->timeEvalDsdAn, p->timeEval ); |
| ABC_PRTP( " DsdSp", p->timeEvalDsdSp, p->timeEval ); |
| ABC_PRTP( " Other", p->timeEval-p->timeEvalMuxAn-p->timeEvalMuxSp-p->timeEvalDsdAn-p->timeEvalDsdSp, p->timeEval ); |
| ABC_PRTP( "Map ", p->timeMap, p->timeTotal ); |
| ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); |
| ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); |
| } |
| |
| Lpk_ManStop( p ); |
| // check the resulting network |
| if ( !Abc_NtkCheck( pNtk ) ) |
| { |
| printf( "Lpk_Resynthesize: The network check has failed.\n" ); |
| return 0; |
| } |
| return 1; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |