diff options
author | Alan Mishchenko <alanmi@berkeley.edu> | 2012-03-25 16:49:29 -0700 |
---|---|---|
committer | Alan Mishchenko <alanmi@berkeley.edu> | 2012-03-25 16:49:29 -0700 |
commit | b4df114e4a84e56f9cd1b865d685852045b16937 (patch) | |
tree | 6b20f1673f1f9057523b059d8f1c0c1673c1a315 /src/base/abci/abcExtract.c | |
parent | 309bcf2dec92b745c3ec0078691997823317c58b (diff) | |
download | abc-b4df114e4a84e56f9cd1b865d685852045b16937.tar.gz abc-b4df114e4a84e56f9cd1b865d685852045b16937.tar.bz2 abc-b4df114e4a84e56f9cd1b865d685852045b16937.zip |
Logic sharing for multi-input gates.
Diffstat (limited to 'src/base/abci/abcExtract.c')
-rw-r--r-- | src/base/abci/abcExtract.c | 510 |
1 files changed, 505 insertions, 5 deletions
diff --git a/src/base/abci/abcExtract.c b/src/base/abci/abcExtract.c index e6b4193b..cc2532de 100644 --- a/src/base/abci/abcExtract.c +++ b/src/base/abci/abcExtract.c @@ -1,12 +1,12 @@ /**CFile**************************************************************** - FileName [abcMvCost.c] + FileName [abcShare.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] - Synopsis [Calculating the cost of one MV block.] + Synopsis [Shared logic extraction.] Author [Alan Mishchenko] @@ -14,7 +14,7 @@ Date [Ver. 1.0. Started - June 20, 2005.] - Revision [$Id: abcMvCost.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + Revision [$Id: abcShare.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ @@ -22,17 +22,143 @@ ABC_NAMESPACE_IMPL_START - //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +#define SHARE_NUM 2 + +typedef struct Abc_ShaMan_t_ Abc_ShaMan_t; +struct Abc_ShaMan_t_ +{ + int nMultiSize; + int fVerbose; + Abc_Ntk_t * pNtk; + Vec_Ptr_t * vBuckets; + Vec_Int_t * vObj2Lit; + int nStartCols; + int nCountXors; + int nFoundXors; +}; + +static inline word Abc_NtkSharePack( int Lev, int Id ) { return (((word)Lev) << 32) | Id; } +static inline int Abc_NtkShareUnpackLev( word Num ) { return (Num >> 32); } +static inline int Abc_NtkShareUnpackId( word Num ) { return Num & 0xFFFF; } + + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* + Synopsis [Working with the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_ShaMan_t * Abc_ShaManStart( Abc_Ntk_t * pNtk ) +{ + Abc_ShaMan_t * p; + p = ABC_CALLOC( Abc_ShaMan_t, 1 ); + p->pNtk = pNtk; + p->vObj2Lit = Vec_IntAlloc( 1000 ); + return p; +} +void Abc_ShaManStop( Abc_ShaMan_t * p ) +{ + Vec_Ptr_t * vBucket; + int i; + Vec_PtrForEachEntry( Vec_Ptr_t *, p->vBuckets, vBucket, i ) + Vec_VecFree( (Vec_Vec_t *)vBucket ); + Vec_PtrFreeP( &p->vBuckets ); + Vec_IntFreeP( &p->vObj2Lit ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Collects one multi-input XOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Abc_NtkShareSuperXor( Abc_Obj_t * pObjInit, int * pfCompl, int * pCounter ) +{ + int fCompl = Abc_ObjIsComplement(pObjInit); + Abc_Obj_t * pObj = Abc_ObjRegular(pObjInit); + Abc_Ntk_t * pNtk = Abc_ObjNtk(pObj); + Abc_Obj_t * pObjC, * pObj0, * pObj1, * pRoot; + Vec_Wrd_t * vSuper; + word Num, NumNext; + int i, k; + assert( Abc_NodeIsExorType(pObj) ); + // start iteration + vSuper = Vec_WrdAlloc( 10 ); + Vec_WrdPush( vSuper, Abc_NtkSharePack(Abc_ObjLevel(pObj), Abc_ObjId(pObj)) ); + while ( Vec_WrdSize(vSuper) > 0 ) + { + // make sure there are no duplicates + Num = Vec_WrdEntry( vSuper, 0 ); + Vec_WrdForEachEntryStart( vSuper, NumNext, i, 1 ) + { + assert( Num != NumNext ); + Num = NumNext; + } + // extract XOR gate decomposable on the topmost level + Vec_WrdForEachEntryReverse( vSuper, Num, i ) + { + pRoot = Abc_NtkObj( pNtk, Abc_NtkShareUnpackId(Num) ); + if ( Abc_NodeIsExorType(pRoot) ) + { + Vec_WrdRemove( vSuper, Num ); + break; + } + } + if ( i == -1 ) + break; + // extract + pObjC = Abc_NodeRecognizeMux( pRoot, &pObj1, &pObj0 ); + assert( pObj1 == Abc_ObjNot(pObj0) ); + fCompl ^= Abc_ObjIsComplement(pObjC); pObjC = Abc_ObjRegular(pObjC); + fCompl ^= Abc_ObjIsComplement(pObj0); pObj0 = Abc_ObjRegular(pObj0); + Vec_WrdPushOrder( vSuper, Abc_NtkSharePack(Abc_ObjLevel(pObjC), Abc_ObjId(pObjC)) ); + Vec_WrdPushOrder( vSuper, Abc_NtkSharePack(Abc_ObjLevel(pObj0), Abc_ObjId(pObj0)) ); + (*pCounter)++; + // remove duplicates + k = 0; + Vec_WrdForEachEntry( vSuper, Num, i ) + { + if ( i + 1 == Vec_WrdSize(vSuper) ) + { + Vec_WrdWriteEntry( vSuper, k++, Num ); + break; + } + NumNext = Vec_WrdEntry( vSuper, i+1 ); + assert( Num <= NumNext ); + if ( Num == NumNext ) + i++; + else + Vec_WrdWriteEntry( vSuper, k++, Num ); + } + Vec_WrdShrink( vSuper, k ); + } + *pfCompl = fCompl; + Vec_WrdForEachEntry( vSuper, Num, i ) + Vec_WrdWriteEntry( vSuper, i, Abc_NtkShareUnpackId(Num) ); + return vSuper; +} + +/**Function************************************************************* + Synopsis [] Description [] @@ -42,11 +168,385 @@ ABC_NAMESPACE_IMPL_START SeeAlso [] ***********************************************************************/ -void Abc_MvCostTest( Abc_Ntk_t * pNtk ) +void Abc_NtkSharePrint( Abc_ShaMan_t * p ) { + Vec_Ptr_t * vBucket; + Vec_Int_t * vInput; + int i, k, j, ObjId; + char * pBuffer = ABC_ALLOC( char, Vec_IntSize(p->vObj2Lit) + 1 ); + int * pCounters = ABC_CALLOC( int, Vec_IntSize(p->vObj2Lit) + 1 ); + int nTotal = 0; + Vec_PtrForEachEntry( Vec_Ptr_t *, p->vBuckets, vBucket, i ) + Vec_PtrForEachEntry( Vec_Int_t *, vBucket, vInput, j ) + { + for ( k = 0; k < Vec_IntSize(p->vObj2Lit); k++ ) + pBuffer[k] = '0'; + pBuffer[k] = 0; + + Vec_IntForEachEntryStart( vInput, ObjId, k, SHARE_NUM ) + { + assert( ObjId < Vec_IntSize(p->vObj2Lit) ); + pBuffer[ObjId] = '1'; + pCounters[ObjId]++; + } + printf( "%4d%3d: %s\n", Vec_IntEntry(vInput, 0), Vec_IntEntry(vInput, 1), pBuffer ); + } + + for ( i = 0; i < Vec_IntSize(p->vObj2Lit); i++ ) + if ( pCounters[i] > 0 ) + printf( "%d=%d ", i, pCounters[i] ); + printf( "\n" ); + + nTotal = 0; + for ( i = 0; i < p->nStartCols; i++ ) + nTotal += pCounters[i] - 1; + printf( "Total = %d. ", nTotal ); + printf( "Xors = %d.\n", Vec_IntSize(p->vObj2Lit) - p->nStartCols + nTotal ); + + ABC_FREE( pCounters ); + ABC_FREE( pBuffer ); + printf( "Bucket contents: " ); + Vec_PtrForEachEntry( Vec_Ptr_t *, p->vBuckets, vBucket, i ) + printf( "%d ", Vec_PtrSize(vBucket) ); + printf( "\n" ); } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkShareFindBestMatch( Vec_Ptr_t * vBuckets, Vec_Int_t ** pvInput, Vec_Int_t ** pvInput2 ) +{ + int nPoolSize = 40; + Vec_Ptr_t * vPool = Vec_PtrAlloc( nPoolSize ); + Vec_Ptr_t * vBucket; + Vec_Int_t * vInput, * vInput2, * vInputBest = NULL, * vInputBest2 = NULL; + int i, k, Cost, CostBest = 0, Delay, DelayBest = 0; + + Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vBuckets, vBucket, i ) + Vec_PtrForEachEntry( Vec_Int_t *, vBucket, vInput, k ) + { + Vec_PtrPush( vPool, vInput ); + if ( Vec_PtrSize(vPool) == nPoolSize ) + goto outside; + } +outside: + + Vec_PtrForEachEntryReverse( Vec_Int_t *, vPool, vInput, i ) + Vec_PtrForEachEntryReverse( Vec_Int_t *, vPool, vInput2, k ) + { + if ( i == k ) + continue; + + vInput->pArray += SHARE_NUM; + vInput2->pArray += SHARE_NUM; + vInput->nSize -= SHARE_NUM; + vInput2->nSize -= SHARE_NUM; + + Cost = Vec_IntTwoCountCommon(vInput, vInput2); + + vInput->pArray -= SHARE_NUM; + vInput2->pArray -= SHARE_NUM; + vInput->nSize += SHARE_NUM; + vInput2->nSize += SHARE_NUM; + + if ( Cost < 2 ) + continue; + + Delay = Abc_MaxInt( Vec_IntEntry(vInput, 1), Vec_IntEntry(vInput2, 1) ); + + if ( CostBest < Cost || (CostBest == Cost && (DelayBest > Delay)) ) + { + CostBest = Cost; + DelayBest = Delay; + vInputBest = vInput; + vInputBest2 = vInput2; + } + } + Vec_PtrFree( vPool ); + + *pvInput = vInputBest; + *pvInput2 = vInputBest2; + + if ( vInputBest == NULL ) + return; + + Vec_PtrRemove( (Vec_Ptr_t *)Vec_PtrEntry(vBuckets, Vec_IntSize(vInputBest)-SHARE_NUM), (Vec_Int_t *)vInputBest ); + Vec_PtrRemove( (Vec_Ptr_t *)Vec_PtrEntry(vBuckets, Vec_IntSize(vInputBest2)-SHARE_NUM), (Vec_Int_t *)vInputBest2 ); +} +void Abc_NtkShareOptimize( Abc_ShaMan_t * p ) +{ + Abc_Obj_t * pObj, * pObj0, * pObj1; + Vec_Int_t * vInput, * vInput2; + Vec_Int_t * vNew, * vOld1, * vOld2; + int i; + for ( i = 0; ; i++ ) + { + Abc_NtkShareFindBestMatch( p->vBuckets, &vInput, &vInput2 ); + if ( vInput == NULL ) + break; + + // create new node + pObj0 = Abc_ObjFromLit( p->pNtk, Vec_IntEntry(vInput, 0) ); + pObj1 = Abc_ObjFromLit( p->pNtk, Vec_IntEntry(vInput2, 0) ); + pObj = Abc_AigXor( (Abc_Aig_t *)p->pNtk->pManFunc, pObj0, pObj1 ); + p->nCountXors++; + + // save new node + vOld1 = Vec_IntAlloc( 16 ); Vec_IntPush( vOld1, Vec_IntEntry(vInput, 0) ); Vec_IntPush( vOld1, Vec_IntEntry(vInput, 1) ); + vOld2 = Vec_IntAlloc( 16 ); Vec_IntPush( vOld2, Vec_IntEntry(vInput2, 0) ); Vec_IntPush( vOld2, Vec_IntEntry(vInput2, 1) ); + vNew = Vec_IntAlloc( 16 ); Vec_IntPush( vNew, Abc_ObjToLit(pObj) ); Vec_IntPush( vNew, Abc_ObjLevel(Abc_ObjRegular(pObj)) ); + + // compute new arrays + vInput->pArray += SHARE_NUM; + vInput2->pArray += SHARE_NUM; + vInput->nSize -= SHARE_NUM; + vInput2->nSize -= SHARE_NUM; + + Vec_IntTwoSplit( vInput, vInput2, vNew, vOld1, vOld2 ); + + vInput->pArray -= SHARE_NUM; + vInput2->pArray -= SHARE_NUM; + vInput->nSize += SHARE_NUM; + vInput2->nSize += SHARE_NUM; + + // add to the old ones + Vec_IntPush( vOld1, Vec_IntSize(p->vObj2Lit) ); + Vec_IntPush( vOld2, Vec_IntSize(p->vObj2Lit) ); + Vec_IntPush( p->vObj2Lit, Abc_ObjToLit(pObj) ); + + Vec_PtrPush( (Vec_Ptr_t *)Vec_PtrEntry(p->vBuckets, Vec_IntSize(vOld1)-SHARE_NUM), vOld1 ); + Vec_PtrPush( (Vec_Ptr_t *)Vec_PtrEntry(p->vBuckets, Vec_IntSize(vOld2)-SHARE_NUM), vOld2 ); + Vec_PtrPush( (Vec_Ptr_t *)Vec_PtrEntry(p->vBuckets, Vec_IntSize(vNew)-SHARE_NUM), vNew ); + + Vec_IntFree( vInput ); + Vec_IntFree( vInput2 ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkUpdateNetwork( Abc_ShaMan_t * p ) +{ + Abc_Ntk_t * pNtk; + Vec_Int_t * vInput, * vMap2Repl; + Vec_Ptr_t * vOrig, * vRepl, * vBucket; + Abc_Obj_t * pObj, * pNew; + int i, j, k, ObjId, iLit; + + vOrig = Vec_PtrAlloc( p->nStartCols ); + vRepl = Vec_PtrAlloc( p->nStartCols ); + for ( i = 0; i < p->nStartCols; i++ ) + { + iLit = Vec_IntEntry( p->vObj2Lit, i ); + + pObj = Abc_NtkObj( p->pNtk, Abc_Lit2Var(iLit) ); + pNew = Abc_ObjNotCond( Abc_AigConst1(p->pNtk), !Abc_LitIsCompl(iLit) ); + + Vec_PtrPush( vOrig, pObj ); + Vec_PtrPush( vRepl, pNew ); + + p->nCountXors--; + } + + // go through the columns + Vec_PtrForEachEntry( Vec_Ptr_t *, p->vBuckets, vBucket, i ) + Vec_PtrForEachEntry( Vec_Int_t *, vBucket, vInput, j ) + { + Vec_IntForEachEntryStart( vInput, ObjId, k, SHARE_NUM ) + { + assert( ObjId < Vec_IntSize(p->vObj2Lit) ); + if ( ObjId >= p->nStartCols ) + break; + assert( ObjId < p->nStartCols ); + iLit = Vec_IntEntry( vInput, 0 ); + + pNew = (Abc_Obj_t *)Vec_PtrEntry( vRepl, ObjId ); + pNew = Abc_AigXor( (Abc_Aig_t *)p->pNtk->pManFunc, pNew, Abc_ObjFromLit(p->pNtk, iLit) ); + Vec_PtrWriteEntry( vRepl, ObjId, pNew ); + p->nCountXors++; + } + } + + if ( p->fVerbose ) + printf( "Total XORs collected = %d. Total XORs constructed = %d.\n", p->nFoundXors, p->nCountXors ); + + // create map of originals + vMap2Repl = Vec_IntStartFull( Abc_NtkObjNumMax(p->pNtk) ); + Vec_PtrForEachEntry( Abc_Obj_t *, vOrig, pObj, i ) + Vec_IntWriteEntry( vMap2Repl, Abc_ObjId(pObj), Abc_ObjToLit((Abc_Obj_t *)Vec_PtrEntry(vRepl, i)) ); + Vec_PtrFree( vOrig ); + Vec_PtrFree( vRepl ); + + // update fanin pointers + Abc_NtkForEachObj( p->pNtk, pObj, i ) + { + if ( Abc_ObjIsCo(pObj) || Abc_ObjIsNode(pObj) ) + { + iLit = Vec_IntEntry( vMap2Repl, Abc_ObjFaninId0(pObj) ); + if ( iLit >= 0 ) + { + pObj->fCompl0 ^= Abc_LitIsCompl(iLit); + Vec_IntWriteEntry( &pObj->vFanins, 0, Abc_Lit2Var(iLit) ); + } + } + if ( Abc_ObjIsNode(pObj) ) + { + iLit = Vec_IntEntry( vMap2Repl, Abc_ObjFaninId1(pObj) ); + if ( iLit >= 0 ) + { + pObj->fCompl1 ^= Abc_LitIsCompl(iLit); + Vec_IntWriteEntry( &pObj->vFanins, 1, Abc_Lit2Var(iLit) ); + } + } + } + Vec_IntFree( vMap2Repl ); + +// pNtk = Abc_NtkRestrash( p->pNtk, 1 ); + pNtk = Abc_NtkBalanceExor( p->pNtk, 1, 0 ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Creates multi-input XOR representation for the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTraverseSupers_rec( Abc_ShaMan_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vInputs ) +{ + if ( Abc_NodeIsTravIdCurrent( pObj ) ) + return; + Abc_NodeSetTravIdCurrent( pObj ); + if ( Abc_ObjIsCi(pObj) ) + return; + assert( Abc_ObjIsNode(pObj) ); + if ( Abc_NodeIsExorType(pObj) ) + { + Vec_Wrd_t * vSuper; + int k, fCompl; + word Num; + vSuper = Abc_NtkShareSuperXor( pObj, &fCompl, &p->nFoundXors ); + if ( Vec_WrdSize(vSuper) >= p->nMultiSize ) + { + Vec_WrdForEachEntry( vSuper, Num, k ) + { + Vec_Int_t * vInput = (Vec_Int_t *)Vec_PtrEntry( vInputs, (int)Num ); + if ( vInput == NULL ) + { + vInput = Vec_IntAlloc( 10 ); + Vec_IntPush( vInput, Abc_Var2Lit((int)Num, 0) ); + Vec_IntPush( vInput, Abc_ObjLevel(Abc_NtkObj(p->pNtk, (int)Num)) ); + assert( SHARE_NUM == Vec_IntSize(vInput) ); + Vec_PtrWriteEntry( vInputs, (int)Num, vInput ); + } + Vec_IntPush( vInput, Vec_IntSize(p->vObj2Lit) ); + } + Vec_IntPush( p->vObj2Lit, Abc_Var2Lit(Abc_ObjId(pObj), fCompl) ); + } + // call recursively + Vec_WrdForEachEntry( vSuper, Num, k ) + Abc_NtkTraverseSupers_rec( p, Abc_NtkObj(p->pNtk, (int)Num), vInputs ); + Vec_WrdFree( vSuper ); + } + else + { + Abc_NtkTraverseSupers_rec( p, Abc_ObjFanin0(pObj), vInputs ); + Abc_NtkTraverseSupers_rec( p, Abc_ObjFanin1(pObj), vInputs ); + } +} +void Abc_NtkTraverseSupers( Abc_ShaMan_t * p ) +{ + Vec_Ptr_t * vInputs; + Vec_Int_t * vInput; + Abc_Obj_t * pObj; + int i, nOnesMax; + + // create mapping of nodes into their column vectors + vInputs = Vec_PtrStart( Abc_NtkObjNumMax(p->pNtk) ); + Abc_NtkIncrementTravId( p->pNtk ); + Abc_NtkForEachCo( p->pNtk, pObj, i ) + Abc_NtkTraverseSupers_rec( p, Abc_ObjFanin0(pObj), vInputs ); + p->nStartCols = Vec_IntSize(p->vObj2Lit); + + // find the largest number of 1s + nOnesMax = 0; + Vec_PtrForEachEntry( Vec_Int_t *, vInputs, vInput, i ) + if ( vInput ) + nOnesMax = Abc_MaxInt( nOnesMax, Vec_IntSize(vInput)-SHARE_NUM ); + + // create buckets + assert( p->vBuckets == NULL ); + p->vBuckets = Vec_PtrAlloc( nOnesMax + 1 ); + for ( i = 0; i <= nOnesMax; i++ ) + Vec_PtrPush( p->vBuckets, Vec_PtrAlloc(10) ); + + // load vectors into buckets + Vec_PtrForEachEntry( Vec_Int_t *, vInputs, vInput, i ) + if ( vInput ) + Vec_PtrPush( (Vec_Ptr_t *)Vec_PtrEntry(p->vBuckets, Vec_IntSize(vInput)-SHARE_NUM), vInput ); + Vec_PtrFree( vInputs ); +} + +/**Function************************************************************* + + Synopsis [Extracts one multi-output XOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkShareXor( Abc_Ntk_t * pNtk, int nMultiSize, int fAnd, int fVerbose ) +{ + Abc_Ntk_t * pNtkNew; + Abc_ShaMan_t * p; + assert( Abc_NtkIsStrash(pNtk) ); + p = Abc_ShaManStart( pNtk ); + p->nMultiSize = nMultiSize; + p->fVerbose = fVerbose; + Abc_NtkTraverseSupers( p ); + if ( p->nStartCols < 2 ) + { + Abc_ShaManStop( p ); + return Abc_NtkDup( pNtk ); + } + if ( fVerbose ) + Abc_NtkSharePrint( p ); + Abc_NtkShareOptimize( p ); + if ( fVerbose ) + Abc_NtkSharePrint( p ); + pNtkNew = Abc_NtkUpdateNetwork( p ); + Abc_ShaManStop( p ); + return pNtkNew; +} + + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// |