| /**CFile**************************************************************** |
| |
| FileName [lpkSets.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: lpkSets.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "lpkInt.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| typedef struct Lpk_Set_t_ Lpk_Set_t; |
| struct Lpk_Set_t_ |
| { |
| char iVar; // the cofactoring variable |
| char Over; // the overlap in supports |
| char SRed; // the support reduction |
| char Size; // the size of the boundset |
| unsigned uSubset0; // the first subset (with removed) |
| unsigned uSubset1; // the second subset (with removed) |
| }; |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Recursively computes decomposable subsets.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| unsigned Lpk_ComputeSets_rec( Kit_DsdNtk_t * p, int iLit, Vec_Int_t * vSets ) |
| { |
| unsigned i, iLitFanin, uSupport, uSuppCur; |
| Kit_DsdObj_t * pObj; |
| // consider the case of simple gate |
| pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) ); |
| if ( pObj == NULL ) |
| return (1 << Abc_Lit2Var(iLit)); |
| if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR ) |
| { |
| unsigned uSupps[16], Limit, s; |
| uSupport = 0; |
| Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) |
| { |
| uSupps[i] = Lpk_ComputeSets_rec( p, iLitFanin, vSets ); |
| uSupport |= uSupps[i]; |
| } |
| // create all subsets, except empty and full |
| Limit = (1 << pObj->nFans) - 1; |
| for ( s = 1; s < Limit; s++ ) |
| { |
| uSuppCur = 0; |
| for ( i = 0; i < pObj->nFans; i++ ) |
| if ( s & (1 << i) ) |
| uSuppCur |= uSupps[i]; |
| Vec_IntPush( vSets, uSuppCur ); |
| } |
| return uSupport; |
| } |
| assert( pObj->Type == KIT_DSD_PRIME ); |
| // get the cumulative support of all fanins |
| uSupport = 0; |
| Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) |
| { |
| uSuppCur = Lpk_ComputeSets_rec( p, iLitFanin, vSets ); |
| uSupport |= uSuppCur; |
| Vec_IntPush( vSets, uSuppCur ); |
| } |
| return uSupport; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes the set of subsets of decomposable variables.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| unsigned Lpk_ComputeSets( Kit_DsdNtk_t * p, Vec_Int_t * vSets ) |
| { |
| unsigned uSupport, Entry; |
| int Number, i; |
| assert( p->nVars <= 16 ); |
| Vec_IntClear( vSets ); |
| Vec_IntPush( vSets, 0 ); |
| if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 ) |
| return 0; |
| if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR ) |
| { |
| uSupport = ( 1 << Abc_Lit2Var(Kit_DsdNtkRoot(p)->pFans[0]) ); |
| Vec_IntPush( vSets, uSupport ); |
| return uSupport; |
| } |
| uSupport = Lpk_ComputeSets_rec( p, p->Root, vSets ); |
| assert( (uSupport & 0xFFFF0000) == 0 ); |
| Vec_IntPush( vSets, uSupport ); |
| // set the remaining variables |
| Vec_IntForEachEntry( vSets, Number, i ) |
| { |
| Entry = Number; |
| Vec_IntWriteEntry( vSets, i, Entry | ((uSupport & ~Entry) << 16) ); |
| } |
| return uSupport; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prints the sets of subsets.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static void Lpk_PrintSetOne( int uSupport ) |
| { |
| unsigned k; |
| for ( k = 0; k < 16; k++ ) |
| if ( uSupport & (1<<k) ) |
| printf( "%c", 'a'+k ); |
| printf( " " ); |
| } |
| /**Function************************************************************* |
| |
| Synopsis [Prints the sets of subsets.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static void Lpk_PrintSets( Vec_Int_t * vSets ) |
| { |
| unsigned uSupport; |
| int Number, i; |
| printf( "Subsets(%d): ", Vec_IntSize(vSets) ); |
| Vec_IntForEachEntry( vSets, Number, i ) |
| { |
| uSupport = Number; |
| Lpk_PrintSetOne( uSupport ); |
| } |
| printf( "\n" ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes maximal support reducing bound-sets.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Lpk_ComposeSets( Vec_Int_t * vSets0, Vec_Int_t * vSets1, int nVars, int iCofVar, |
| Lpk_Set_t * pStore, int * pSize, int nSizeLimit ) |
| { |
| static int nTravId = 0; // the number of the times this is visited |
| static int TravId[1<<16] = {0}; // last visited |
| static char SRed[1<<16]; // best support reduction |
| static char Over[1<<16]; // best overlaps |
| static unsigned Parents[1<<16]; // best set of parents |
| static unsigned short Used[1<<16]; // storage for used subsets |
| int nSuppSize, nSuppOver, nSuppRed, nUsed, nMinOver, i, k, s; |
| unsigned Entry, Entry0, Entry1; |
| unsigned uSupp, uSupp0, uSupp1, uSuppTotal; |
| Lpk_Set_t * pEntry; |
| |
| if ( nTravId == (1 << 30) ) |
| memset( TravId, 0, sizeof(int) * (1 << 16) ); |
| |
| // collect support reducing subsets |
| nUsed = 0; |
| nTravId++; |
| uSuppTotal = Kit_BitMask(nVars) & ~(1<<iCofVar); |
| Vec_IntForEachEntry( vSets0, Entry0, i ) |
| Vec_IntForEachEntry( vSets1, Entry1, k ) |
| { |
| uSupp0 = (Entry0 & 0xFFFF); |
| uSupp1 = (Entry1 & 0xFFFF); |
| // skip trivial |
| if ( uSupp0 == 0 || uSupp1 == 0 || (uSupp0 | uSupp1) == uSuppTotal ) |
| continue; |
| if ( Kit_WordHasOneBit(uSupp0) && Kit_WordHasOneBit(uSupp1) ) |
| continue; |
| // get the entry |
| Entry = Entry0 | Entry1; |
| uSupp = Entry & 0xFFFF; |
| // set the bound set size |
| nSuppSize = Kit_WordCountOnes( uSupp ); |
| // get the number of overlapping vars |
| nSuppOver = Kit_WordCountOnes( Entry & (Entry >> 16) ); |
| // get the support reduction |
| nSuppRed = nSuppSize - 1 - nSuppOver; |
| // only consider support-reducing subsets |
| if ( nSuppRed <= 0 ) |
| continue; |
| // check if this support is already used |
| if ( TravId[uSupp] < nTravId ) |
| { |
| Used[nUsed++] = uSupp; |
| |
| TravId[uSupp] = nTravId; |
| SRed[uSupp] = nSuppRed; |
| Over[uSupp] = nSuppOver; |
| Parents[uSupp] = (k << 16) | i; |
| } |
| else if ( TravId[uSupp] == nTravId && SRed[uSupp] < nSuppRed ) |
| { |
| TravId[uSupp] = nTravId; |
| SRed[uSupp] = nSuppRed; |
| Over[uSupp] = nSuppOver; |
| Parents[uSupp] = (k << 16) | i; |
| } |
| } |
| |
| // find the minimum overlap |
| nMinOver = 1000; |
| for ( s = 0; s < nUsed; s++ ) |
| if ( nMinOver > Over[Used[s]] ) |
| nMinOver = Over[Used[s]]; |
| |
| |
| // collect the accumulated ones |
| for ( s = 0; s < nUsed; s++ ) |
| if ( Over[Used[s]] == nMinOver ) |
| { |
| // save the entry |
| if ( *pSize == nSizeLimit ) |
| return; |
| pEntry = pStore + (*pSize)++; |
| |
| i = Parents[Used[s]] & 0xFFFF; |
| k = Parents[Used[s]] >> 16; |
| |
| pEntry->uSubset0 = Vec_IntEntry(vSets0, i); |
| pEntry->uSubset1 = Vec_IntEntry(vSets1, k); |
| Entry = pEntry->uSubset0 | pEntry->uSubset1; |
| |
| // record the cofactoring variable |
| pEntry->iVar = iCofVar; |
| // set the bound set size |
| pEntry->Size = Kit_WordCountOnes( Entry & 0xFFFF ); |
| // get the number of overlapping vars |
| pEntry->Over = Kit_WordCountOnes( Entry & (Entry >> 16) ); |
| // get the support reduction |
| pEntry->SRed = pEntry->Size - 1 - pEntry->Over; |
| assert( pEntry->SRed > 0 ); |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prints one set.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Lpk_MapSuppPrintSet( Lpk_Set_t * pSet, int i ) |
| { |
| unsigned Entry; |
| Entry = pSet->uSubset0 | pSet->uSubset1; |
| printf( "%2d : ", i ); |
| printf( "Var = %c ", 'a' + pSet->iVar ); |
| printf( "Size = %2d ", pSet->Size ); |
| printf( "Over = %2d ", pSet->Over ); |
| printf( "SRed = %2d ", pSet->SRed ); |
| Lpk_PrintSetOne( Entry ); |
| printf( " " ); |
| Lpk_PrintSetOne( Entry >> 16 ); |
| printf( "\n" ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Evaluates the cofactors.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| unsigned Lpk_MapSuppRedDecSelect( Lpk_Man_t * p, unsigned * pTruth, int nVars, int * piVar, int * piVarReused ) |
| { |
| static int nStoreSize = 256; |
| static Lpk_Set_t pStore[256], * pSet, * pSetBest; |
| Kit_DsdNtk_t * ppNtks[2], * pTemp; |
| Vec_Int_t * vSets0 = p->vSets[0]; |
| Vec_Int_t * vSets1 = p->vSets[1]; |
| unsigned * pCof0 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 0 ); |
| unsigned * pCof1 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 1 ); |
| int nSets, i, SizeMax;//, SRedMax; |
| unsigned Entry; |
| int fVerbose = p->pPars->fVeryVerbose; |
| // int fVerbose = 0; |
| |
| // collect decomposable subsets for each pair of cofactors |
| if ( fVerbose ) |
| { |
| printf( "\nExploring support-reducing bound-sets of function:\n" ); |
| Kit_DsdPrintFromTruth( pTruth, nVars ); |
| } |
| nSets = 0; |
| for ( i = 0; i < nVars; i++ ) |
| { |
| if ( fVerbose ) |
| printf( "Evaluating variable %c:\n", 'a'+i ); |
| // evaluate the cofactor pair |
| Kit_TruthCofactor0New( pCof0, pTruth, nVars, i ); |
| Kit_TruthCofactor1New( pCof1, pTruth, nVars, i ); |
| // decompose and expand |
| ppNtks[0] = Kit_DsdDecompose( pCof0, nVars ); |
| ppNtks[1] = Kit_DsdDecompose( pCof1, nVars ); |
| ppNtks[0] = Kit_DsdExpand( pTemp = ppNtks[0] ); Kit_DsdNtkFree( pTemp ); |
| ppNtks[1] = Kit_DsdExpand( pTemp = ppNtks[1] ); Kit_DsdNtkFree( pTemp ); |
| if ( fVerbose ) |
| Kit_DsdPrint( stdout, ppNtks[0] ); |
| if ( fVerbose ) |
| Kit_DsdPrint( stdout, ppNtks[1] ); |
| // compute subsets |
| Lpk_ComputeSets( ppNtks[0], vSets0 ); |
| Lpk_ComputeSets( ppNtks[1], vSets1 ); |
| // print subsets |
| if ( fVerbose ) |
| Lpk_PrintSets( vSets0 ); |
| if ( fVerbose ) |
| Lpk_PrintSets( vSets1 ); |
| // free the networks |
| Kit_DsdNtkFree( ppNtks[0] ); |
| Kit_DsdNtkFree( ppNtks[1] ); |
| // evaluate the pair |
| Lpk_ComposeSets( vSets0, vSets1, nVars, i, pStore, &nSets, nStoreSize ); |
| } |
| |
| // print the results |
| if ( fVerbose ) |
| printf( "\n" ); |
| if ( fVerbose ) |
| for ( i = 0; i < nSets; i++ ) |
| Lpk_MapSuppPrintSet( pStore + i, i ); |
| |
| // choose the best subset |
| SizeMax = 0; |
| pSetBest = NULL; |
| for ( i = 0; i < nSets; i++ ) |
| { |
| pSet = pStore + i; |
| if ( pSet->Size > p->pPars->nLutSize - 1 ) |
| continue; |
| if ( SizeMax < pSet->Size ) |
| { |
| pSetBest = pSet; |
| SizeMax = pSet->Size; |
| } |
| } |
| /* |
| // if the best is not choosen, select the one with largest reduction |
| SRedMax = 0; |
| if ( pSetBest == NULL ) |
| { |
| for ( i = 0; i < nSets; i++ ) |
| { |
| pSet = pStore + i; |
| if ( SRedMax < pSet->SRed ) |
| { |
| pSetBest = pSet; |
| SRedMax = pSet->SRed; |
| } |
| } |
| } |
| */ |
| if ( pSetBest == NULL ) |
| { |
| if ( fVerbose ) |
| printf( "Could not select a subset.\n" ); |
| return 0; |
| } |
| else |
| { |
| if ( fVerbose ) |
| printf( "Selected the following subset:\n" ); |
| if ( fVerbose ) |
| Lpk_MapSuppPrintSet( pSetBest, pSetBest - pStore ); |
| } |
| |
| // prepare the return result |
| // get the remaining variables |
| Entry = ((pSetBest->uSubset0 >> 16) | (pSetBest->uSubset1 >> 16)); |
| // get the variables to be removed |
| Entry = Kit_BitMask(nVars) & ~(1<<pSetBest->iVar) & ~Entry; |
| // make sure there are some - otherwise it is not supp-red |
| assert( Entry ); |
| // remember the first such variable |
| *piVarReused = Kit_WordFindFirstBit( Entry ); |
| *piVar = pSetBest->iVar; |
| return (pSetBest->uSubset1 << 16) | (pSetBest->uSubset0 & 0xFFFF); |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |