| /**CFile**************************************************************** |
| |
| FileName [ FxchMan.c ] |
| |
| PackageName [ Fast eXtract with Cube Hashing (FXCH) ] |
| |
| Synopsis [ Fxch Manager implementation ] |
| |
| Author [ Bruno Schmitt - boschmitt at inf.ufrgs.br ] |
| |
| Affiliation [ UFRGS ] |
| |
| Date [ Ver. 1.0. Started - March 6, 2016. ] |
| |
| Revision [] |
| |
| ***********************************************************************/ |
| #include "Fxch.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// LOCAL FUNCTIONS DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| static inline int Fxch_ManSCAddRemove( Fxch_Man_t* pFxchMan, |
| unsigned int SubCubeID, |
| unsigned int iCube, |
| unsigned int iLit0, |
| unsigned int iLit1, |
| char fAdd, |
| char fUpdate ) |
| { |
| int ret = 0; |
| |
| if ( fAdd ) |
| { |
| ret = Fxch_SCHashTableInsert( pFxchMan->pSCHashTable, pFxchMan->vCubes, |
| SubCubeID, |
| iCube, iLit0, iLit1, fUpdate ); |
| } |
| else |
| { |
| ret = Fxch_SCHashTableRemove( pFxchMan->pSCHashTable, pFxchMan->vCubes, |
| SubCubeID, |
| iCube, iLit0, iLit1, fUpdate ); |
| } |
| |
| return ret; |
| } |
| |
| |
| static inline int Fxch_ManDivSingleCube( Fxch_Man_t* pFxchMan, |
| int iCube, |
| int fAdd, |
| int fUpdate ) |
| { |
| Vec_Int_t* vCube = Vec_WecEntry( pFxchMan->vCubes, iCube ); |
| int i, k, |
| Lit0, |
| Lit1, |
| fSingleCube = 1, |
| fBase = 0; |
| |
| if ( Vec_IntSize( vCube ) < 2 ) |
| return 0; |
| |
| Vec_IntForEachEntryStart( vCube, Lit0, i, 1) |
| Vec_IntForEachEntryStart( vCube, Lit1, k, (i + 1) ) |
| { |
| int * pOutputID, nOnes, j, z; |
| assert( Lit0 < Lit1 ); |
| |
| Vec_IntClear( pFxchMan->vCubeFree ); |
| Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( Abc_LitNot( Lit0 ), 0 ) ); |
| Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( Abc_LitNot( Lit1 ), 1 ) ); |
| |
| pOutputID = Vec_IntEntryP( pFxchMan->vOutputID, iCube * pFxchMan->nSizeOutputID ); |
| nOnes = 0; |
| |
| for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) |
| nOnes += Fxch_CountOnes( pOutputID[j] ); |
| |
| if ( nOnes == 0 ) |
| nOnes = 1; |
| |
| if (fAdd) |
| { |
| for ( z = 0; z < nOnes; z++ ) |
| Fxch_DivAdd( pFxchMan, fUpdate, fSingleCube, fBase ); |
| pFxchMan->nPairsS++; |
| } |
| else |
| { |
| for ( z = 0; z < nOnes; z++ ) |
| Fxch_DivRemove( pFxchMan, fUpdate, fSingleCube, fBase ); |
| pFxchMan->nPairsS--; |
| } |
| } |
| |
| return Vec_IntSize( vCube ) * ( Vec_IntSize( vCube ) - 1 ) / 2; |
| } |
| |
| static inline void Fxch_ManDivDoubleCube( Fxch_Man_t* pFxchMan, |
| int iCube, |
| int fAdd, |
| int fUpdate ) |
| { |
| Vec_Int_t* vLitHashKeys = pFxchMan->vLitHashKeys, |
| * vCube = Vec_WecEntry( pFxchMan->vCubes, iCube ); |
| int SubCubeID = 0, |
| iLit0, |
| Lit0; |
| |
| Vec_IntForEachEntryStart( vCube, Lit0, iLit0, 1) |
| SubCubeID += Vec_IntEntry( vLitHashKeys, Lit0 ); |
| |
| Fxch_ManSCAddRemove( pFxchMan, SubCubeID, |
| iCube, 0, 0, |
| (char)fAdd, (char)fUpdate ); |
| |
| Vec_IntForEachEntryStart( vCube, Lit0, iLit0, 1) |
| { |
| /* 1 Lit remove */ |
| SubCubeID -= Vec_IntEntry( vLitHashKeys, Lit0 ); |
| |
| pFxchMan->nPairsD += Fxch_ManSCAddRemove( pFxchMan, SubCubeID, |
| iCube, iLit0, 0, |
| (char)fAdd, (char)fUpdate ); |
| |
| if ( Vec_IntSize( vCube ) >= 3 ) |
| { |
| int Lit1, |
| iLit1; |
| |
| Vec_IntForEachEntryStart( vCube, Lit1, iLit1, iLit0 + 1) |
| { |
| /* 2 Lit remove */ |
| SubCubeID -= Vec_IntEntry( vLitHashKeys, Lit1 ); |
| |
| pFxchMan->nPairsD += Fxch_ManSCAddRemove( pFxchMan, SubCubeID, |
| iCube, iLit0, iLit1, |
| (char)fAdd, (char)fUpdate ); |
| |
| SubCubeID += Vec_IntEntry( vLitHashKeys, Lit1 ); |
| } |
| } |
| |
| SubCubeID += Vec_IntEntry( vLitHashKeys, Lit0 ); |
| } |
| } |
| |
| static inline void Fxch_ManCompressCubes( Vec_Wec_t* vCubes, |
| Vec_Int_t* vLit2Cube ) |
| { |
| int i, |
| k = 0, |
| CubeId; |
| |
| Vec_IntForEachEntry( vLit2Cube, CubeId, i ) |
| if ( Vec_IntSize(Vec_WecEntry(vCubes, CubeId)) > 0 ) |
| Vec_IntWriteEntry( vLit2Cube, k++, CubeId ); |
| |
| Vec_IntShrink( vLit2Cube, k ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// PUBLIC INTERFACE /// |
| //////////////////////////////////////////////////////////////////////// |
| Fxch_Man_t* Fxch_ManAlloc( Vec_Wec_t* vCubes ) |
| { |
| Fxch_Man_t* pFxchMan = ABC_CALLOC( Fxch_Man_t, 1 ); |
| |
| pFxchMan->vCubes = vCubes; |
| pFxchMan->nCubesInit = Vec_WecSize( vCubes ); |
| |
| pFxchMan->pDivHash = Hsh_VecManStart( 1024 ); |
| pFxchMan->vDivWeights = Vec_FltAlloc( 1024 ); |
| pFxchMan->vDivCubePairs = Vec_WecAlloc( 1024 ); |
| |
| pFxchMan->vCubeFree = Vec_IntAlloc( 4 ); |
| pFxchMan->vDiv = Vec_IntAlloc( 4 ); |
| |
| pFxchMan->vCubesS = Vec_IntAlloc( 128 ); |
| pFxchMan->vPairs = Vec_IntAlloc( 128 ); |
| pFxchMan->vCubesToUpdate = Vec_IntAlloc( 64 ); |
| pFxchMan->vCubesToRemove = Vec_IntAlloc( 64 ); |
| pFxchMan->vSCC = Vec_IntAlloc( 64 ); |
| |
| return pFxchMan; |
| } |
| |
| void Fxch_ManFree( Fxch_Man_t* pFxchMan ) |
| { |
| Vec_WecFree( pFxchMan->vLits ); |
| Vec_IntFree( pFxchMan->vLitCount ); |
| Vec_IntFree( pFxchMan->vLitHashKeys ); |
| Hsh_VecManStop( pFxchMan->pDivHash ); |
| Vec_FltFree( pFxchMan->vDivWeights ); |
| Vec_QueFree( pFxchMan->vDivPrio ); |
| Vec_WecFree( pFxchMan->vDivCubePairs ); |
| Vec_IntFree( pFxchMan->vLevels ); |
| |
| Vec_IntFree( pFxchMan->vCubeFree ); |
| Vec_IntFree( pFxchMan->vDiv ); |
| |
| Vec_IntFree( pFxchMan->vCubesS ); |
| Vec_IntFree( pFxchMan->vPairs ); |
| Vec_IntFree( pFxchMan->vCubesToUpdate ); |
| Vec_IntFree( pFxchMan->vCubesToRemove ); |
| Vec_IntFree( pFxchMan->vSCC ); |
| |
| ABC_FREE( pFxchMan ); |
| } |
| |
| void Fxch_ManMapLiteralsIntoCubes( Fxch_Man_t* pFxchMan, |
| int nVars ) |
| { |
| |
| Vec_Int_t* vCube; |
| int i, k, |
| Lit, |
| Count; |
| |
| pFxchMan->nVars = 0; |
| pFxchMan->nLits = 0; |
| Vec_WecForEachLevel( pFxchMan->vCubes, vCube, i ) |
| { |
| assert( Vec_IntSize(vCube) > 0 ); |
| pFxchMan->nVars = Abc_MaxInt( pFxchMan->nVars, Vec_IntEntry( vCube, 0 ) ); |
| pFxchMan->nLits += Vec_IntSize(vCube) - 1; |
| Vec_IntForEachEntryStart( vCube, Lit, k, 1 ) |
| pFxchMan->nVars = Abc_MaxInt( pFxchMan->nVars, Abc_Lit2Var( Lit ) ); |
| } |
| |
| assert( pFxchMan->nVars < nVars ); |
| pFxchMan->nVars = nVars; |
| |
| /* Count the number of time each literal appears on the SOP */ |
| pFxchMan->vLitCount = Vec_IntStart( 2 * pFxchMan->nVars ); |
| Vec_WecForEachLevel( pFxchMan->vCubes, vCube, i ) |
| Vec_IntForEachEntryStart( vCube, Lit, k, 1 ) |
| Vec_IntAddToEntry( pFxchMan->vLitCount, Lit, 1 ); |
| |
| /* Allocate space to the array of arrays wich maps Literals into cubes which uses them */ |
| pFxchMan->vLits = Vec_WecStart( 2 * pFxchMan->nVars ); |
| Vec_IntForEachEntry( pFxchMan->vLitCount, Count, Lit ) |
| Vec_IntGrow( Vec_WecEntry( pFxchMan->vLits, Lit ), Count ); |
| |
| /* Maps Literals into cubes which uses them */ |
| Vec_WecForEachLevel( pFxchMan->vCubes, vCube, i ) |
| Vec_IntForEachEntryStart( vCube, Lit, k, 1 ) |
| Vec_WecPush( pFxchMan->vLits, Lit, i ); |
| } |
| |
| void Fxch_ManGenerateLitHashKeys( Fxch_Man_t* pFxchMan ) |
| { |
| int i; |
| /* Generates the random number which will be used for hashing cubes */ |
| Gia_ManRandom( 1 ); |
| pFxchMan->vLitHashKeys = Vec_IntAlloc( ( 2 * pFxchMan->nVars ) ); |
| for ( i = 0; i < (2 * pFxchMan->nVars); i++ ) |
| Vec_IntPush( pFxchMan->vLitHashKeys, Gia_ManRandom(0) & 0x3FFFFFF ); |
| } |
| |
| void Fxch_ManSCHashTablesInit( Fxch_Man_t* pFxchMan ) |
| { |
| Vec_Wec_t* vCubes = pFxchMan->vCubes; |
| Vec_Int_t* vCube; |
| int iCube, |
| nTotalHashed = 0; |
| |
| Vec_WecForEachLevel( vCubes, vCube, iCube ) |
| { |
| int nLits = Vec_IntSize( vCube ) - 1, |
| nSubCubes = nLits <= 2? nLits + 1: ( nLits * nLits + nLits ) / 2; |
| |
| nTotalHashed += nSubCubes + 1; |
| } |
| |
| pFxchMan->pSCHashTable = Fxch_SCHashTableCreate( pFxchMan, nTotalHashed ); |
| } |
| |
| void Fxch_ManSCHashTablesFree( Fxch_Man_t* pFxchMan ) |
| { |
| Fxch_SCHashTableDelete( pFxchMan->pSCHashTable ); |
| } |
| |
| void Fxch_ManDivCreate( Fxch_Man_t* pFxchMan ) |
| { |
| Vec_Int_t* vCube; |
| float Weight; |
| int fAdd = 1, |
| fUpdate = 0, |
| iCube; |
| |
| Vec_WecForEachLevel( pFxchMan->vCubes, vCube, iCube ) |
| { |
| Fxch_ManDivSingleCube( pFxchMan, iCube, fAdd, fUpdate ); |
| Fxch_ManDivDoubleCube( pFxchMan, iCube, fAdd, fUpdate ); |
| } |
| |
| pFxchMan->vDivPrio = Vec_QueAlloc( Vec_FltSize( pFxchMan->vDivWeights ) ); |
| Vec_QueSetPriority( pFxchMan->vDivPrio, Vec_FltArrayP( pFxchMan->vDivWeights ) ); |
| Vec_FltForEachEntry( pFxchMan->vDivWeights, Weight, iCube ) |
| { |
| if ( Weight > 0.0 ) |
| Vec_QuePush( pFxchMan->vDivPrio, iCube ); |
| } |
| } |
| |
| /* Level Computation */ |
| int Fxch_ManComputeLevelDiv( Fxch_Man_t* pFxchMan, |
| Vec_Int_t* vCubeFree ) |
| { |
| int i, |
| Lit, |
| Level = 0; |
| |
| Vec_IntForEachEntry( vCubeFree, Lit, i ) |
| Level = Abc_MaxInt( Level, Vec_IntEntry( pFxchMan->vLevels, Abc_Lit2Var( Abc_Lit2Var( Lit ) ) ) ); |
| |
| return Abc_MinInt( Level, 800 ); |
| } |
| |
| int Fxch_ManComputeLevelCube( Fxch_Man_t* pFxchMan, |
| Vec_Int_t * vCube ) |
| { |
| int k, |
| Lit, |
| Level = 0; |
| |
| Vec_IntForEachEntryStart( vCube, Lit, k, 1 ) |
| Level = Abc_MaxInt( Level, Vec_IntEntry( pFxchMan->vLevels, Abc_Lit2Var( Lit ) ) ); |
| |
| return Level; |
| } |
| |
| void Fxch_ManComputeLevel( Fxch_Man_t* pFxchMan ) |
| { |
| Vec_Int_t* vCube; |
| int i, |
| iVar, |
| iFirst = 0; |
| |
| iVar = Vec_IntEntry( Vec_WecEntry( pFxchMan->vCubes, 0 ), 0 ); |
| pFxchMan->vLevels = Vec_IntStart( pFxchMan->nVars ); |
| |
| Vec_WecForEachLevel( pFxchMan->vCubes, vCube, i ) |
| { |
| if ( iVar != Vec_IntEntry( vCube, 0 ) ) |
| { |
| Vec_IntAddToEntry( pFxchMan->vLevels, iVar, i - iFirst ); |
| iVar = Vec_IntEntry( vCube, 0 ); |
| iFirst = i; |
| } |
| Vec_IntUpdateEntry( pFxchMan->vLevels, iVar, Fxch_ManComputeLevelCube( pFxchMan, vCube ) ); |
| } |
| } |
| |
| /* Extract divisor from single-cubes */ |
| static inline void Fxch_ManExtractDivFromCube( Fxch_Man_t* pFxchMan, |
| const int Lit0, |
| const int Lit1, |
| const int iVarNew ) |
| { |
| int i, iCube0; |
| Vec_Int_t* vLitP = Vec_WecEntry( pFxchMan->vLits, Vec_WecSize( pFxchMan->vLits ) - 2 ); |
| |
| Vec_IntForEachEntry( pFxchMan->vCubesS, iCube0, i ) |
| { |
| int RetValue; |
| Vec_Int_t* vCube0; |
| |
| vCube0 = Fxch_ManGetCube( pFxchMan, iCube0 ); |
| RetValue = Vec_IntRemove1( vCube0, Abc_LitNot( Lit0 ) ); |
| RetValue += Vec_IntRemove1( vCube0, Abc_LitNot( Lit1 ) ); |
| assert( RetValue == 2 ); |
| |
| Vec_IntPush( vCube0, Abc_Var2Lit( iVarNew, 0 ) ); |
| Vec_IntPush( vLitP, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); |
| Vec_IntPush( pFxchMan->vCubesToUpdate, iCube0 ); |
| |
| pFxchMan->nLits--; |
| } |
| } |
| |
| /* Extract divisor from cube pairs */ |
| static inline void Fxch_ManExtractDivFromCubePairs( Fxch_Man_t* pFxchMan, |
| const int iVarNew ) |
| { |
| /* For each pair (Ci, Cj) */ |
| int iCube0, iCube1, i; |
| |
| |
| Vec_IntForEachEntryDouble( pFxchMan->vPairs, iCube0, iCube1, i ) |
| { |
| int j, Lit, |
| RetValue, |
| fCompl = 0; |
| int * pOutputID0, * pOutputID1; |
| |
| Vec_Int_t* vCube = NULL, |
| * vCube0 = Fxch_ManGetCube( pFxchMan, iCube0 ), |
| * vCube1 = Fxch_ManGetCube( pFxchMan, iCube1 ), |
| * vCube0Copy = Vec_IntDup( vCube0 ), |
| * vCube1Copy = Vec_IntDup( vCube1 ); |
| |
| RetValue = Fxch_DivRemoveLits( vCube0Copy, vCube1Copy, pFxchMan->vDiv, &fCompl ); |
| |
| assert( RetValue == Vec_IntSize( pFxchMan->vDiv ) ); |
| |
| pFxchMan->nLits -= Vec_IntSize( pFxchMan->vDiv ) + Vec_IntSize( vCube1 ) - 2; |
| |
| /* Identify type of Extraction */ |
| pOutputID0 = Vec_IntEntryP( pFxchMan->vOutputID, iCube0 * pFxchMan->nSizeOutputID ); |
| pOutputID1 = Vec_IntEntryP( pFxchMan->vOutputID, iCube1 * pFxchMan->nSizeOutputID ); |
| RetValue = 1; |
| for ( j = 0; j < pFxchMan->nSizeOutputID && RetValue; j++ ) |
| RetValue = ( pOutputID0[j] == pOutputID1[j] ); |
| |
| /* Exact Extractraion */ |
| if ( RetValue ) |
| { |
| Vec_IntClear( vCube0 ); |
| Vec_IntAppend( vCube0, vCube0Copy ); |
| vCube = vCube0; |
| |
| Vec_IntPush( pFxchMan->vCubesToUpdate, iCube0 ); |
| Vec_IntClear( vCube1 ); |
| |
| /* Update Lit -> Cube mapping */ |
| Vec_IntForEachEntry( pFxchMan->vDiv, Lit, j ) |
| { |
| Vec_IntRemove( Vec_WecEntry( pFxchMan->vLits, Abc_Lit2Var( Lit ) ), |
| Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); |
| Vec_IntRemove( Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Abc_Lit2Var( Lit ) ) ), |
| Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); |
| } |
| |
| } |
| /* Unexact Extraction */ |
| else |
| { |
| for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) |
| pFxchMan->pTempOutputID[j] = ( pOutputID0[j] & pOutputID1[j] ); |
| |
| /* Create new cube */ |
| vCube = Vec_WecPushLevel( pFxchMan->vCubes ); |
| Vec_IntAppend( vCube, vCube0Copy ); |
| Vec_IntPushArray( pFxchMan->vOutputID, pFxchMan->pTempOutputID, pFxchMan->nSizeOutputID ); |
| Vec_IntPush( pFxchMan->vCubesToUpdate, Vec_WecLevelId( pFxchMan->vCubes, vCube ) ); |
| |
| /* Update Lit -> Cube mapping */ |
| Vec_IntForEachEntryStart( vCube, Lit, j, 1 ) |
| Vec_WecPush( pFxchMan->vLits, Lit, Vec_WecLevelId( pFxchMan->vCubes, vCube ) ); |
| |
| /*********************************************************/ |
| RetValue = 0; |
| for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) |
| { |
| pFxchMan->pTempOutputID[j] = pOutputID0[j]; |
| RetValue |= ( pOutputID0[j] & ~( pOutputID1[j] ) ); |
| pOutputID0[j] &= ~( pOutputID1[j] ); |
| } |
| |
| if ( RetValue != 0 ) |
| Vec_IntPush( pFxchMan->vCubesToUpdate, iCube0 ); |
| else |
| Vec_IntClear( vCube0 ); |
| |
| /*********************************************************/ |
| RetValue = 0; |
| for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) |
| { |
| RetValue |= ( pOutputID1[j] & ~( pFxchMan->pTempOutputID[j] ) ); |
| pOutputID1[j] &= ~( pFxchMan->pTempOutputID[j] ); |
| } |
| |
| if ( RetValue != 0 ) |
| Vec_IntPush( pFxchMan->vCubesToUpdate, iCube1 ); |
| else |
| Vec_IntClear( vCube1 ); |
| |
| } |
| Vec_IntFree( vCube0Copy ); |
| Vec_IntFree( vCube1Copy ); |
| |
| if ( iVarNew ) |
| { |
| Vec_Int_t* vLitP = Vec_WecEntry( pFxchMan->vLits, Vec_WecSize( pFxchMan->vLits ) - 2 ), |
| * vLitN = Vec_WecEntry( pFxchMan->vLits, Vec_WecSize( pFxchMan->vLits ) - 1 ); |
| |
| assert( vCube ); |
| if ( Vec_IntSize( pFxchMan->vDiv ) == 2 || fCompl ) |
| { |
| Vec_IntPush( vCube, Abc_Var2Lit( iVarNew, 1 ) ); |
| Vec_IntPush( vLitN, Vec_WecLevelId( pFxchMan->vCubes, vCube ) ); |
| Vec_IntSort( vLitN, 0 ); |
| } |
| else |
| { |
| Vec_IntPush( vCube, Abc_Var2Lit( iVarNew, 0 ) ); |
| Vec_IntPush( vLitP, Vec_WecLevelId( pFxchMan->vCubes, vCube ) ); |
| Vec_IntSort( vLitP, 0 ); |
| } |
| } |
| } |
| |
| return; |
| } |
| |
| static inline int Fxch_ManCreateCube( Fxch_Man_t* pFxchMan, |
| int Lit0, |
| int Lit1 ) |
| { |
| int Level, |
| iVarNew, |
| j; |
| Vec_Int_t* vCube0, |
| * vCube1; |
| |
| /* Create a new variable */ |
| iVarNew = pFxchMan->nVars; |
| pFxchMan->nVars++; |
| |
| /* Clear temporary outputID vector */ |
| for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) |
| pFxchMan->pTempOutputID[j] = 0; |
| |
| /* Create new Lit hash keys */ |
| Vec_IntPush( pFxchMan->vLitHashKeys, Gia_ManRandom(0) & 0x3FFFFFF ); |
| Vec_IntPush( pFxchMan->vLitHashKeys, Gia_ManRandom(0) & 0x3FFFFFF ); |
| |
| /* Create new Cube */ |
| vCube0 = Vec_WecPushLevel( pFxchMan->vCubes ); |
| Vec_IntPush( vCube0, iVarNew ); |
| Vec_IntPushArray( pFxchMan->vOutputID, pFxchMan->pTempOutputID, pFxchMan->nSizeOutputID ); |
| |
| if ( Vec_IntSize( pFxchMan->vDiv ) == 2 ) |
| { |
| if ( Lit0 > Lit1 ) |
| ABC_SWAP(int, Lit0, Lit1); |
| |
| Vec_IntPush( vCube0, Abc_LitNot( Lit0 ) ); |
| Vec_IntPush( vCube0, Abc_LitNot( Lit1 ) ); |
| Level = 1 + Fxch_ManComputeLevelCube( pFxchMan, vCube0 ); |
| } |
| else |
| { |
| int i; |
| int Lit; |
| |
| vCube1 = Vec_WecPushLevel( pFxchMan->vCubes ); |
| Vec_IntPush( vCube1, iVarNew ); |
| Vec_IntPushArray( pFxchMan->vOutputID, pFxchMan->pTempOutputID, pFxchMan->nSizeOutputID ); |
| |
| vCube0 = Fxch_ManGetCube( pFxchMan, Vec_WecSize( pFxchMan->vCubes ) - 2 ); |
| Fxch_DivSepareteCubes( pFxchMan->vDiv, vCube0, vCube1 ); |
| Level = 2 + Abc_MaxInt( Fxch_ManComputeLevelCube( pFxchMan, vCube0 ), |
| Fxch_ManComputeLevelCube( pFxchMan, vCube1 ) ); |
| |
| Vec_IntPush( pFxchMan->vCubesToUpdate, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); |
| Vec_IntPush( pFxchMan->vCubesToUpdate, Vec_WecLevelId( pFxchMan->vCubes, vCube1 ) ); |
| |
| /* Update Lit -> Cube mapping */ |
| Vec_IntForEachEntryStart( vCube0, Lit, i, 1 ) |
| Vec_WecPush( pFxchMan->vLits, Lit, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); |
| |
| Vec_IntForEachEntryStart( vCube1, Lit, i, 1 ) |
| Vec_WecPush( pFxchMan->vLits, Lit, Vec_WecLevelId( pFxchMan->vCubes, vCube1 ) ); |
| } |
| assert( Vec_IntSize( pFxchMan->vLevels ) == iVarNew ); |
| Vec_IntPush( pFxchMan->vLevels, Level ); |
| |
| pFxchMan->nLits += Vec_IntSize( pFxchMan->vDiv ); |
| |
| /* Create new literals */ |
| Vec_WecPushLevel( pFxchMan->vLits ); |
| Vec_WecPushLevel( pFxchMan->vLits ); |
| |
| return iVarNew; |
| } |
| |
| void Fxch_ManUpdate( Fxch_Man_t* pFxchMan, |
| int iDiv ) |
| { |
| int i, iCube0, iCube1, |
| Lit0 = -1, |
| Lit1 = -1, |
| iVarNew; |
| |
| Vec_Int_t* vCube0, |
| * vCube1, |
| * vDivCubePairs; |
| |
| /* Get the selected candidate (divisor) */ |
| Vec_IntClear( pFxchMan->vDiv ); |
| Vec_IntAppend( pFxchMan->vDiv, Hsh_VecReadEntry( pFxchMan->pDivHash, iDiv ) ); |
| |
| /* Find cubes associated with the divisor */ |
| Vec_IntClear( pFxchMan->vCubesS ); |
| if ( Vec_IntSize( pFxchMan->vDiv ) == 2 ) |
| { |
| Lit0 = Abc_Lit2Var( Vec_IntEntry( pFxchMan->vDiv, 0 ) ); |
| Lit1 = Abc_Lit2Var( Vec_IntEntry( pFxchMan->vDiv, 1 ) ); |
| assert( Lit0 >= 0 && Lit1 >= 0 ); |
| |
| Fxch_ManCompressCubes( pFxchMan->vCubes, Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Lit0 ) ) ); |
| Fxch_ManCompressCubes( pFxchMan->vCubes, Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Lit1 ) ) ); |
| Vec_IntTwoRemoveCommon( Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Lit0 ) ), |
| Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Lit1 ) ), |
| pFxchMan->vCubesS ); |
| } |
| |
| /* Find pairs associated with the divisor */ |
| Vec_IntClear( pFxchMan->vPairs ); |
| vDivCubePairs = Vec_WecEntry( pFxchMan->vDivCubePairs, iDiv ); |
| Vec_IntAppend( pFxchMan->vPairs, vDivCubePairs ); |
| Vec_IntErase( vDivCubePairs ); |
| |
| Vec_IntForEachEntryDouble( pFxchMan->vPairs, iCube0, iCube1, i ) |
| { |
| assert( Fxch_ManGetLit( pFxchMan, iCube0, 0) == Fxch_ManGetLit( pFxchMan, iCube1, 0) ); |
| if (iCube0 > iCube1) |
| { |
| Vec_IntSetEntry( pFxchMan->vPairs, i, iCube1); |
| Vec_IntSetEntry( pFxchMan->vPairs, i+1, iCube0); |
| } |
| } |
| |
| Vec_IntUniqifyPairs( pFxchMan->vPairs ); |
| assert( Vec_IntSize( pFxchMan->vPairs ) % 2 == 0 ); |
| |
| /* subtract cost of single-cube divisors */ |
| Vec_IntForEachEntry( pFxchMan->vCubesS, iCube0, i ) |
| { |
| Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1); |
| |
| if ( Vec_WecEntryEntry( pFxchMan->vCubes, iCube0, 0 ) == 0 ) |
| Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 ); |
| } |
| |
| Vec_IntForEachEntry( pFxchMan->vPairs, iCube0, i ) |
| { |
| Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1); |
| |
| if ( Vec_WecEntryEntry( pFxchMan->vCubes, iCube0, 0 ) == 0 ) |
| Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 ); |
| } |
| |
| Vec_IntClear( pFxchMan->vCubesToUpdate ); |
| if ( Fxch_DivIsNotConstant1( pFxchMan->vDiv ) ) |
| { |
| iVarNew = Fxch_ManCreateCube( pFxchMan, Lit0, Lit1 ); |
| Fxch_ManExtractDivFromCube( pFxchMan, Lit0, Lit1, iVarNew ); |
| Fxch_ManExtractDivFromCubePairs( pFxchMan, iVarNew ); |
| } |
| else |
| Fxch_ManExtractDivFromCubePairs( pFxchMan, 0 ); |
| |
| assert( Vec_IntSize( pFxchMan->vCubesToUpdate ) ); |
| |
| /* Add cost */ |
| Vec_IntForEachEntry( pFxchMan->vCubesToUpdate, iCube0, i ) |
| { |
| Fxch_ManDivSingleCube( pFxchMan, iCube0, 1, 1 ); |
| |
| if ( Vec_WecEntryEntry( pFxchMan->vCubes, iCube0, 0 ) == 0 ) |
| Fxch_ManDivDoubleCube( pFxchMan, iCube0, 1, 1 ); |
| } |
| |
| /* Deal with SCC */ |
| if ( Vec_IntSize( pFxchMan->vSCC ) ) |
| { |
| Vec_IntUniqifyPairs( pFxchMan->vSCC ); |
| assert( Vec_IntSize( pFxchMan->vSCC ) % 2 == 0 ); |
| |
| Vec_IntForEachEntryDouble( pFxchMan->vSCC, iCube0, iCube1, i ) |
| { |
| int j, RetValue = 1; |
| int* pOutputID0 = Vec_IntEntryP( pFxchMan->vOutputID, iCube0 * pFxchMan->nSizeOutputID ); |
| int* pOutputID1 = Vec_IntEntryP( pFxchMan->vOutputID, iCube1 * pFxchMan->nSizeOutputID ); |
| vCube0 = Vec_WecEntry( pFxchMan->vCubes, iCube0 ); |
| vCube1 = Vec_WecEntry( pFxchMan->vCubes, iCube1 ); |
| |
| if ( !Vec_WecIntHasMark( vCube0 ) ) |
| { |
| Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1 ); |
| Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 ); |
| Vec_WecIntSetMark( vCube0 ); |
| } |
| |
| if ( !Vec_WecIntHasMark( vCube1 ) ) |
| { |
| Fxch_ManDivSingleCube( pFxchMan, iCube1, 0, 1 ); |
| Fxch_ManDivDoubleCube( pFxchMan, iCube1, 0, 1 ); |
| Vec_WecIntSetMark( vCube1 ); |
| } |
| |
| if ( Vec_IntSize( vCube0 ) == Vec_IntSize( vCube1 ) ) |
| { |
| for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) |
| { |
| pOutputID1[j] |= pOutputID0[j]; |
| pOutputID0[j] = 0; |
| } |
| Vec_IntClear( Vec_WecEntry( pFxchMan->vCubes, iCube0 ) ); |
| Vec_WecIntXorMark( vCube0 ); |
| continue; |
| } |
| |
| for ( j = 0; j < pFxchMan->nSizeOutputID && RetValue; j++ ) |
| RetValue = ( pOutputID0[j] == pOutputID1[j] ); |
| |
| if ( RetValue ) |
| { |
| Vec_IntClear( Vec_WecEntry( pFxchMan->vCubes, iCube0 ) ); |
| Vec_WecIntXorMark( vCube0 ); |
| } |
| else |
| { |
| RetValue = 0; |
| for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) |
| { |
| RetValue |= ( pOutputID0[j] & ~( pOutputID1[j] ) ); |
| pOutputID0[j] &= ~( pOutputID1[j] ); |
| } |
| |
| if ( RetValue == 0 ) |
| { |
| Vec_IntClear( Vec_WecEntry( pFxchMan->vCubes, iCube0 ) ); |
| Vec_WecIntXorMark( vCube0 ); |
| } |
| } |
| } |
| |
| Vec_IntForEachEntryDouble( pFxchMan->vSCC, iCube0, iCube1, i ) |
| { |
| vCube0 = Vec_WecEntry( pFxchMan->vCubes, iCube0 ); |
| vCube1 = Vec_WecEntry( pFxchMan->vCubes, iCube1 ); |
| |
| if ( Vec_WecIntHasMark( vCube0 ) ) |
| { |
| Fxch_ManDivSingleCube( pFxchMan, iCube0, 1, 1 ); |
| Fxch_ManDivDoubleCube( pFxchMan, iCube0, 1, 1 ); |
| Vec_WecIntXorMark( vCube0 ); |
| } |
| |
| if ( Vec_WecIntHasMark( vCube1 ) ) |
| { |
| Fxch_ManDivSingleCube( pFxchMan, iCube1, 1, 1 ); |
| Fxch_ManDivDoubleCube( pFxchMan, iCube1, 1, 1 ); |
| Vec_WecIntXorMark( vCube1 ); |
| } |
| } |
| |
| Vec_IntClear( pFxchMan->vSCC ); |
| } |
| |
| pFxchMan->nExtDivs++; |
| } |
| |
| /* Print */ |
| void Fxch_ManPrintDivs( Fxch_Man_t* pFxchMan ) |
| { |
| int iDiv; |
| |
| for ( iDiv = 0; iDiv < Vec_FltSize( pFxchMan->vDivWeights ); iDiv++ ) |
| Fxch_DivPrint( pFxchMan, iDiv ); |
| } |
| |
| void Fxch_ManPrintStats( Fxch_Man_t* pFxchMan ) |
| { |
| printf( "Cubes =%8d ", Vec_WecSizeUsed( pFxchMan->vCubes ) ); |
| printf( "Lits =%8d ", Vec_WecSizeUsed( pFxchMan->vLits ) ); |
| printf( "Divs =%8d ", Hsh_VecSize( pFxchMan->pDivHash ) ); |
| printf( "Divs+ =%8d ", Vec_QueSize( pFxchMan->vDivPrio ) ); |
| printf( "Extr =%7d \n", pFxchMan->nExtDivs ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| ABC_NAMESPACE_IMPL_END |