| /**CFile**************************************************************** |
| |
| FileName [lpkAbcDec.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Fast Boolean matching for LUT structures.] |
| |
| Synopsis [The new core procedure.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - April 28, 2007.] |
| |
| Revision [$Id: lpkAbcDec.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "lpkInt.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Implements the function.] |
| |
| Description [Returns the node implementing this function.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Obj_t * Lpk_ImplementFun( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Lpk_Fun_t * p ) |
| { |
| extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); |
| unsigned * pTruth; |
| Abc_Obj_t * pObjNew; |
| int i; |
| if ( p->fMark ) |
| pMan->nMuxes++; |
| else |
| pMan->nDsds++; |
| // create the new node |
| pObjNew = Abc_NtkCreateNode( pNtk ); |
| for ( i = 0; i < (int)p->nVars; i++ ) |
| Abc_ObjAddFanin( pObjNew, Abc_ObjRegular((Abc_Obj_t *)Vec_PtrEntry(vLeaves, p->pFanins[i])) ); |
| Abc_ObjSetLevel( pObjNew, Abc_ObjLevelNew(pObjNew) ); |
| // assign the node's function |
| pTruth = Lpk_FunTruth(p, 0); |
| if ( p->nVars == 0 ) |
| { |
| pObjNew->pData = Hop_NotCond( Hop_ManConst1((Hop_Man_t *)pNtk->pManFunc), !(pTruth[0] & 1) ); |
| return pObjNew; |
| } |
| if ( p->nVars == 1 ) |
| { |
| pObjNew->pData = Hop_NotCond( Hop_ManPi((Hop_Man_t *)pNtk->pManFunc, 0), (pTruth[0] & 1) ); |
| return pObjNew; |
| } |
| // create the logic function |
| pObjNew->pData = Kit_TruthToHop( (Hop_Man_t *)pNtk->pManFunc, pTruth, p->nVars, NULL ); |
| return pObjNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Implements the function.] |
| |
| Description [Returns the node implementing this function.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Obj_t * Lpk_Implement_rec( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Lpk_Fun_t * pFun ) |
| { |
| Abc_Obj_t * pFanin, * pRes; |
| int i; |
| // prepare the leaves of the function |
| for ( i = 0; i < (int)pFun->nVars; i++ ) |
| { |
| pFanin = (Abc_Obj_t *)Vec_PtrEntry( vLeaves, pFun->pFanins[i] ); |
| if ( !Abc_ObjIsComplement(pFanin) ) |
| Lpk_Implement_rec( pMan, pNtk, vLeaves, (Lpk_Fun_t *)pFanin ); |
| pFanin = (Abc_Obj_t *)Vec_PtrEntry( vLeaves, pFun->pFanins[i] ); |
| assert( Abc_ObjIsComplement(pFanin) ); |
| } |
| // construct the function |
| pRes = Lpk_ImplementFun( pMan, pNtk, vLeaves, pFun ); |
| // replace the function |
| Vec_PtrWriteEntry( vLeaves, pFun->Id, Abc_ObjNot(pRes) ); |
| Lpk_FunFree( pFun ); |
| return pRes; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Implements the function.] |
| |
| Description [Returns the node implementing this function.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Obj_t * Lpk_Implement( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, int nLeavesOld ) |
| { |
| Abc_Obj_t * pFanin, * pRes; |
| int i; |
| assert( nLeavesOld < Vec_PtrSize(vLeaves) ); |
| // mark implemented nodes |
| Vec_PtrForEachEntryStop( Abc_Obj_t *, vLeaves, pFanin, i, nLeavesOld ) |
| Vec_PtrWriteEntry( vLeaves, i, Abc_ObjNot(pFanin) ); |
| // recursively construct starting from the first entry |
| pRes = Lpk_Implement_rec( pMan, pNtk, vLeaves, (Lpk_Fun_t *)Vec_PtrEntry( vLeaves, nLeavesOld ) ); |
| Vec_PtrShrink( vLeaves, nLeavesOld ); |
| return pRes; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Decomposes the function using recursive MUX decomposition.] |
| |
| Description [Returns the ID of the top-most decomposition node |
| implementing this function, or 0 if there is no decomposition satisfying |
| the constraints on area and delay.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Lpk_Decompose_rec( Lpk_Man_t * pMan, Lpk_Fun_t * p ) |
| { |
| Lpk_Res_t * pResMux, * pResDsd; |
| Lpk_Fun_t * p2; |
| abctime clk; |
| |
| // is only called for non-trivial blocks |
| assert( p->nLutK >= 3 && p->nLutK <= 6 ); |
| assert( p->nVars > p->nLutK ); |
| // skip if area bound is exceeded |
| if ( Lpk_LutNumLuts(p->nVars, p->nLutK) > (int)p->nAreaLim ) |
| return 0; |
| // skip if delay bound is exceeded |
| if ( Lpk_SuppDelay(p->uSupp, p->pDelays) > (int)p->nDelayLim ) |
| return 0; |
| |
| // compute supports if needed |
| if ( !p->fSupports ) |
| Lpk_FunComputeCofSupps( p ); |
| |
| // check DSD decomposition |
| clk = Abc_Clock(); |
| pResDsd = Lpk_DsdAnalize( pMan, p, pMan->pPars->nVarsShared ); |
| pMan->timeEvalDsdAn += Abc_Clock() - clk; |
| if ( pResDsd && (pResDsd->nBSVars == (int)p->nLutK || pResDsd->nBSVars == (int)p->nLutK - 1) && |
| pResDsd->AreaEst <= (int)p->nAreaLim && pResDsd->DelayEst <= (int)p->nDelayLim ) |
| { |
| clk = Abc_Clock(); |
| p2 = Lpk_DsdSplit( pMan, p, pResDsd->pCofVars, pResDsd->nCofVars, pResDsd->BSVars ); |
| pMan->timeEvalDsdSp += Abc_Clock() - clk; |
| assert( p2->nVars <= (int)p->nLutK ); |
| if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) ) |
| return 0; |
| return 1; |
| } |
| |
| // check MUX decomposition |
| clk = Abc_Clock(); |
| pResMux = Lpk_MuxAnalize( pMan, p ); |
| pMan->timeEvalMuxAn += Abc_Clock() - clk; |
| // pResMux = NULL; |
| assert( !pResMux || (pResMux->DelayEst <= (int)p->nDelayLim && pResMux->AreaEst <= (int)p->nAreaLim) ); |
| // accept MUX decomposition if it is "good" |
| if ( pResMux && pResMux->nSuppSizeS <= (int)p->nLutK && pResMux->nSuppSizeL <= (int)p->nLutK ) |
| pResDsd = NULL; |
| else if ( pResMux && pResDsd ) |
| { |
| // compare two decompositions |
| if ( pResMux->AreaEst < pResDsd->AreaEst || |
| (pResMux->AreaEst == pResDsd->AreaEst && pResMux->nSuppSizeL < pResDsd->nSuppSizeL) || |
| (pResMux->AreaEst == pResDsd->AreaEst && pResMux->nSuppSizeL == pResDsd->nSuppSizeL && pResMux->DelayEst < pResDsd->DelayEst) ) |
| pResDsd = NULL; |
| else |
| pResMux = NULL; |
| } |
| assert( pResMux == NULL || pResDsd == NULL ); |
| if ( pResMux ) |
| { |
| clk = Abc_Clock(); |
| p2 = Lpk_MuxSplit( pMan, p, pResMux->Variable, pResMux->Polarity ); |
| pMan->timeEvalMuxSp += Abc_Clock() - clk; |
| if ( p2->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p2 ) ) |
| return 0; |
| if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) ) |
| return 0; |
| return 1; |
| } |
| if ( pResDsd ) |
| { |
| clk = Abc_Clock(); |
| p2 = Lpk_DsdSplit( pMan, p, pResDsd->pCofVars, pResDsd->nCofVars, pResDsd->BSVars ); |
| pMan->timeEvalDsdSp += Abc_Clock() - clk; |
| assert( p2->nVars <= (int)p->nLutK ); |
| if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) ) |
| return 0; |
| return 1; |
| } |
| return 0; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Removes decomposed nodes from the array of fanins.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Lpk_DecomposeClean( Vec_Ptr_t * vLeaves, int nLeavesOld ) |
| { |
| Lpk_Fun_t * pFunc; |
| int i; |
| Vec_PtrForEachEntryStart( Lpk_Fun_t *, vLeaves, pFunc, i, nLeavesOld ) |
| Lpk_FunFree( pFunc ); |
| Vec_PtrShrink( vLeaves, nLeavesOld ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Decomposes the function using recursive MUX decomposition.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Obj_t * Lpk_Decompose( Lpk_Man_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, unsigned * puSupps, int nLutK, int AreaLim, int DelayLim ) |
| { |
| Lpk_Fun_t * pFun; |
| Abc_Obj_t * pObjNew = NULL; |
| int nLeaves = Vec_PtrSize( vLeaves ); |
| pFun = Lpk_FunCreate( pNtk, vLeaves, pTruth, nLutK, AreaLim, DelayLim ); |
| if ( puSupps[0] || puSupps[1] ) |
| { |
| /* |
| int i; |
| Lpk_FunComputeCofSupps( pFun ); |
| for ( i = 0; i < nLeaves; i++ ) |
| { |
| assert( pFun->puSupps[2*i+0] == puSupps[2*i+0] ); |
| assert( pFun->puSupps[2*i+1] == puSupps[2*i+1] ); |
| } |
| */ |
| memcpy( pFun->puSupps, puSupps, sizeof(unsigned) * 2 * nLeaves ); |
| pFun->fSupports = 1; |
| } |
| Lpk_FunSuppMinimize( pFun ); |
| if ( pFun->nVars <= pFun->nLutK ) |
| pObjNew = Lpk_ImplementFun( p, pNtk, vLeaves, pFun ); |
| else if ( Lpk_Decompose_rec(p, pFun) ) |
| pObjNew = Lpk_Implement( p, pNtk, vLeaves, nLeaves ); |
| Lpk_DecomposeClean( vLeaves, nLeaves ); |
| return pObjNew; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |