| /**CFile**************************************************************** |
| |
| FileName [mpmMap.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Configurable technology mapper.] |
| |
| Synopsis [Mapping algorithm.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 1, 2013.] |
| |
| Revision [$Id: mpmMap.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "mpmInt.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| //#define MIG_RUNTIME |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Cut manipulation.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline int Mpm_CutAlloc( Mpm_Man_t * p, int nLeaves, Mpm_Cut_t ** ppCut ) |
| { |
| int hHandle = Mmr_StepFetch( p->pManCuts, Mpm_CutWordNum(nLeaves) ); |
| *ppCut = (Mpm_Cut_t *)Mmr_StepEntry( p->pManCuts, hHandle ); |
| (*ppCut)->nLeaves = nLeaves; |
| (*ppCut)->hNext = 0; |
| (*ppCut)->fUseless = 0; |
| (*ppCut)->fCompl = 0; |
| return hHandle; |
| } |
| static inline int Mpm_CutCreateZero( Mpm_Man_t * p ) |
| { |
| Mpm_Cut_t * pCut; |
| int hCut = Mpm_CutAlloc( p, 0, &pCut ); |
| pCut->iFunc = 0; // const0 |
| return hCut; |
| } |
| static inline int Mpm_CutCreateUnit( Mpm_Man_t * p, int Id ) |
| { |
| Mpm_Cut_t * pCut; |
| int hCut = Mpm_CutAlloc( p, 1, &pCut ); |
| pCut->iFunc = Abc_Var2Lit( p->funcVar0, 0 ); // var |
| pCut->pLeaves[0] = Abc_Var2Lit( Id, 0 ); |
| return hCut; |
| } |
| static inline int Mpm_CutCreate( Mpm_Man_t * p, Mpm_Cut_t * pUni, Mpm_Cut_t ** ppCut ) |
| { |
| int hCutNew = Mpm_CutAlloc( p, pUni->nLeaves, ppCut ); |
| (*ppCut)->iFunc = pUni->iFunc; |
| (*ppCut)->fCompl = pUni->fCompl; |
| (*ppCut)->fUseless = pUni->fUseless; |
| (*ppCut)->nLeaves = pUni->nLeaves; |
| memcpy( (*ppCut)->pLeaves, pUni->pLeaves, sizeof(int) * pUni->nLeaves ); |
| return hCutNew; |
| } |
| static inline int Mpm_CutDup( Mpm_Man_t * p, Mpm_Cut_t * pCut, int fCompl ) |
| { |
| Mpm_Cut_t * pCutNew; |
| int hCutNew = Mpm_CutAlloc( p, pCut->nLeaves, &pCutNew ); |
| pCutNew->iFunc = Abc_LitNotCond( pCut->iFunc, fCompl ); |
| pCutNew->fUseless = pCut->fUseless; |
| pCutNew->nLeaves = pCut->nLeaves; |
| memcpy( pCutNew->pLeaves, pCut->pLeaves, sizeof(int) * pCut->nLeaves ); |
| return hCutNew; |
| } |
| static inline int Mpm_CutCopySet( Mpm_Man_t * p, Mig_Obj_t * pObj, int fCompl ) |
| { |
| Mpm_Cut_t * pCut; |
| int hCut, iList = 0, * pList = &iList; |
| Mpm_ObjForEachCut( p, pObj, hCut, pCut ) |
| { |
| *pList = Mpm_CutDup( p, pCut, fCompl ); |
| pList = &Mpm_CutFetch( p, *pList )->hNext; |
| } |
| *pList = 0; |
| return iList; |
| } |
| void Mpm_CutPrint( Mpm_Cut_t * pCut ) |
| { |
| int i; |
| printf( "%d : { ", pCut->nLeaves ); |
| for ( i = 0; i < (int)pCut->nLeaves; i++ ) |
| printf( "%d ", pCut->pLeaves[i] ); |
| printf( "}\n" ); |
| } |
| static inline void Mpm_CutPrintAll( Mpm_Man_t * p ) |
| { |
| int i; |
| for ( i = 0; i < p->nCutStore; i++ ) |
| { |
| printf( "%2d : ", i ); |
| Mpm_CutPrint( &p->pCutStore[i]->pCut ); |
| } |
| } |
| static inline int Mpm_CutFindLeaf( Mpm_Cut_t * pNew, int iObj ) |
| { |
| int i; |
| for ( i = 0; i < (int)pNew->nLeaves; i++ ) |
| if ( Abc_Lit2Var(pNew->pLeaves[i]) == iObj ) |
| return i; |
| return i; |
| } |
| static inline int Mpm_CutIsContained( Mpm_Man_t * p, Mpm_Cut_t * pBase, Mpm_Cut_t * pCut ) // check if pCut is contained pBase |
| { |
| int i; |
| for ( i = 0; i < (int)pCut->nLeaves; i++ ) |
| if ( Mpm_CutFindLeaf( pBase, Abc_Lit2Var(pCut->pLeaves[i]) ) == (int)pBase->nLeaves ) |
| return 0; |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Cut attibutes.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline int Mpm_CutGetArea( Mpm_Man_t * p, Mpm_Cut_t * pCut ) |
| { |
| if ( p->pPars->fMap4Cnf ) |
| return MPM_UNIT_AREA * p->pDsd6[Abc_Lit2Var(pCut->iFunc)].nClauses; |
| if ( p->pPars->fMap4Aig ) |
| return MPM_UNIT_AREA * p->pDsd6[Abc_Lit2Var(pCut->iFunc)].nAnds; |
| if ( p->pPars->fMap4Gates ) |
| return MPM_UNIT_AREA * 1; |
| return p->pLibLut->pLutAreas[pCut->nLeaves]; |
| } |
| static inline word Mpm_CutGetSign( Mpm_Cut_t * pCut ) |
| { |
| int i, iLeaf; |
| word uSign = 0; |
| Mpm_CutForEachLeafId( pCut, iLeaf, i ) |
| uSign |= ((word)1 << (iLeaf & 0x3F)); |
| return uSign; |
| } |
| static inline int Mpm_CutGetArrTime( Mpm_Man_t * p, Mpm_Cut_t * pCut ) |
| { |
| int * pmTimes = Vec_IntArray( &p->vTimes ); |
| int * pDelays = p->pLibLut->pLutDelays[pCut->nLeaves]; |
| int i, iLeaf, ArrTime = 0; |
| Mpm_CutForEachLeafId( pCut, iLeaf, i ) |
| ArrTime = Abc_MaxInt( ArrTime, pmTimes[iLeaf] + pDelays[i] ); |
| return ArrTime; |
| } |
| static inline Mpm_Uni_t * Mpm_CutSetupInfo( Mpm_Man_t * p, Mpm_Cut_t * pCut, int ArrTime ) |
| { |
| int * pMigRefs = Vec_IntArray( &p->vMigRefs ); |
| int * pMapRefs = Vec_IntArray( &p->vMapRefs ); |
| int * pEstRefs = Vec_IntArray( &p->vEstRefs ); |
| int * pmArea = Vec_IntArray( &p->vAreas ); |
| int * pmEdge = Vec_IntArray( &p->vEdges ); |
| int i, iLeaf; |
| Mpm_Uni_t * pUnit = (Mpm_Uni_t *)Vec_PtrEntryLast(&p->vFreeUnits); |
| assert( &pUnit->pCut == pCut ); |
| pUnit->mTime = ArrTime; |
| pUnit->mArea = Mpm_CutGetArea( p, pCut ); |
| pUnit->mEdge = MPM_UNIT_EDGE * pCut->nLeaves; |
| pUnit->mAveRefs = 0; |
| pUnit->Cost = 0; |
| pUnit->uSign = 0; |
| Mpm_CutForEachLeafId( pCut, iLeaf, i ) |
| { |
| if ( p->fMainRun && pMapRefs[iLeaf] == 0 ) // not used in the mapping |
| { |
| pUnit->mArea += pmArea[iLeaf]; |
| pUnit->mEdge += pmEdge[iLeaf]; |
| } |
| else |
| { |
| assert( pEstRefs[iLeaf] > 0 ); |
| pUnit->mArea += MPM_UNIT_REFS * pmArea[iLeaf] / pEstRefs[iLeaf]; |
| pUnit->mEdge += MPM_UNIT_REFS * pmEdge[iLeaf] / pEstRefs[iLeaf]; |
| pUnit->mAveRefs += p->fMainRun ? pMapRefs[iLeaf] : pMigRefs[iLeaf]; |
| } |
| pUnit->uSign |= ((word)1 << (iLeaf & 0x3F)); |
| } |
| pUnit->mAveRefs = pUnit->mAveRefs * MPM_UNIT_EDGE / Abc_MaxInt(pCut->nLeaves, 1); |
| assert( pUnit->mTime <= 0x3FFFFFFF ); |
| assert( pUnit->mArea <= 0x3FFFFFFF ); |
| assert( pUnit->mEdge <= 0x3FFFFFFF ); |
| return pUnit; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Compares cut against those present in the store.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Mpm_ObjAddCutToStore( Mpm_Man_t * p, Mpm_Cut_t * pCut, int ArrTime ) |
| { |
| int fEnableContainment = 1; |
| Mpm_Uni_t * pUnit, * pUnitNew; |
| int k, iPivot, last; |
| // create new unit |
| #ifdef MIG_RUNTIME |
| abctime clk; |
| clk = Abc_Clock(); |
| #endif |
| pUnitNew = Mpm_CutSetupInfo( p, pCut, ArrTime ); |
| #ifdef MIG_RUNTIME |
| p->timeEval += Abc_Clock() - clk; |
| #endif |
| // special case when the cut store is empty |
| if ( p->nCutStore == 0 ) |
| { |
| p->pCutStore[p->nCutStore++] = pUnitNew; |
| Vec_PtrPop( &p->vFreeUnits ); |
| return 1; |
| } |
| // special case when the cut store is full and last cut is better than new cut |
| if ( p->nCutStore == p->nNumCuts-1 && p->pCutCmp(pUnitNew, p->pCutStore[p->nCutStore-1]) > 0 ) |
| return 0; |
| |
| // find place of the given cut in the store |
| assert( p->nCutStore <= p->nNumCuts ); |
| for ( iPivot = p->nCutStore - 1; iPivot >= 0; iPivot-- ) |
| if ( p->pCutCmp(pUnitNew, p->pCutStore[iPivot]) > 0 ) // iPivot-th cut is better than new cut |
| break; |
| |
| if ( fEnableContainment ) |
| { |
| #ifdef MIG_RUNTIME |
| clk = Abc_Clock(); |
| #endif |
| // filter this cut using other cuts |
| for ( k = 0; k <= iPivot; k++ ) |
| { |
| pUnit = p->pCutStore[k]; |
| if ( pUnitNew->pCut.nLeaves >= pUnit->pCut.nLeaves && |
| (pUnitNew->uSign & pUnit->uSign) == pUnit->uSign && |
| Mpm_CutIsContained(p, &pUnitNew->pCut, &pUnit->pCut) ) |
| { |
| #ifdef MIG_RUNTIME |
| p->timeCompare += Abc_Clock() - clk; |
| #endif |
| return 0; |
| } |
| } |
| } |
| |
| // special case when the best cut is useless while the new cut is not |
| if ( p->pCutStore[0]->pCut.fUseless && !pUnitNew->pCut.fUseless ) |
| iPivot = -1; |
| |
| // add the cut to storage |
| assert( pUnitNew == (Mpm_Uni_t *)Vec_PtrEntryLast(&p->vFreeUnits) ); |
| Vec_PtrPop( &p->vFreeUnits ); |
| |
| // insert this cut at location iPivot |
| iPivot++; |
| for ( k = p->nCutStore++; k > iPivot; k-- ) |
| p->pCutStore[k] = p->pCutStore[k-1]; |
| p->pCutStore[iPivot] = pUnitNew; |
| |
| if ( fEnableContainment ) |
| { |
| // filter other cuts using this cut |
| for ( k = last = iPivot+1; k < p->nCutStore; k++ ) |
| { |
| pUnit = p->pCutStore[k]; |
| if ( pUnitNew->pCut.nLeaves <= pUnit->pCut.nLeaves && |
| (pUnitNew->uSign & pUnit->uSign) == pUnitNew->uSign && |
| Mpm_CutIsContained(p, &pUnit->pCut, &pUnitNew->pCut) ) |
| { |
| Vec_PtrPush( &p->vFreeUnits, pUnit ); |
| continue; |
| } |
| p->pCutStore[last++] = p->pCutStore[k]; |
| } |
| p->nCutStore = last; |
| #ifdef MIG_RUNTIME |
| p->timeCompare += Abc_Clock() - clk; |
| #endif |
| } |
| |
| // remove the last cut if too many |
| if ( p->nCutStore == p->nNumCuts ) |
| Vec_PtrPush( &p->vFreeUnits, p->pCutStore[--p->nCutStore] ); |
| assert( p->nCutStore < p->nNumCuts ); |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Cut enumeration.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline Mpm_Cut_t * Mpm_ManMergeCuts( Mpm_Man_t * p, Mpm_Cut_t * pCut0, Mpm_Cut_t * pCut1, Mpm_Cut_t * pCut2 ) |
| { |
| Mpm_Cut_t * pTemp, * pCut = &((Mpm_Uni_t *)Vec_PtrEntryLast(&p->vFreeUnits))->pCut; |
| int i, c, iPlace; |
| // base cut |
| memcpy( pCut->pLeaves, pCut0->pLeaves, sizeof(int) * pCut0->nLeaves ); |
| pCut->nLeaves = pCut0->nLeaves; |
| // remaining cuts |
| if ( p->pPars->fUseDsd ) |
| { |
| for ( c = 1; c < 3; c++ ) |
| { |
| pTemp = (c == 1) ? pCut1 : pCut2; |
| if ( pTemp == NULL ) |
| break; |
| p->uPermMask[c] = 0x3FFFF; // 18 bits |
| p->uComplMask[c] = 0; |
| for ( i = 0; i < (int)pTemp->nLeaves; i++ ) |
| { |
| iPlace = Mpm_CutFindLeaf( pCut, Abc_Lit2Var(pTemp->pLeaves[i]) ); |
| if ( iPlace == (int)pCut->nLeaves ) |
| { |
| if ( (int)pCut->nLeaves == p->nLutSize ) |
| return NULL; |
| pCut->pLeaves[pCut->nLeaves++] = pTemp->pLeaves[i]; |
| } |
| p->uPermMask[c] ^= (((i & 7) ^ 7) << (3*iPlace)); |
| if ( pTemp->pLeaves[i] != pCut->pLeaves[iPlace] ) |
| p->uComplMask[c] |= (1 << iPlace); |
| } |
| } |
| } |
| else |
| { |
| for ( c = 1; c < 3; c++ ) |
| { |
| pTemp = (c == 1) ? pCut1 : pCut2; |
| if ( pTemp == NULL ) |
| break; |
| for ( i = 0; i < (int)pTemp->nLeaves; i++ ) |
| { |
| iPlace = Mpm_CutFindLeaf( pCut, Abc_Lit2Var(pTemp->pLeaves[i]) ); |
| if ( iPlace == (int)pCut->nLeaves ) |
| { |
| if ( (int)pCut->nLeaves == p->nLutSize ) |
| return NULL; |
| pCut->pLeaves[pCut->nLeaves++] = pTemp->pLeaves[i]; |
| } |
| } |
| } |
| } |
| if ( pCut1 == NULL ) |
| { |
| pCut->hNext = 0; |
| pCut->iFunc = pCut0->iFunc; |
| pCut->fUseless = pCut0->fUseless; |
| pCut->fCompl = pCut0->fCompl; |
| } |
| else |
| { |
| pCut->hNext = 0; |
| pCut->iFunc = 0; pCut->iFunc = ~pCut->iFunc; |
| pCut->fUseless = 0; |
| pCut->fCompl = 0; |
| } |
| p->nCutsMerged++; |
| p->nCutsMergedAll++; |
| if ( p->pPars->fUseTruth ) |
| Vec_IntSelectSort( pCut->pLeaves, pCut->nLeaves ); |
| return pCut; |
| } |
| static inline int Mpm_ManExploreNewCut( Mpm_Man_t * p, Mig_Obj_t * pObj, Mpm_Cut_t * pCut0, Mpm_Cut_t * pCut1, Mpm_Cut_t * pCut2, int Required ) |
| { |
| Mpm_Cut_t * pCut; |
| int ArrTime; |
| #ifdef MIG_RUNTIME |
| abctime clk = clock(); |
| #endif |
| |
| if ( pCut0->nLeaves >= pCut1->nLeaves ) |
| { |
| pCut = Mpm_ManMergeCuts( p, pCut0, pCut1, pCut2 ); |
| #ifdef MIG_RUNTIME |
| p->timeMerge += clock() - clk; |
| #endif |
| if ( pCut == NULL ) |
| return 1; |
| if ( p->pPars->fUseTruth ) |
| Mpm_CutComputeTruth( p, pCut, pCut0, pCut1, pCut2, Mig_ObjFaninC0(pObj), Mig_ObjFaninC1(pObj), Mig_ObjFaninC2(pObj), Mig_ObjNodeType(pObj) ); |
| else if ( p->pPars->fUseDsd ) |
| { |
| if ( !Mpm_CutComputeDsd6( p, pCut, pCut0, pCut1, pCut2, Mig_ObjFaninC0(pObj), Mig_ObjFaninC1(pObj), Mig_ObjFaninC2(pObj), Mig_ObjNodeType(pObj) ) ) |
| return 1; |
| } |
| } |
| else |
| { |
| pCut = Mpm_ManMergeCuts( p, pCut1, pCut0, pCut2 ); |
| #ifdef MIG_RUNTIME |
| p->timeMerge += clock() - clk; |
| #endif |
| if ( pCut == NULL ) |
| return 1; |
| if ( p->pPars->fUseTruth ) |
| Mpm_CutComputeTruth( p, pCut, pCut1, pCut0, pCut2, Mig_ObjFaninC1(pObj), Mig_ObjFaninC0(pObj), 1 ^ Mig_ObjFaninC2(pObj), Mig_ObjNodeType(pObj) ); |
| else if ( p->pPars->fUseDsd ) |
| { |
| if ( !Mpm_CutComputeDsd6( p, pCut, pCut1, pCut0, pCut2, Mig_ObjFaninC1(pObj), Mig_ObjFaninC0(pObj), 1 ^ Mig_ObjFaninC2(pObj), Mig_ObjNodeType(pObj) ) ) |
| return 1; |
| } |
| } |
| |
| #ifdef MIG_RUNTIME |
| clk = clock(); |
| #endif |
| ArrTime = Mpm_CutGetArrTime( p, pCut ); |
| #ifdef MIG_RUNTIME |
| p->timeEval += clock() - clk; |
| #endif |
| if ( p->fMainRun && ArrTime > Required ) |
| return 1; |
| |
| #ifdef MIG_RUNTIME |
| clk = Abc_Clock(); |
| #endif |
| Mpm_ObjAddCutToStore( p, pCut, ArrTime ); |
| #ifdef MIG_RUNTIME |
| p->timeStore += Abc_Clock() - clk; |
| #endif |
| |
| /* |
| // return 0 if const or buffer cut is derived - reset all cuts to contain only one --- does not work |
| // if ( pCut->nLeaves < 2 && p->nCutStore == 1 ) |
| // return 0; |
| if ( pCut->nLeaves < 2 ) |
| { |
| int i; |
| assert( p->nCutStore >= 1 ); |
| for ( i = 1; i < p->nCutStore; i++ ) |
| Vec_PtrPush( &p->vFreeUnits, p->pCutStore[i] ); |
| p->nCutStore = 1; |
| return 0; |
| } |
| */ |
| return 1; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline void Mpm_ObjRecycleCuts( Mpm_Man_t * p, Mig_Obj_t * pObj ) |
| { |
| Mpm_Cut_t * pCut; |
| int hCut, hNext; |
| Mpm_ObjForEachCutSafe( p, pObj, hCut, pCut, hNext ) |
| Mmr_StepRecycle( p->pManCuts, hCut ); |
| Mpm_ObjSetCutList( p, pObj, 0 ); |
| } |
| static inline void Mpm_ObjDerefFaninCuts( Mpm_Man_t * p, Mig_Obj_t * pObj ) |
| { |
| Mig_Obj_t * pFanin; |
| int i; |
| Mig_ObjForEachFanin( pObj, pFanin, i ) |
| if ( Mig_ObjIsNode(pFanin) && Mig_ObjMigRefDec(p, pFanin) == 0 ) |
| Mpm_ObjRecycleCuts( p, pFanin ); |
| pFanin = Mig_ObjSibl(pObj); |
| if ( pFanin && Mig_ObjMigRefDec(p, pFanin) == 0 ) |
| Mpm_ObjRecycleCuts( p, pFanin ); |
| if ( Mig_ObjMigRefNum(p, pObj) == 0 ) |
| Mpm_ObjRecycleCuts( p, pObj ); |
| } |
| static inline void Mpm_ObjCollectFaninsAndSigns( Mpm_Man_t * p, Mig_Obj_t * pObj, int i ) |
| { |
| Mpm_Cut_t * pCut; |
| int hCut, nCuts = 0; |
| Mpm_ObjForEachCut( p, pObj, hCut, pCut ) |
| { |
| p->pCuts[i][nCuts] = pCut; |
| p->pSigns[i][nCuts++] = Mpm_CutGetSign( pCut ); |
| } |
| p->nCuts[i] = nCuts; |
| } |
| static inline void Mpm_ObjPrepareFanins( Mpm_Man_t * p, Mig_Obj_t * pObj ) |
| { |
| Mig_Obj_t * pFanin; |
| int i; |
| Mig_ObjForEachFanin( pObj, pFanin, i ) |
| Mpm_ObjCollectFaninsAndSigns( p, pFanin, i ); |
| } |
| // create storage from cuts at the node |
| void Mpm_ObjAddChoiceCutsToStore( Mpm_Man_t * p, Mig_Obj_t * pRoot, Mig_Obj_t * pObj, int ReqTime ) |
| { |
| Mpm_Cut_t * pCut; |
| int hCut, hNext, ArrTime; |
| int fCompl = Mig_ObjPhase(pRoot) ^ Mig_ObjPhase(pObj); |
| Mpm_ObjForEachCutSafe( p, pObj, hCut, pCut, hNext ) |
| { |
| if ( Abc_Lit2Var(pCut->pLeaves[0]) == Mig_ObjId(pObj) ) |
| continue; |
| ArrTime = Mpm_CutGetArrTime( p, pCut ); |
| if ( ArrTime > ReqTime ) |
| continue; |
| pCut->fCompl ^= fCompl; |
| pCut = Mpm_ManMergeCuts( p, pCut, NULL, NULL ); |
| Mpm_ObjAddCutToStore( p, pCut, ArrTime ); |
| } |
| } |
| // create cuts at the node from storage |
| void Mpm_ObjTranslateCutsFromStore( Mpm_Man_t * p, Mig_Obj_t * pObj ) |
| { |
| Mpm_Cut_t * pCut = NULL; |
| Mpm_Uni_t * pUnit; |
| int i, *pList = Mpm_ObjCutListP( p, pObj ); |
| assert( p->nCutStore > 0 && p->nCutStore <= p->nNumCuts ); |
| assert( *pList == 0 ); |
| // translate cuts |
| for ( i = 0; i < p->nCutStore; i++ ) |
| { |
| pUnit = p->pCutStore[i]; |
| *pList = Mpm_CutCreate( p, &pUnit->pCut, &pCut ); |
| pList = &pCut->hNext; |
| Vec_PtrPush( &p->vFreeUnits, pUnit ); |
| } |
| assert( Vec_PtrSize(&p->vFreeUnits) == p->nNumCuts + 1 ); |
| if ( p->nCutStore == 1 && pCut->nLeaves < 2 ) |
| *pList = 0; |
| else |
| *pList = Mpm_CutCreateUnit( p, Mig_ObjId(pObj) ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Mpm_ManDeriveCuts( Mpm_Man_t * p, Mig_Obj_t * pObj ) |
| { |
| Mpm_Cut_t * pCut0, * pCut1, * pCut2; |
| int Required = Mpm_ObjRequired( p, pObj ); |
| int hCutBest = Mpm_ObjCutBest( p, pObj ); |
| int c0, c1, c2; |
| #ifdef MIG_RUNTIME |
| abctime clk; |
| #endif |
| |
| assert( Vec_PtrSize( &p->vFreeUnits ) == p->nNumCuts + 1 ); |
| assert( Mpm_ObjCutList(p, pObj) == 0 ); |
| p->nCutStore = 0; |
| if ( hCutBest > 0 ) // cut list is assigned |
| { |
| Mpm_Cut_t * pCut = Mpm_ObjCutBestP( p, pObj ); |
| int Times = Mpm_CutGetArrTime( p, pCut ); |
| assert( pCut->hNext == 0 ); |
| if ( Times > Required ) |
| printf( "Arrival time (%d) exceeds required time (%d) at object %d.\n", Times, Required, Mig_ObjId(pObj) ); |
| if ( p->fMainRun ) |
| Mpm_ObjAddCutToStore( p, Mpm_ManMergeCuts(p, pCut, NULL, NULL), Times ); |
| else |
| Mpm_ObjSetTime( p, pObj, Times ); |
| } |
| // start storage with choice cuts |
| if ( Mig_ManChoiceNum(p->pMig) && Mig_ObjSiblId(pObj) ) |
| Mpm_ObjAddChoiceCutsToStore( p, pObj, Mig_ObjSibl(pObj), Required ); |
| |
| #ifdef MIG_RUNTIME |
| clk = Abc_Clock(); |
| #endif |
| Mpm_ObjPrepareFanins( p, pObj ); |
| if ( Mig_ObjIsNode2(pObj) ) |
| { |
| // go through cut pairs |
| for ( c0 = 0; c0 < p->nCuts[0] && (pCut0 = p->pCuts[0][c0]); c0++ ) |
| for ( c1 = 0; c1 < p->nCuts[1] && (pCut1 = p->pCuts[1][c1]); c1++ ) |
| if ( Abc_TtCountOnes(p->pSigns[0][c0] | p->pSigns[1][c1]) <= p->nLutSize ) |
| if ( !Mpm_ManExploreNewCut( p, pObj, pCut0, pCut1, NULL, Required ) ) |
| goto finish; |
| } |
| else if ( Mig_ObjIsNode3(pObj) ) |
| { |
| // go through cut triples |
| for ( c0 = 0; c0 < p->nCuts[0] && (pCut0 = p->pCuts[0][c0]); c0++ ) |
| for ( c1 = 0; c1 < p->nCuts[1] && (pCut1 = p->pCuts[1][c1]); c1++ ) |
| for ( c2 = 0; c2 < p->nCuts[2] && (pCut2 = p->pCuts[2][c2]); c2++ ) |
| if ( Abc_TtCountOnes(p->pSigns[0][c0] | p->pSigns[1][c1] | p->pSigns[2][c2]) <= p->nLutSize ) |
| if ( !Mpm_ManExploreNewCut( p, pObj, pCut0, pCut1, pCut2, Required ) ) |
| goto finish; |
| } |
| else assert( 0 ); |
| #ifdef MIG_RUNTIME |
| p->timeDerive += Abc_Clock() - clk; |
| #endif |
| |
| finish: |
| // save best cut |
| assert( p->nCutStore > 0 ); |
| if ( p->pCutStore[0]->mTime <= Required ) |
| { |
| Mpm_Cut_t * pCut; |
| if ( hCutBest ) |
| Mmr_StepRecycle( p->pManCuts, hCutBest ); |
| hCutBest = Mpm_CutCreate( p, &p->pCutStore[0]->pCut, &pCut ); |
| Mpm_ObjSetCutBest( p, pObj, hCutBest ); |
| Mpm_ObjSetTime( p, pObj, p->pCutStore[0]->mTime ); |
| Mpm_ObjSetArea( p, pObj, p->pCutStore[0]->mArea ); |
| Mpm_ObjSetEdge( p, pObj, p->pCutStore[0]->mEdge ); |
| } |
| else assert( !p->fMainRun ); |
| assert( hCutBest > 0 ); |
| // transform internal storage into regular cuts |
| Mpm_ObjTranslateCutsFromStore( p, pObj ); |
| // dereference fanin cuts and reference node |
| Mpm_ObjDerefFaninCuts( p, pObj ); |
| return 1; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Required times.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline int Mpm_ManFindArrivalMax( Mpm_Man_t * p ) |
| { |
| int * pmTimes = Vec_IntArray( &p->vTimes ); |
| Mig_Obj_t * pObj; |
| int i, ArrMax = 0; |
| Mig_ManForEachCo( p->pMig, pObj, i ) |
| ArrMax = Abc_MaxInt( ArrMax, pmTimes[ Mig_ObjFaninId0(pObj) ] ); |
| return ArrMax; |
| } |
| static inline void Mpm_ManFinalizeRound( Mpm_Man_t * p ) |
| { |
| int * pMapRefs = Vec_IntArray( &p->vMapRefs ); |
| int * pRequired = Vec_IntArray( &p->vRequireds ); |
| Mig_Obj_t * pObj; |
| Mpm_Cut_t * pCut; |
| int * pDelays; |
| int i, iLeaf; |
| p->GloArea = 0; |
| p->GloEdge = 0; |
| p->GloRequired = Mpm_ManFindArrivalMax(p); |
| if ( p->pPars->DelayTarget != -1 ) |
| p->GloRequired = Abc_MaxInt( p->GloRequired, p->pPars->DelayTarget ); |
| Mpm_ManCleanMapRefs( p ); |
| Mpm_ManCleanRequired( p ); |
| Mig_ManForEachObjReverse( p->pMig, pObj ) |
| { |
| if ( Mig_ObjIsCo(pObj) ) |
| { |
| pRequired[Mig_ObjFaninId0(pObj)] = p->GloRequired; |
| pMapRefs [Mig_ObjFaninId0(pObj)]++; |
| } |
| else if ( Mig_ObjIsNode(pObj) ) |
| { |
| int Required = pRequired[Mig_ObjId(pObj)]; |
| assert( Required > 0 ); |
| if ( pMapRefs[Mig_ObjId(pObj)] > 0 ) |
| { |
| pCut = Mpm_ObjCutBestP( p, pObj ); |
| pDelays = p->pLibLut->pLutDelays[pCut->nLeaves]; |
| Mpm_CutForEachLeafId( pCut, iLeaf, i ) |
| { |
| pRequired[iLeaf] = Abc_MinInt( pRequired[iLeaf], Required - pDelays[i] ); |
| pMapRefs [iLeaf]++; |
| } |
| p->GloArea += Mpm_CutGetArea( p, pCut ); |
| p->GloEdge += pCut->nLeaves; |
| } |
| } |
| else if ( Mig_ObjIsBuf(pObj) ) |
| { |
| } |
| } |
| p->GloArea /= MPM_UNIT_AREA; |
| } |
| static inline void Mpm_ManComputeEstRefs( Mpm_Man_t * p ) |
| { |
| int * pMapRefs = Vec_IntArray( &p->vMapRefs ); |
| int * pEstRefs = Vec_IntArray( &p->vEstRefs ); |
| int i; |
| assert( p->fMainRun ); |
| // pObj->EstRefs = (float)((2.0 * pObj->EstRefs + pObj->nRefs) / 3.0); |
| for ( i = 0; i < Mig_ManObjNum(p->pMig); i++ ) |
| pEstRefs[i] = (1 * pEstRefs[i] + MPM_UNIT_REFS * pMapRefs[i]) / 2; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Cut comparison.] |
| |
| Description [Returns positive number if new one is better than old one.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Mpm_CutCompareDelay( Mpm_Uni_t * pOld, Mpm_Uni_t * pNew ) |
| { |
| if ( pOld->mTime != pNew->mTime ) return pOld->mTime - pNew->mTime; |
| if ( pOld->pCut.nLeaves != pNew->pCut.nLeaves ) return pOld->pCut.nLeaves - pNew->pCut.nLeaves; |
| if ( pOld->mArea != pNew->mArea ) return pOld->mArea - pNew->mArea; |
| if ( pOld->mEdge != pNew->mEdge ) return pOld->mEdge - pNew->mEdge; |
| return 0; |
| } |
| int Mpm_CutCompareDelay2( Mpm_Uni_t * pOld, Mpm_Uni_t * pNew ) |
| { |
| if ( pOld->mTime != pNew->mTime ) return pOld->mTime - pNew->mTime; |
| if ( pOld->mArea != pNew->mArea ) return pOld->mArea - pNew->mArea; |
| if ( pOld->mEdge != pNew->mEdge ) return pOld->mEdge - pNew->mEdge; |
| if ( pOld->pCut.nLeaves != pNew->pCut.nLeaves ) return pOld->pCut.nLeaves - pNew->pCut.nLeaves; |
| return 0; |
| } |
| int Mpm_CutCompareArea( Mpm_Uni_t * pOld, Mpm_Uni_t * pNew ) |
| { |
| if ( pOld->mArea != pNew->mArea ) return pOld->mArea - pNew->mArea; |
| if ( pOld->pCut.nLeaves != pNew->pCut.nLeaves ) return pOld->pCut.nLeaves - pNew->pCut.nLeaves; |
| if ( pOld->mEdge != pNew->mEdge ) return pOld->mEdge - pNew->mEdge; |
| if ( pOld->mAveRefs != pNew->mAveRefs ) return pOld->mAveRefs - pNew->mAveRefs; |
| if ( pOld->mTime != pNew->mTime ) return pOld->mTime - pNew->mTime; |
| return 0; |
| } |
| int Mpm_CutCompareArea2( Mpm_Uni_t * pOld, Mpm_Uni_t * pNew ) |
| { |
| if ( pOld->mArea != pNew->mArea ) return pOld->mArea - pNew->mArea; |
| if ( pOld->mEdge != pNew->mEdge ) return pOld->mEdge - pNew->mEdge; |
| if ( pOld->mAveRefs != pNew->mAveRefs ) return pOld->mAveRefs - pNew->mAveRefs; |
| if ( pOld->pCut.nLeaves != pNew->pCut.nLeaves ) return pOld->pCut.nLeaves - pNew->pCut.nLeaves; |
| if ( pOld->mTime != pNew->mTime ) return pOld->mTime - pNew->mTime; |
| return 0; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Technology mapping experiment.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Mpm_ManPrepare( Mpm_Man_t * p ) |
| { |
| Mig_Obj_t * pObj; |
| int i, hCut; |
| Mig_ManForEachCi( p->pMig, pObj, i ) |
| { |
| hCut = Mpm_CutCreateUnit( p, Mig_ObjId(pObj) ); |
| Mpm_ObjSetCutBest( p, pObj, hCut ); |
| Mpm_ObjSetCutList( p, pObj, hCut ); |
| } |
| Mig_ManForEachCand( p->pMig, pObj ) |
| Mpm_ObjSetEstRef( p, pObj, MPM_UNIT_REFS * Mig_ObjRefNum(pObj) ); |
| } |
| void Mpm_ManPerformRound( Mpm_Man_t * p ) |
| { |
| Mig_Obj_t * pObj; |
| abctime clk = Abc_Clock(); |
| int i; |
| // copy references |
| assert( Vec_IntSize(&p->vMigRefs) == Vec_IntSize(&p->pMig->vRefs) ); |
| memcpy( Vec_IntArray(&p->vMigRefs), Vec_IntArray(&p->pMig->vRefs), sizeof(int) * Mig_ManObjNum(p->pMig) ); |
| Mig_ManForEachCo( p->pMig, pObj, i ) |
| Mig_ObjMigRefDec( p, Mig_ObjFanin0(pObj) ); |
| // derive cuts |
| p->nCutsMerged = 0; |
| Mig_ManForEachNode( p->pMig, pObj ) |
| Mpm_ManDeriveCuts( p, pObj ); |
| assert( Mig_ManCandNum(p->pMig) == p->pManCuts->nEntries ); |
| Mpm_ManFinalizeRound( p ); |
| // report results |
| if ( p->pPars->fVerbose ) |
| { |
| printf( "Del =%5d. Ar =%8d. Edge =%8d. Cut =%10d. Max =%8d. Tru =%8d. Small =%6d. ", |
| p->GloRequired, (int)p->GloArea, (int)p->GloEdge, |
| p->nCutsMerged, p->pManCuts->nEntriesMax, |
| p->vTtMem ? p->vTtMem->nEntries : 0, p->nSmallSupp ); |
| Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); |
| } |
| } |
| void Mpm_ManPerform( Mpm_Man_t * p ) |
| { |
| if ( p->pPars->fMap4Cnf ) |
| { |
| p->pCutCmp = Mpm_CutCompareArea; |
| Mpm_ManPerformRound( p ); |
| } |
| else |
| { |
| p->pCutCmp = Mpm_CutCompareDelay; |
| Mpm_ManPerformRound( p ); |
| if ( p->pPars->fOneRound ) |
| return; |
| |
| p->pCutCmp = Mpm_CutCompareDelay2; |
| Mpm_ManPerformRound( p ); |
| |
| p->pCutCmp = Mpm_CutCompareArea; |
| Mpm_ManPerformRound( p ); |
| |
| p->fMainRun = 1; |
| |
| p->pCutCmp = Mpm_CutCompareArea; |
| Mpm_ManComputeEstRefs( p ); |
| Mpm_ManPerformRound( p ); |
| |
| p->pCutCmp = Mpm_CutCompareArea2; |
| Mpm_ManComputeEstRefs( p ); |
| Mpm_ManPerformRound( p ); |
| } |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |