| /**CFile**************************************************************** |
| |
| FileName [abcShare.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Network and node package.] |
| |
| Synopsis [Shared logic extraction.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: abcShare.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "base/abc/abc.h" |
| |
| 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 nCountGates; |
| int nFoundGates; |
| }; |
| |
| 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 & 0xFFFFFFFF; } |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// 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 gate.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Wrd_t * Abc_NtkShareSuperXor( Abc_Obj_t * pObj, int * pfCompl, int * pCounter ) |
| { |
| Abc_Ntk_t * pNtk = Abc_ObjNtk(pObj); |
| Abc_Obj_t * pObjC, * pObj0, * pObj1, * pRoot = NULL; |
| Vec_Wrd_t * vSuper; |
| word Num, NumNext; |
| int i, k, fCompl = 0; |
| assert( !Abc_ObjIsComplement(pObj) ); |
| 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; |
| } |
| Vec_Wrd_t * Abc_NtkShareSuperAnd( Abc_Obj_t * pObj, int * pCounter ) |
| { |
| Abc_Ntk_t * pNtk = Abc_ObjNtk(pObj); |
| Abc_Obj_t * pObj0, * pObj1, * pRoot = NULL; |
| Vec_Wrd_t * vSuper; |
| word Num, NumNext; |
| int i, k; |
| assert( !Abc_ObjIsComplement(pObj) ); |
| // start iteration |
| vSuper = Vec_WrdAlloc( 10 ); |
| Vec_WrdPush( vSuper, Abc_NtkSharePack(Abc_ObjLevel(pObj), Abc_ObjToLit(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 AND gate decomposable on the topmost level |
| Vec_WrdForEachEntryReverse( vSuper, Num, i ) |
| { |
| pRoot = Abc_ObjFromLit( pNtk, Abc_NtkShareUnpackId(Num) ); |
| if ( !Abc_ObjIsComplement(pRoot) && Abc_ObjIsNode(pRoot) ) |
| { |
| Vec_WrdRemove( vSuper, Num ); |
| break; |
| } |
| } |
| if ( i == -1 ) |
| break; |
| assert( Abc_ObjIsNode(pRoot) ); |
| // extract |
| pObj0 = Abc_ObjChild0(pRoot); |
| pObj1 = Abc_ObjChild1(pRoot); |
| assert( Abc_ObjIsNode(Abc_ObjRegular(pObj0)) || Abc_ObjIsCi(Abc_ObjRegular(pObj0)) ); |
| assert( Abc_ObjIsNode(Abc_ObjRegular(pObj1)) || Abc_ObjIsCi(Abc_ObjRegular(pObj1)) ); |
| Vec_WrdPushOrder( vSuper, Abc_NtkSharePack(Abc_ObjLevel(Abc_ObjRegular(pObj0)), Abc_ObjToLit(pObj0)) ); |
| Vec_WrdPushOrder( vSuper, Abc_NtkSharePack(Abc_ObjLevel(Abc_ObjRegular(pObj1)), Abc_ObjToLit(pObj1)) ); |
| (*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 + 1 == NumNext && (NumNext & 1) ) // pos_lit & neg_lit = 0 |
| { |
| Vec_WrdClear( vSuper ); |
| return vSuper; |
| } |
| if ( Num < NumNext ) |
| Vec_WrdWriteEntry( vSuper, k++, Num ); |
| } |
| Vec_WrdShrink( vSuper, k ); |
| } |
| Vec_WrdForEachEntry( vSuper, Num, i ) |
| Vec_WrdWriteEntry( vSuper, i, Abc_NtkShareUnpackId(Num) ); |
| return vSuper; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Creates multi-input XOR representation for the nodes.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkTraverseSupersXor_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->nFoundGates ); |
| if ( Vec_WrdSize(vSuper) <= 1 || 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_NtkTraverseSupersXor_rec( p, Abc_NtkObj(p->pNtk, (int)Num), vInputs ); |
| Vec_WrdFree( vSuper ); |
| } |
| else |
| { |
| Abc_NtkTraverseSupersXor_rec( p, Abc_ObjFanin0(pObj), vInputs ); |
| Abc_NtkTraverseSupersXor_rec( p, Abc_ObjFanin1(pObj), vInputs ); |
| } |
| } |
| void Abc_NtkTraverseSupersAnd_rec( Abc_ShaMan_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vInputs ) |
| { |
| Vec_Wrd_t * vSuper; |
| word Num; |
| int k; |
| if ( Abc_NodeIsTravIdCurrent( pObj ) ) |
| return; |
| Abc_NodeSetTravIdCurrent( pObj ); |
| if ( Abc_ObjIsCi(pObj) ) |
| return; |
| assert( Abc_ObjIsNode(pObj) ); |
| vSuper = Abc_NtkShareSuperAnd( pObj, &p->nFoundGates ); |
| if ( Vec_WrdSize(vSuper) <= 1 || 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, (int)Num ); |
| Vec_IntPush( vInput, Abc_ObjLevel(Abc_NtkObj(p->pNtk, Abc_Lit2Var((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_ObjToLit(pObj) ); |
| } |
| // call recursively |
| Vec_WrdForEachEntry( vSuper, Num, k ) |
| Abc_NtkTraverseSupersAnd_rec( p, Abc_NtkObj(p->pNtk, Abc_Lit2Var((int)Num)), vInputs ); |
| Vec_WrdFree( vSuper ); |
| } |
| void Abc_NtkTraverseSupers( Abc_ShaMan_t * p, int fAnd ) |
| { |
| 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) * (1 + fAnd) ); |
| Abc_NtkIncrementTravId( p->pNtk ); |
| if ( fAnd ) |
| { |
| Abc_NtkForEachCo( p->pNtk, pObj, i ) |
| if ( Abc_ObjIsNode(Abc_ObjFanin0(pObj)) ) |
| Abc_NtkTraverseSupersAnd_rec( p, Abc_ObjFanin0(pObj), vInputs ); |
| } |
| else |
| { |
| Abc_NtkForEachCo( p->pNtk, pObj, i ) |
| if ( Abc_ObjIsNode(Abc_ObjFanin0(pObj)) ) |
| Abc_NtkTraverseSupersXor_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 [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| 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( "Gates = %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_NtkDumpBlif( Abc_Ntk_t * p ) |
| { |
| FILE * pFile; |
| Vec_Ptr_t * vSupp; |
| Abc_Obj_t * pObj; |
| int i, k; |
| pFile = fopen( "multi_and.blif", "wb" ); |
| if ( pFile == NULL ) |
| { |
| printf( "Cannot open output file.\n" ); |
| return; |
| } |
| fprintf( pFile, ".model %s\n", "multi_and" ); |
| fprintf( pFile, ".inputs" ); |
| for ( i = 0; i < Abc_NtkCiNum(p); i++ ) |
| fprintf( pFile, " i%d", i ); |
| fprintf( pFile, "\n" ); |
| fprintf( pFile, ".outputs" ); |
| for ( i = 0; i < Abc_NtkCoNum(p); i++ ) |
| fprintf( pFile, " o%d", i ); |
| fprintf( pFile, "\n" ); |
| Abc_NtkForEachCi( p, pObj, i ) |
| pObj->iTemp = i; |
| for ( i = 0; i < Abc_NtkCoNum(p); i++ ) |
| { |
| pObj = Abc_NtkCo( p, i ); |
| vSupp = Abc_NtkNodeSupport( p, &pObj, 1 ); |
| fprintf( pFile, ".names" ); |
| Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, k ) |
| fprintf( pFile, " i%d", pObj->iTemp ); |
| fprintf( pFile, " o%d\n", i ); |
| Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, k ) |
| fprintf( pFile, "1" ); |
| fprintf( pFile, " 1\n" ); |
| Vec_PtrFree( vSupp ); |
| } |
| fprintf( pFile, ".end\n\n" ); |
| fclose( pFile ); |
| } |
| |
| |
| /**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, int fAnd ) |
| { |
| 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) ); |
| if ( fAnd ) |
| pObj = Abc_AigAnd( (Abc_Aig_t *)p->pNtk->pManFunc, pObj0, pObj1 ); |
| else |
| pObj = Abc_AigXor( (Abc_Aig_t *)p->pNtk->pManFunc, pObj0, pObj1 ); |
| p->nCountGates++; |
| |
| // 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, int fAnd ) |
| { |
| 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; |
| int iLitConst1 = Abc_ObjToLit( Abc_AigConst1(p->pNtk) ); |
| |
| vOrig = Vec_PtrAlloc( p->nStartCols ); |
| vRepl = Vec_PtrAlloc( p->nStartCols ); |
| for ( i = 0; i < p->nStartCols; i++ ) |
| { |
| iLit = Vec_IntEntry( p->vObj2Lit, i ); |
| assert( !fAnd || !Abc_LitIsCompl(iLit) ); |
| |
| pObj = Abc_NtkObj( p->pNtk, Abc_Lit2Var(iLit) ); |
| |
| if ( fAnd ) |
| pNew = Abc_AigConst1(p->pNtk); |
| else |
| pNew = Abc_ObjNotCond( Abc_AigConst1(p->pNtk), !Abc_LitIsCompl(iLit) ); |
| |
| Vec_PtrPush( vOrig, pObj ); |
| Vec_PtrPush( vRepl, pNew ); |
| |
| p->nCountGates--; |
| } |
| |
| // 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 ); |
| if ( fAnd ) |
| pNew = Abc_AigAnd( (Abc_Aig_t *)p->pNtk->pManFunc, pNew, Abc_ObjFromLit(p->pNtk, iLit) ); |
| else |
| pNew = Abc_AigXor( (Abc_Aig_t *)p->pNtk->pManFunc, pNew, Abc_ObjFromLit(p->pNtk, iLit) ); |
| Vec_PtrWriteEntry( vRepl, ObjId, pNew ); |
| p->nCountGates++; |
| } |
| } |
| |
| if ( p->fVerbose ) |
| printf( "Total gates collected = %d. Total gates constructed = %d.\n", p->nFoundGates, p->nCountGates ); |
| |
| // create map of originals |
| vMap2Repl = Vec_IntStartFull( Abc_NtkObjNumMax(p->pNtk) ); |
| Vec_PtrForEachEntry( Abc_Obj_t *, vOrig, pObj, i ) |
| { |
| // printf( "Replacing %d by %d.\n", Abc_ObjId(pObj), Abc_ObjToLit((Abc_Obj_t *)Vec_PtrEntry(vRepl, 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 ) |
| { |
| if ( iLit == iLitConst1 && fAnd ) |
| { |
| pObj->fCompl0 ^= 1; |
| Vec_IntWriteEntry( &pObj->vFanins, 0, Abc_Lit2Var(iLitConst1) ); |
| } |
| else |
| { |
| 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 ) |
| { |
| if ( iLit == iLitConst1 && fAnd ) |
| { |
| pObj->fCompl1 ^= 1; |
| Vec_IntWriteEntry( &pObj->vFanins, 1, Abc_Lit2Var(iLitConst1) ); |
| } |
| else |
| { |
| pObj->fCompl1 ^= Abc_LitIsCompl(iLit); |
| Vec_IntWriteEntry( &pObj->vFanins, 1, Abc_Lit2Var(iLit) ); |
| } |
| } |
| } |
| } |
| Vec_IntFree( vMap2Repl ); |
| |
| // pNtk = Abc_NtkRestrash( p->pNtk, 1 ); |
| if ( fAnd ) |
| pNtk = Abc_NtkBalance( p->pNtk, 0, 0, 1 ); |
| else |
| pNtk = Abc_NtkBalanceExor( p->pNtk, 1, 0 ); |
| return pNtk; |
| } |
| |
| /**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) ); |
| // Abc_NtkDumpBlif( pNtk ); |
| p = Abc_ShaManStart( pNtk ); |
| p->nMultiSize = nMultiSize; |
| p->fVerbose = fVerbose; |
| Abc_NtkTraverseSupers( p, fAnd ); |
| if ( p->nStartCols < 2 ) |
| { |
| Abc_ShaManStop( p ); |
| return Abc_NtkDup( pNtk ); |
| } |
| if ( fVerbose ) |
| Abc_NtkSharePrint( p ); |
| Abc_NtkShareOptimize( p, fAnd ); |
| if ( fVerbose ) |
| Abc_NtkSharePrint( p ); |
| pNtkNew = Abc_NtkUpdateNetwork( p, fAnd ); |
| Abc_ShaManStop( p ); |
| return pNtkNew; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |