| /**CFile**************************************************************** |
| |
| FileName [ioReadPlaMo.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Command processing package.] |
| |
| Synopsis [Procedure to read network from file.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: ioReadPlaMo.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "ioAbc.h" |
| #include "misc/util/utilTruth.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| typedef struct Mop_Man_t_ Mop_Man_t; |
| struct Mop_Man_t_ |
| { |
| int nIns; |
| int nOuts; |
| int nWordsIn; |
| int nWordsOut; |
| Vec_Wrd_t * vWordsIn; |
| Vec_Wrd_t * vWordsOut; |
| Vec_Int_t * vCubes; |
| Vec_Int_t * vFree; |
| }; |
| |
| static inline int Mop_ManIsSopSymb( char c ) { return c == '0' || c == '1' || c == '-'; } |
| static inline int Mop_ManIsSpace( char c ) { return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; } |
| |
| static inline word * Mop_ManCubeIn( Mop_Man_t * p, int i ) { return Vec_WrdEntryP(p->vWordsIn, p->nWordsIn * i); } |
| static inline word * Mop_ManCubeOut( Mop_Man_t * p, int i ) { return Vec_WrdEntryP(p->vWordsOut, p->nWordsOut * i); } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Mop_Man_t * Mop_ManAlloc( int nIns, int nOuts, int nCubes ) |
| { |
| Mop_Man_t * p = ABC_CALLOC( Mop_Man_t, 1 ); |
| p->nIns = nIns; |
| p->nOuts = nOuts; |
| p->nWordsIn = Abc_Bit6WordNum( 2 * nIns ); |
| p->nWordsOut = Abc_Bit6WordNum( nOuts ); |
| p->vWordsIn = Vec_WrdStart( 2 * p->nWordsIn * nCubes ); |
| p->vWordsOut = Vec_WrdStart( 2 * p->nWordsOut * nCubes ); |
| p->vCubes = Vec_IntAlloc( 2 * nCubes ); |
| p->vFree = Vec_IntAlloc( 2 * nCubes ); |
| return p; |
| } |
| void Mop_ManStop( Mop_Man_t * p ) |
| { |
| Vec_WrdFree( p->vWordsIn ); |
| Vec_WrdFree( p->vWordsOut ); |
| Vec_IntFree( p->vCubes ); |
| Vec_IntFree( p->vFree ); |
| ABC_FREE( p ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Reads the file into a character buffer.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| char * Mop_ManLoadFile( char * pFileName ) |
| { |
| FILE * pFile; |
| int nFileSize, RetValue; |
| char * pContents; |
| pFile = fopen( pFileName, "rb" ); |
| if ( pFile == NULL ) |
| { |
| Abc_Print( -1, "Mop_ManLoadFile(): The file is unavailable (absent or open).\n" ); |
| return NULL; |
| } |
| fseek( pFile, 0, SEEK_END ); |
| nFileSize = ftell( pFile ); |
| if ( nFileSize == 0 ) |
| { |
| Abc_Print( -1, "Mop_ManLoadFile(): The file is empty.\n" ); |
| return NULL; |
| } |
| pContents = ABC_ALLOC( char, nFileSize + 10 ); |
| rewind( pFile ); |
| RetValue = fread( pContents, nFileSize, 1, pFile ); |
| fclose( pFile ); |
| strcpy( pContents + nFileSize, "\n" ); |
| return pContents; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Mop_ManReadParams( char * pBuffer, int * pnIns, int * pnOuts ) |
| { |
| char * pIns = strstr( pBuffer, ".i " ); |
| char * pOuts = strstr( pBuffer, ".o " ); |
| char * pStr = pBuffer; int nCubes = 0; |
| if ( pIns == NULL || pOuts == NULL ) |
| return -1; |
| *pnIns = atoi( pIns + 2 ); |
| *pnOuts = atoi( pOuts + 2 ); |
| while ( *pStr ) |
| nCubes += (*pStr++ == '\n'); |
| return nCubes; |
| } |
| Mop_Man_t * Mop_ManRead( char * pFileName ) |
| { |
| Mop_Man_t * p; |
| int nIns, nOuts, nCubes, iCube; |
| char * pToken, * pBuffer = Mop_ManLoadFile( pFileName ); |
| if ( pBuffer == NULL ) |
| return NULL; |
| nCubes = Mop_ManReadParams( pBuffer, &nIns, &nOuts ); |
| if ( nCubes == -1 ) |
| return NULL; |
| p = Mop_ManAlloc( nIns, nOuts, nCubes ); |
| // get the first cube |
| pToken = strtok( pBuffer, "\n" ); |
| while ( pToken ) |
| { |
| while ( Mop_ManIsSpace(*pToken) ) |
| pToken++; |
| if ( Mop_ManIsSopSymb(*pToken) ) |
| break; |
| pToken = strtok( NULL, "\n" ); |
| } |
| // read cubes |
| for ( iCube = 0; pToken && Mop_ManIsSopSymb(*pToken); iCube++ ) |
| { |
| char * pTokenCopy = pToken; |
| int i, o, nVars[2] = {nIns, nOuts}; |
| word * pCube[2] = { Mop_ManCubeIn(p, iCube), Mop_ManCubeOut(p, iCube) }; |
| for ( o = 0; o < 2; o++ ) |
| { |
| while ( Mop_ManIsSpace(*pToken) ) |
| pToken++; |
| for ( i = 0; i < nVars[o]; i++, pToken++ ) |
| { |
| if ( !Mop_ManIsSopSymb(*pToken) ) |
| { |
| printf( "Cannot read cube %d (%s).\n", iCube+1, pTokenCopy ); |
| ABC_FREE( pBuffer ); |
| Mop_ManStop( p ); |
| return NULL; |
| } |
| if ( o == 1 ) |
| { |
| if ( *pToken == '1' ) |
| Abc_TtSetBit( pCube[o], i ); |
| } |
| else if ( *pToken == '0' ) |
| Abc_TtSetBit( pCube[o], 2*i ); |
| else if ( *pToken == '1' ) |
| Abc_TtSetBit( pCube[o], 2*i+1 ); |
| } |
| } |
| assert( iCube < nCubes ); |
| Vec_IntPush( p->vCubes, iCube ); |
| pToken = strtok( NULL, "\n" ); |
| } |
| for ( ; iCube < 2 * nCubes; iCube++ ) |
| Vec_IntPush( p->vFree, iCube ); |
| ABC_FREE( pBuffer ); |
| return p; |
| } |
| void Mop_ManPrintOne( Mop_Man_t * p, int iCube ) |
| { |
| int k; |
| char Symb[4] = { '-', '0', '1', '?' }; |
| word * pCubeIn = Mop_ManCubeIn( p, iCube ); |
| word * pCubeOut = Mop_ManCubeOut( p, iCube ); |
| for ( k = 0; k < p->nIns; k++ ) |
| printf( "%c", Symb[Abc_TtGetQua(pCubeIn, k)] ); |
| printf( " " ); |
| for ( k = 0; k < p->nOuts; k++ ) |
| printf( "%d", Abc_TtGetBit(pCubeOut, k) ); |
| printf( "\n" ); |
| } |
| void Mop_ManPrint( Mop_Man_t * p ) |
| { |
| int i, iCube; |
| printf( ".%d\n", p->nIns ); |
| printf( ".%d\n", p->nOuts ); |
| Vec_IntForEachEntry( p->vCubes, iCube, i ) |
| Mop_ManPrintOne( p, iCube ); |
| printf( ".e\n" ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline int Mop_ManCountOnes( word * pCube, int nWords ) |
| { |
| int w, Count = 0; |
| for ( w = 0; w < nWords; w++ ) |
| Count += Abc_TtCountOnes( pCube[w] ); |
| return Count; |
| } |
| static inline int Mop_ManCountOutputLits( Mop_Man_t * p ) |
| { |
| int i, iCube, nOutLits = 0; |
| Vec_IntForEachEntry( p->vCubes, iCube, i ) |
| nOutLits += Mop_ManCountOnes( Mop_ManCubeOut(p, iCube), p->nWordsOut ); |
| return nOutLits; |
| } |
| static inline Vec_Wec_t * Mop_ManCreateGroups( Mop_Man_t * p ) |
| { |
| int i, iCube; |
| Vec_Wec_t * vGroups = Vec_WecStart( p->nIns ); |
| Vec_IntForEachEntry( p->vCubes, iCube, i ) |
| Vec_WecPush( vGroups, Mop_ManCountOnes(Mop_ManCubeIn(p, iCube), p->nWordsIn), iCube ); |
| return vGroups; |
| } |
| static inline int Mop_ManUnCreateGroups( Mop_Man_t * p, Vec_Wec_t * vGroups ) |
| { |
| int i, c1, iCube1; |
| int nBefore = Vec_IntSize(p->vCubes); |
| Vec_Int_t * vGroup; |
| Vec_IntClear( p->vCubes ); |
| Vec_WecForEachLevel( vGroups, vGroup, i ) |
| Vec_IntForEachEntry( vGroup, iCube1, c1 ) |
| if ( iCube1 != -1 ) |
| Vec_IntPush( p->vCubes, iCube1 ); |
| return nBefore - Vec_IntSize(p->vCubes); |
| } |
| static inline int Mop_ManCheckContain( word * pBig, word * pSmall, int nWords ) |
| { |
| int w; |
| for ( w = 0; w < nWords; w++ ) |
| if ( pSmall[w] != (pSmall[w] & pBig[w]) ) |
| return 0; |
| return 1; |
| } |
| static inline void Mop_ManRemoveEmpty( Mop_Man_t * p ) |
| { |
| int w, i, k = 0, iCube; |
| Vec_IntForEachEntry( p->vCubes, iCube, i ) |
| { |
| word * pCube = Mop_ManCubeOut( p, iCube ); |
| for ( w = 0; w < p->nWordsOut; w++ ) |
| if ( pCube[w] ) |
| break; |
| if ( w < p->nWordsOut ) |
| Vec_IntWriteEntry( p->vCubes, k++, iCube ); |
| } |
| Vec_IntShrink( p->vCubes, k ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Count how many times each variable appears in the input parts.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Int_t * Mop_ManCollectStats( Mop_Man_t * p ) |
| { |
| int i, v, iCube, nVars = 32 * p->nWordsIn; |
| Vec_Int_t * vStats = Vec_IntStart( nVars ); |
| Vec_IntForEachEntry( p->vCubes, iCube, i ) |
| { |
| word * pCube = Mop_ManCubeIn(p, iCube); |
| int nOutLits = Mop_ManCountOnes( Mop_ManCubeOut(p, iCube), p->nWordsOut ); |
| for ( v = 0; v < nVars; v++ ) |
| if ( Abc_TtGetQua(pCube, v) ) |
| Vec_IntAddToEntry( vStats, v, nOutLits ); |
| } |
| return vStats; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| // knowing that cubes are distance-1, find the different input variable |
| static inline int Mop_ManFindDiffVar( word * pCube1, word * pCube2, int nWords ) |
| { |
| int w, i; |
| for ( w = 0; w < nWords; w++ ) |
| { |
| word Xor = pCube1[w] ^ pCube2[w]; |
| for ( i = 0; i < 32; i++ ) |
| if ( (Xor >> (i << 1)) & 0x3 ) |
| return w * 32 + i; |
| } |
| assert( 0 ); |
| return -1; |
| } |
| // check containment of input parts of two cubes |
| static inline int Mop_ManCheckDist1( word * pCube1, word * pCube2, int nWords ) |
| { |
| int w, fFound1 = 0; |
| for ( w = 0; w < nWords; w++ ) |
| { |
| word Xor = pCube1[w] ^ pCube2[w]; |
| if ( Xor == 0 ) // equal |
| continue; |
| if ( (Xor ^ (Xor >> 1)) & ABC_CONST(0x5555555555555555) ) // not pairs |
| return 0; |
| Xor &= (Xor >> 1) & ABC_CONST(0x5555555555555555); |
| if ( Xor == 0 ) // not equal and not distance-1 |
| return 0; |
| if ( fFound1 ) // distance-2 or more |
| return 0; |
| if ( (Xor & (Xor-1)) ) // distance-2 or more |
| return 0; |
| fFound1 = 1; // distance 1 so far |
| } |
| return fFound1; |
| } |
| // compresses cubes in the group |
| static inline void Map_ManGroupCompact( Vec_Int_t * vGroup ) |
| { |
| int i, Entry, k = 0; |
| Vec_IntForEachEntry( vGroup, Entry, i ) |
| if ( Entry != -1 ) |
| Vec_IntWriteEntry( vGroup, k++, Entry ); |
| Vec_IntShrink( vGroup, k ); |
| } |
| // takes cubes with identical literal count and removes duplicates |
| int Mop_ManRemoveIdentical( Mop_Man_t * p, Vec_Int_t * vGroup ) |
| { |
| int w, c1, c2, iCube1, iCube2, nEqual = 0; |
| Vec_IntForEachEntry( vGroup, iCube1, c1 ) |
| if ( iCube1 != -1 ) |
| { |
| word * pCube1Out, * pCube1 = Mop_ManCubeIn( p, iCube1 ); |
| Vec_IntForEachEntryStart( vGroup, iCube2, c2, c1+1 ) |
| if ( iCube2 != -1 ) |
| { |
| word * pCube2Out, * pCube2 = Mop_ManCubeIn( p, iCube2 ); |
| if ( memcmp(pCube1, pCube2, sizeof(word)*p->nWordsIn) ) |
| continue; |
| // merge cubes |
| pCube1Out = Mop_ManCubeOut( p, iCube1 ); |
| pCube2Out = Mop_ManCubeOut( p, iCube2 ); |
| for ( w = 0; w < p->nWordsOut; w++ ) |
| pCube1Out[w] |= pCube2Out[w]; |
| Vec_IntWriteEntry( vGroup, c2, -1 ); |
| Vec_IntPush( p->vFree, iCube2 ); |
| nEqual++; |
| } |
| } |
| if ( nEqual ) |
| Map_ManGroupCompact( vGroup ); |
| return nEqual; |
| } |
| // reduces the set of pairs |
| Vec_Int_t * Mop_ManCompatiblePairs( Vec_Int_t * vPairs, int nObjs ) |
| { |
| int i, Entry, Entry2; |
| Vec_Int_t * vCounts = Vec_IntStart( nObjs ); |
| Vec_Int_t * vPairsNew = Vec_IntAlloc( Vec_IntSize(vPairs) ); |
| Vec_IntForEachEntry( vPairs, Entry, i ) |
| Vec_IntAddToEntry( vCounts, Entry, 1 ); |
| // include pairs which have those that appear only once |
| Vec_IntForEachEntryDouble( vPairs, Entry, Entry2, i ) |
| if ( Vec_IntEntry(vCounts, Entry) == 1 || Vec_IntEntry(vCounts, Entry2) == 1 ) |
| { |
| if ( Vec_IntEntry(vCounts, Entry) == 1 ) |
| Vec_IntPushTwo( vPairsNew, Entry, Entry2 ); |
| else |
| Vec_IntPushTwo( vPairsNew, Entry2, Entry ); |
| Vec_IntWriteEntry( vCounts, Entry, -1 ); |
| Vec_IntWriteEntry( vCounts, Entry2, -1 ); |
| } |
| // add those remaining pairs that are both present |
| Vec_IntForEachEntryDouble( vPairs, Entry, Entry2, i ) |
| if ( Vec_IntEntry(vCounts, Entry) > 0 && Vec_IntEntry(vCounts, Entry2) > 0 ) |
| { |
| Vec_IntPushTwo( vPairsNew, Entry, Entry2 ); |
| Vec_IntWriteEntry( vCounts, Entry, -1 ); |
| Vec_IntWriteEntry( vCounts, Entry2, -1 ); |
| } |
| // add remaining pairs |
| Vec_IntForEachEntryDouble( vPairs, Entry, Entry2, i ) |
| if ( Vec_IntEntry(vCounts, Entry) > 0 || Vec_IntEntry(vCounts, Entry2) > 0 ) |
| { |
| if ( Vec_IntEntry(vCounts, Entry) > 0 ) |
| Vec_IntPushTwo( vPairsNew, Entry, Entry2 ); |
| else |
| Vec_IntPushTwo( vPairsNew, Entry2, Entry ); |
| Vec_IntWriteEntry( vCounts, Entry, -1 ); |
| Vec_IntWriteEntry( vCounts, Entry2, -1 ); |
| } |
| Vec_IntFree( vCounts ); |
| // verify the result |
| if ( 0 ) |
| { |
| Vec_Int_t * vTemp1 = Vec_IntDup( vPairs ); |
| Vec_Int_t * vTemp2 = Vec_IntDup( vPairsNew ); |
| Vec_IntUniqify( vTemp1 ); |
| Vec_IntUniqify( vTemp2 ); |
| assert( Vec_IntEqual( vTemp1, vTemp2 ) ); |
| Vec_IntFree( vTemp1 ); |
| Vec_IntFree( vTemp2 ); |
| } |
| return vPairsNew; |
| } |
| // detects pairs of distance-1 cubes with identical outputs |
| Vec_Int_t * Mop_ManFindDist1Pairs( Mop_Man_t * p, Vec_Int_t * vGroup ) |
| { |
| int c1, c2, iCube1, iCube2; |
| Vec_Int_t * vPairs = Vec_IntAlloc( 100 ); |
| Vec_IntForEachEntry( vGroup, iCube1, c1 ) |
| { |
| word * pCube1Out, * pCube1 = Mop_ManCubeIn( p, iCube1 ); |
| Vec_IntForEachEntryStart( vGroup, iCube2, c2, c1+1 ) |
| { |
| word * pCube2Out, * pCube2 = Mop_ManCubeIn( p, iCube2 ); |
| if ( !Mop_ManCheckDist1(pCube1, pCube2, p->nWordsIn) ) |
| continue; |
| pCube1Out = Mop_ManCubeOut( p, iCube1 ); |
| pCube2Out = Mop_ManCubeOut( p, iCube2 ); |
| if ( !memcmp(pCube1Out, pCube2Out, sizeof(word)*p->nWordsOut) ) |
| Vec_IntPushTwo( vPairs, c1, c2 ); |
| } |
| } |
| return vPairs; |
| } |
| // merge distance-1 with identical output part |
| int Mop_ManMergeDist1Pairs( Mop_Man_t * p, Vec_Int_t * vGroup, Vec_Int_t * vGroupPrev, Vec_Int_t * vStats, int nLimit ) |
| { |
| Vec_Int_t * vPairs = Mop_ManFindDist1Pairs( p, vGroup ); |
| Vec_Int_t * vPairsNew = Mop_ManCompatiblePairs( vPairs, Vec_IntSize(vGroup) ); |
| int nCubes = Vec_IntSize(vGroup) + Vec_IntSize(vGroupPrev); |
| int w, i, c1, c2, iCubeNew, iVar; |
| // move cubes to the previous group |
| word * pCube, * pCube1, * pCube2; |
| Vec_Int_t * vToFree = Vec_IntAlloc( Vec_IntSize(vPairsNew) ); |
| Vec_IntForEachEntryDouble( vPairsNew, c1, c2, i ) |
| { |
| pCube1 = Mop_ManCubeIn( p, Vec_IntEntry(vGroup, c1) ); |
| pCube2 = Mop_ManCubeIn( p, Vec_IntEntry(vGroup, c2) ); |
| assert( Mop_ManCheckDist1(pCube1, pCube2, p->nWordsIn) ); |
| |
| // skip those cubes that have frequently appearing variables |
| iVar = Mop_ManFindDiffVar( pCube1, pCube2, p->nWordsIn ); |
| if ( Vec_IntEntry( vStats, iVar ) > nLimit ) |
| continue; |
| Vec_IntPush( vToFree, c1 ); |
| Vec_IntPush( vToFree, c2 ); |
| |
| iCubeNew = Vec_IntPop( p->vFree ); |
| pCube = Mop_ManCubeIn( p, iCubeNew ); |
| for ( w = 0; w < p->nWordsIn; w++ ) |
| pCube[w] = pCube1[w] & pCube2[w]; |
| |
| pCube = Mop_ManCubeOut( p, iCubeNew ); |
| pCube1 = Mop_ManCubeOut( p, Vec_IntEntry(vGroup, c1) ); |
| pCube2 = Mop_ManCubeOut( p, Vec_IntEntry(vGroup, c2) ); |
| |
| assert( !memcmp(pCube1, pCube2, sizeof(word)*p->nWordsOut) ); |
| for ( w = 0; w < p->nWordsOut; w++ ) |
| pCube[w] = pCube1[w]; |
| |
| Vec_IntPush( vGroupPrev, iCubeNew ); |
| } |
| // Vec_IntForEachEntry( vPairsNew, c1, i ) |
| Vec_IntForEachEntry( vToFree, c1, i ) |
| { |
| if ( Vec_IntEntry(vGroup, c1) == -1 ) |
| continue; |
| Vec_IntPush( p->vFree, Vec_IntEntry(vGroup, c1) ); |
| Vec_IntWriteEntry( vGroup, c1, -1 ); |
| } |
| Vec_IntFree( vToFree ); |
| if ( Vec_IntSize(vPairsNew) > 0 ) |
| Map_ManGroupCompact( vGroup ); |
| Vec_IntFree( vPairs ); |
| Vec_IntFree( vPairsNew ); |
| return nCubes - Vec_IntSize(vGroup) - Vec_IntSize(vGroupPrev); |
| } |
| // merge distance-1 with contained output part |
| int Mop_ManMergeDist1Pairs2( Mop_Man_t * p, Vec_Int_t * vGroup, Vec_Int_t * vGroupPrev ) |
| { |
| int w, c1, c2, iCube1, iCube2, Count = 0; |
| Vec_IntForEachEntry( vGroup, iCube1, c1 ) |
| if ( iCube1 != -1 ) |
| { |
| word * pCube1Out, * pCube1 = Mop_ManCubeIn( p, iCube1 ); |
| Vec_IntForEachEntryStart( vGroup, iCube2, c2, c1+1 ) |
| if ( iCube2 != -1 ) |
| { |
| word * pCube2Out, * pCube2 = Mop_ManCubeIn( p, iCube2 ); |
| if ( !Mop_ManCheckDist1(pCube1, pCube2, p->nWordsIn) ) |
| continue; |
| pCube1Out = Mop_ManCubeOut( p, iCube1 ); |
| pCube2Out = Mop_ManCubeOut( p, iCube2 ); |
| assert( memcmp(pCube1Out, pCube2Out, sizeof(word)*p->nWordsOut) ); |
| if ( Mop_ManCheckContain(pCube1Out, pCube2Out, p->nWordsOut) ) // pCube1 has more outputs |
| { |
| // update the input part |
| for ( w = 0; w < p->nWordsIn; w++ ) |
| pCube2[w] &= pCube1[w]; |
| // sharp the output part |
| for ( w = 0; w < p->nWordsOut; w++ ) |
| pCube1Out[w] &= ~pCube2Out[w]; |
| // move to another group |
| Vec_IntPush( vGroupPrev, iCube2 ); |
| Vec_IntWriteEntry( vGroup, c2, -1 ); |
| Count++; |
| } |
| else if ( Mop_ManCheckContain(pCube2Out, pCube1Out, p->nWordsOut) ) // pCube2 has more outputs |
| { |
| // update the input part |
| for ( w = 0; w < p->nWordsIn; w++ ) |
| pCube1[w] &= pCube2[w]; |
| // sharp the output part |
| for ( w = 0; w < p->nWordsOut; w++ ) |
| pCube2Out[w] &= ~pCube1Out[w]; |
| // move to another group |
| Vec_IntPush( vGroupPrev, iCube1 ); |
| Vec_IntWriteEntry( vGroup, c1, -1 ); |
| Count++; |
| } |
| } |
| } |
| if ( Count ) |
| Map_ManGroupCompact( vGroup ); |
| return Count; |
| } |
| int Mop_ManMergeDist1All( Mop_Man_t * p, Vec_Wec_t * vGroups, Vec_Int_t * vStats, int nLimit ) |
| { |
| Vec_Int_t * vGroup; |
| int i, nEqual, nReduce, Count = 0; |
| Vec_WecForEachLevelReverse( vGroups, vGroup, i ) |
| { |
| if ( Vec_IntSize(vGroup) == 0 ) |
| continue; |
| if ( i == 0 ) |
| { |
| printf( "Detected constant-1 cover.\n" ); |
| fflush( stdout ); |
| return -1; |
| } |
| nEqual = Mop_ManRemoveIdentical( p, vGroup ); |
| nReduce = Mop_ManMergeDist1Pairs( p, vGroup, Vec_WecEntry(vGroups, i-1), vStats, nLimit ); |
| //Mop_ManMergeDist1Pairs2( p, vGroup, Vec_WecEntry(vGroups, i-1) ); |
| Count += nEqual + nReduce; |
| //printf( "Group %3d : Equal =%5d. Reduce =%5d.\n", i, nEqual, nReduce ); |
| } |
| return Count; |
| } |
| // reduce contained cubes |
| int Mop_ManMergeContainTwo( Mop_Man_t * p, Vec_Int_t * vGroup, Vec_Int_t * vGroup2 ) |
| { |
| int w, c1, c2, iCube1, iCube2, Count = 0; |
| Vec_IntForEachEntry( vGroup, iCube1, c1 ) |
| { |
| word * pCube1Out, * pCube1 = Mop_ManCubeIn( p, iCube1 ); |
| Vec_IntForEachEntry( vGroup2, iCube2, c2 ) |
| if ( iCube2 != -1 ) |
| { |
| word * pCube2Out, * pCube2 = Mop_ManCubeIn( p, iCube2 ); |
| if ( !Mop_ManCheckContain(pCube2, pCube1, p->nWordsIn) ) |
| continue; |
| pCube1Out = Mop_ManCubeOut( p, iCube1 ); |
| pCube2Out = Mop_ManCubeOut( p, iCube2 ); |
| for ( w = 0; w < p->nWordsOut; w++ ) |
| pCube2Out[w] &= ~pCube1Out[w]; |
| for ( w = 0; w < p->nWordsOut; w++ ) |
| if ( pCube2Out[w] ) |
| break; |
| if ( w < p->nWordsOut ) // has output literals |
| continue; |
| // remove larger cube |
| Vec_IntWriteEntry( vGroup2, c2, -1 ); |
| Vec_IntPush( p->vFree, iCube2 ); |
| Count++; |
| } |
| } |
| if ( Count ) |
| Map_ManGroupCompact( vGroup2 ); |
| return Count; |
| } |
| int Mop_ManMergeContainAll( Mop_Man_t * p, Vec_Wec_t * vGroups ) |
| { |
| Vec_Int_t * vGroup, * vGroup2; |
| int i, k, Count = 0; |
| Vec_WecForEachLevel( vGroups, vGroup, i ) |
| { |
| Count += Mop_ManRemoveIdentical( p, vGroup ); |
| Vec_WecForEachLevelStart( vGroups, vGroup2, k, i+1 ) |
| Count += Mop_ManMergeContainTwo( p, vGroup, vGroup2 ); |
| } |
| return Count; |
| } |
| void Mop_ManReduce2( Mop_Man_t * p ) |
| { |
| abctime clk = Abc_Clock(); |
| int nCubes = Vec_IntSize(p->vCubes); |
| Vec_Int_t * vStats = Mop_ManCollectStats( p ); |
| Vec_Wec_t * vGroups = Mop_ManCreateGroups( p ); |
| int nLimit = ABC_INFINITY; // 5 * Vec_IntSum(vStats) / Vec_IntSize(vStats) + 1; |
| int nOutLits = Mop_ManCountOutputLits( p ); |
| int Count1 = Mop_ManMergeContainAll( p, vGroups ); |
| int Count2 = Mop_ManMergeDist1All( p, vGroups, vStats, nLimit ); |
| int Count3 = Mop_ManMergeContainAll( p, vGroups ); |
| int Count4 = Mop_ManMergeDist1All( p, vGroups, vStats, nLimit ); |
| int Count5 = Mop_ManMergeContainAll( p, vGroups ); |
| int Removed = Mop_ManUnCreateGroups( p, vGroups ); |
| int nOutLits2 = Mop_ManCountOutputLits( p ); |
| Vec_WecFree( vGroups ); |
| //Vec_IntPrint( vStats ); |
| Vec_IntFree( vStats ); |
| assert( Removed == Count1 + Count2 + Count3 ); |
| // report |
| printf( "Cubes: %d -> %d. C = %d. M = %d. C = %d. M = %d. C = %d. Output lits: %d -> %d. ", |
| nCubes, Vec_IntSize(p->vCubes), Count1, Count2, Count3, Count4, Count5, nOutLits, nOutLits2 ); |
| Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Mop_ManReduce( Mop_Man_t * p ) |
| { |
| abctime clk = Abc_Clock(); |
| Vec_Int_t * vGroup, * vGroup2; |
| int i, k, nOutLits, nOutLits2, nEqual = 0, nContain = 0; |
| Vec_Wec_t * vGroups = Mop_ManCreateGroups( p ); |
| // initial stats |
| nOutLits = Mop_ManCountOutputLits( p ); |
| // check identical cubes within each group |
| Vec_WecForEachLevel( vGroups, vGroup, i ) |
| nEqual += Mop_ManRemoveIdentical( p, vGroup ); |
| // check contained cubes |
| Vec_WecForEachLevel( vGroups, vGroup, i ) |
| Vec_WecForEachLevelStart( vGroups, vGroup2, k, i+1 ) |
| nContain += Mop_ManMergeContainTwo( p, vGroup, vGroup2 ); |
| // final stats |
| nOutLits2 = Mop_ManCountOutputLits( p ); |
| Mop_ManUnCreateGroups( p, vGroups ); |
| Vec_WecFree( vGroups ); |
| // report |
| printf( "Total = %d. Reduced %d equal and %d contained cubes. Output lits: %d -> %d. ", Vec_IntSize(p->vCubes), nEqual, nContain, nOutLits, nOutLits2 ); |
| Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Wec_t * Mop_ManCubeCount( Mop_Man_t * p ) |
| { |
| int i, k, iCube; |
| Vec_Wec_t * vOuts = Vec_WecStart( p->nOuts ); |
| Vec_IntForEachEntry( p->vCubes, iCube, i ) |
| if ( iCube != -1 ) |
| { |
| word * pCube = Mop_ManCubeOut( p, iCube ); |
| for ( k = 0; k < p->nOuts; k++ ) |
| if ( Abc_TtGetBit( pCube, k ) ) |
| Vec_WecPush( vOuts, k, iCube ); |
| } |
| return vOuts; |
| } |
| Abc_Ntk_t * Mop_ManDerive( Mop_Man_t * p, char * pFileName ) |
| { |
| int i, k, c, iCube; |
| char Symb[4] = { '-', '0', '1', '?' }; // cube symbols |
| Vec_Str_t * vSop = Vec_StrAlloc( 1000 ); // storage for one SOP |
| Vec_Wec_t * vOuts = Mop_ManCubeCount( p ); // cube count for each output |
| Abc_Ntk_t * pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); |
| pNtk->pName = Extra_UtilStrsav( pFileName ); |
| pNtk->pSpec = Extra_UtilStrsav( pFileName ); |
| for ( i = 0; i < p->nIns; i++ ) |
| Abc_NtkCreatePi(pNtk); |
| for ( i = 0; i < p->nOuts; i++ ) |
| { |
| Vec_Int_t * vThis = Vec_WecEntry( vOuts, i ); |
| Abc_Obj_t * pPo = Abc_NtkCreatePo(pNtk); |
| Abc_Obj_t * pNode = Abc_NtkCreateNode(pNtk); |
| Abc_ObjAddFanin( pPo, pNode ); |
| if ( Vec_IntSize(vThis) == 0 ) |
| { |
| pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 0\n" ); |
| continue; |
| } |
| for ( k = 0; k < p->nIns; k++ ) |
| Abc_ObjAddFanin( pNode, Abc_NtkPi(pNtk, k) ); |
| Vec_StrClear( vSop ); |
| Vec_IntForEachEntry( vThis, iCube, c ) |
| { |
| word * pCube = Mop_ManCubeIn( p, iCube ); |
| for ( k = 0; k < p->nIns; k++ ) |
| Vec_StrPush( vSop, Symb[Abc_TtGetQua(pCube, k)] ); |
| Vec_StrAppend( vSop, " 1\n" ); |
| } |
| Vec_StrPush( vSop, '\0' ); |
| pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, Vec_StrArray(vSop) ); |
| } |
| Vec_StrFree( vSop ); |
| Vec_WecFree( vOuts ); |
| Abc_NtkAddDummyPiNames( pNtk ); |
| Abc_NtkAddDummyPoNames( pNtk ); |
| return pNtk; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Mop_ManTest( char * pFileName, int fMerge, int fVerbose ) |
| { |
| Abc_Ntk_t * pNtk = NULL; |
| Mop_Man_t * p = Mop_ManRead( pFileName ); |
| if ( p == NULL ) |
| return NULL; |
| Mop_ManRemoveEmpty( p ); |
| //Mop_ManPrint( p ); |
| if ( fMerge ) |
| Mop_ManReduce2( p ); |
| else |
| Mop_ManReduce( p ); |
| //Mop_ManPrint( p ); |
| pNtk = Mop_ManDerive( p, pFileName ); |
| Mop_ManStop( p ); |
| return pNtk; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |