diff options
author | Alan Mishchenko <alanmi@berkeley.edu> | 2018-10-02 08:33:25 -0400 |
---|---|---|
committer | Alan Mishchenko <alanmi@berkeley.edu> | 2018-10-02 08:33:25 -0400 |
commit | c750544df6a24ecaab34683b2dbde5e53b8a710c (patch) | |
tree | f89875cb1348f162d67a2339e8f858868be82afa | |
parent | 6f6dba429e3f9d030fcc5a141a2554d7a5d6b5ee (diff) | |
download | abc-c750544df6a24ecaab34683b2dbde5e53b8a710c.tar.gz abc-c750544df6a24ecaab34683b2dbde5e53b8a710c.tar.bz2 abc-c750544df6a24ecaab34683b2dbde5e53b8a710c.zip |
Experiments with Boolean functions.
-rw-r--r-- | src/base/abci/abc.c | 22 | ||||
-rw-r--r-- | src/bdd/extrab/extraBddMisc.c | 4 | ||||
-rw-r--r-- | src/opt/dau/dauNpn2.c | 208 |
3 files changed, 210 insertions, 24 deletions
diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 820440ac..988aba88 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -23108,11 +23108,11 @@ usage: ***********************************************************************/ int Abc_CommandFunEnum( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Dtt_EnumerateLf( int nVars, int nNodeMax, int fDelay, int fVerbose ); + extern void Dtt_EnumerateLf( int nVars, int nNodeMax, int fDelay, int fMulti, int fVerbose ); extern void Dau_FunctionEnum( int nInputs, int nVars, int nNodeMax, int fUseTwo, int fReduce, int fVerbose ); - int c, nInputs = 4, nVars = 4, nNodeMax = 32, fUseTwo = 0, fReduce = 0, fSimple = 0, fDelay = 0, fVerbose = 0; + int c, nInputs = 4, nVars = 4, nNodeMax = 32, fUseTwo = 0, fReduce = 0, fSimple = 0, fDelay = 0, fMulti = 0, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "SIMtrldvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "SIMtrldmvh" ) ) != EOF ) { switch ( c ) { @@ -23161,6 +23161,9 @@ int Abc_CommandFunEnum( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'd': fDelay ^= 1; break; + case 'm': + fMulti ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -23178,7 +23181,7 @@ int Abc_CommandFunEnum( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "The number of inputs should be 3 <= I <= 5.\n" ); goto usage; } - Dtt_EnumerateLf( nVars, nNodeMax, fDelay, fVerbose ); + Dtt_EnumerateLf( nVars, nNodeMax, fDelay, fMulti, fVerbose ); } else { @@ -23197,15 +23200,16 @@ int Abc_CommandFunEnum( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: funenum [-SIM num] [-trldvh]\n" ); + Abc_Print( -2, "usage: funenum [-SIM num] [-trldmvh]\n" ); Abc_Print( -2, "\t enumerates minimum 2-input-gate implementations\n" ); Abc_Print( -2, "\t-S num : the maximum intermediate support size [default = %d]\n", nInputs ); Abc_Print( -2, "\t-I num : the number of inputs of Boolean functions [default = %d]\n", nVars ); Abc_Print( -2, "\t-M num : the maximum number of 2-input gates [default = %d]\n", nNodeMax ); - Abc_Print( -2, "\t-t : toggle adding combination of two gates [default = %s]\n", fUseTwo? "yes": "no" ); - Abc_Print( -2, "\t-r : toggle reducing the last level [default = %s]\n", fReduce? "yes": "no" ); - Abc_Print( -2, "\t-l : toggle generating L(f) rather than C(f) [default = %s]\n", fSimple? "yes": "no" ); - Abc_Print( -2, "\t-d : toggle generating D(f) rather than C(f) [default = %s]\n", fDelay? "yes": "no" ); + Abc_Print( -2, "\t-t : toggle adding combination of two gates [default = %s]\n", fUseTwo? "yes": "no" ); + Abc_Print( -2, "\t-r : toggle reducing the last level [default = %s]\n", fReduce? "yes": "no" ); + Abc_Print( -2, "\t-l : toggle generating L(f) rather than C(f) [default = %s]\n", fSimple? "yes": "no" ); + Abc_Print( -2, "\t-d : toggle generating D(f) rather than C(f) [default = %s]\n", fDelay? "yes": "no" ); + Abc_Print( -2, "\t-m : toggle generating multiplicity statistics [default = %s]\n", fMulti? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; diff --git a/src/bdd/extrab/extraBddMisc.c b/src/bdd/extrab/extraBddMisc.c index 335f6754..42003864 100644 --- a/src/bdd/extrab/extraBddMisc.c +++ b/src/bdd/extrab/extraBddMisc.c @@ -2723,8 +2723,8 @@ DdNode * Extra_bddTuples( if ( K > nVars ) return NULL; - /* the second argument in the recursive call stannds for <n>; - /* reate the first argument, which stands for <k> + /* the second argument in the recursive call stands for <n>; + * create the first argument, which stands for <k> * as when we are talking about the tuple of <k> out of <n> */ for ( i = 0; i < nVars-K; i++ ) VarsK = cuddT( VarsK ); diff --git a/src/opt/dau/dauNpn2.c b/src/opt/dau/dauNpn2.c index b02aa794..68fdc457 100644 --- a/src/opt/dau/dauNpn2.c +++ b/src/opt/dau/dauNpn2.c @@ -46,10 +46,17 @@ struct Dtt_Man_t_ Vec_Int_t * vTemp; // temporary Vec_Int_t * vTemp2; // temporary unsigned FunMask; // function mask + unsigned CmpMask; // function mask unsigned BinMask; // hash mask unsigned * pBins; // hash bins Vec_Int_t * vUsedBins; // used bins int Counts[32]; // node counts + int nClasses; // count of classes + unsigned * pTable; // mapping of funcs into their classes + int * pNodes; // the number of nodes in min-node network + int * pTimes; // the number of different min-node networks + char * pVisited; // visited classes + Vec_Int_t * vVisited; // the number of visited classes }; //////////////////////////////////////////////////////////////////////// @@ -67,7 +74,97 @@ struct Dtt_Man_t_ SeeAlso [] ***********************************************************************/ -Dtt_Man_t * Dtt_ManAlloc( int nVars ) +unsigned * Dau_ReadFile2( char * pFileName, int nSizeW ) +{ + abctime clk = Abc_Clock(); + FILE * pFile = fopen( pFileName, "rb" ); + unsigned * p = (unsigned *)ABC_CALLOC(word, nSizeW); + int RetValue = pFile ? fread( p, sizeof(word), nSizeW, pFile ) : 0; + RetValue = 0; + if ( pFile ) + { + printf( "Finished reading file \"%s\".\n", pFileName ); + fclose( pFile ); + } + else + printf( "Cannot open input file \"%s\".\n", pFileName ); + Abc_PrintTime( 1, "File reading", Abc_Clock() - clk ); + return p; +} +void Dtt_ManRenum( int nVars, unsigned * pTable, int * pnClasses ) +{ + unsigned i, Limit = 1 << ((1 << nVars)-1), Count = 0; + for ( i = 0; i < Limit; i++ ) + if ( pTable[i] == i ) + pTable[i] = Count++; + else + { + assert( pTable[i] < i ); + pTable[i] = pTable[pTable[i]]; + } + printf( "The total number of NPN classes = %d.\n", Count ); + *pnClasses = Count; +} +unsigned * Dtt_ManLoadClasses( int nVars, int * pnClasses ) +{ + unsigned * pTable = NULL; + if ( nVars == 4 ) + pTable = Dau_ReadFile2( "tableW14.data", 1 << 14 ); + else if ( nVars == 5 ) + pTable = Dau_ReadFile2( "tableW30.data", 1 << 30 ); + else assert( 0 ); + Dtt_ManRenum( nVars, pTable, pnClasses ); + return pTable; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dtt_ManAddVisited( Dtt_Man_t * p, unsigned Truth2, int n ) +{ + unsigned Truth = Truth2 & p->CmpMask ? ~Truth2 : Truth2; + unsigned Class = p->pTable[Truth & p->FunMask]; + assert( Class < (unsigned)p->nClasses ); + if ( p->pNodes[Class] < n ) + return; + assert( p->pNodes[Class] == n ); + if ( p->pVisited[Class] ) + return; + p->pVisited[Class] = 1; + Vec_IntPush( p->vVisited, Class ); +} +void Dtt_ManProcessVisited( Dtt_Man_t * p ) +{ + int i, Class; + Vec_IntForEachEntry( p->vVisited, Class, i ) + { + assert( p->pVisited[Class] ); + p->pVisited[Class] = 0; + p->pTimes[Class]++; + } + Vec_IntClear( p->vVisited ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dtt_Man_t * Dtt_ManAlloc( int nVars, int fMulti ) { Dtt_Man_t * p = ABC_CALLOC( Dtt_Man_t, 1 ); p->nVars = nVars; @@ -84,14 +181,26 @@ Dtt_Man_t * Dtt_ManAlloc( int nVars ) p->vFunNodes = Vec_WecStart( 16 ); p->vTemp = Vec_IntAlloc( 4000 ); p->vTemp2 = Vec_IntAlloc( 4000 ); - p->FunMask = nVars == 5 ? ~0 : (nVars == 4 ? 0xFFFF : 0xFF); + p->FunMask = nVars == 5 ? ~0 : (nVars == 4 ? 0xFFFF : 0xFF); + p->CmpMask = nVars == 5 ? 1 << 31 : (nVars == 4 ? 1 << 15 : 1 << 7); p->BinMask = 0x3FFF; p->pBins = ABC_FALLOC( unsigned, p->BinMask + 1 ); p->vUsedBins = Vec_IntAlloc( 4000 ); + if ( !fMulti ) return p; + p->pTable = Dtt_ManLoadClasses( p->nVars, &p->nClasses ); + p->pNodes = ABC_CALLOC( int, p->nClasses ); + p->pTimes = ABC_CALLOC( int, p->nClasses ); + p->pVisited = ABC_CALLOC( char, p->nClasses ); + p->vVisited = Vec_IntAlloc( 1000 ); return p; } void Dtt_ManFree( Dtt_Man_t * p ) { + Vec_IntFreeP( &p->vVisited ); + ABC_FREE( p->pTable ); + ABC_FREE( p->pNodes ); + ABC_FREE( p->pTimes ); + ABC_FREE( p->pVisited ); Vec_IntFreeP( &p->vFanins ); Vec_IntFreeP( &p->vTruths ); Vec_IntFreeP( &p->vConfigs ); @@ -138,14 +247,15 @@ int Dtt_ManCheckHash( Dtt_Man_t * p, unsigned Truth ) } Vec_Int_t * Dtt_ManCollect( Dtt_Man_t * p, unsigned Truth, Vec_Int_t * vFuns ) { - int i, k, Entry; + int i, k, Entry, Shift = (1 << p->nVars) - 1; word tCur = ((word)Truth << 32) | (word)Truth; Vec_IntClear( vFuns ); for ( i = 0; i < p->nPerms; i++ ) { for ( k = 0; k < p->nComps; k++ ) { - unsigned tTemp = (unsigned)(tCur & 1 ? ~tCur : tCur); +// unsigned tTemp = (unsigned)(tCur & 1 ? ~tCur : tCur); + unsigned tTemp = (unsigned)(tCur & p->CmpMask ? ~tCur : tCur); if ( Dtt_ManCheckHash( p, tTemp ) ) Vec_IntPush( vFuns, tTemp ); tCur = Abc_Tt6Flip( tCur, p->pComps[k] ); @@ -174,12 +284,14 @@ Vec_Int_t * Dtt_ManCollect( Dtt_Man_t * p, unsigned Truth, Vec_Int_t * vFuns ) ***********************************************************************/ static inline int Dtt_ManGetFun( Dtt_Man_t * p, unsigned tFun ) { - return Abc_TtGetBit( p->pPres, (tFun & p->FunMask) >> 1 ); + tFun = tFun & p->CmpMask ? ~tFun : tFun; + return Abc_TtGetBit( p->pPres, tFun & p->FunMask ); } static inline void Dtt_ManSetFun( Dtt_Man_t * p, unsigned tFun ) { - //assert( !Dtt_ManGetFun(p, (fFun & p->FunMask)) ); - Abc_TtSetBit( p->pPres, (tFun & p->FunMask) >> 1 ); + tFun = tFun & p->CmpMask ? ~tFun : tFun; + //assert( !Dtt_ManGetFun(p, fFun & p->FunMask ); + Abc_TtSetBit( p->pPres, tFun & p->FunMask ); } void Dtt_ManAddFunction( Dtt_Man_t * p, int n, int FanI, int FanJ, int Type, unsigned Truth ) { @@ -202,14 +314,23 @@ void Dtt_ManAddFunction( Dtt_Man_t * p, int n, int FanI, int FanJ, int Type, uns Dtt_ManSetFun( p, Min ); assert( nNodes < 32 ); p->Counts[nNodes]++; + + if ( p->pTable == NULL ) + return; + Truth = Truth & p->CmpMask ? ~Truth : Truth; + Truth &= p->FunMask; + assert( p->pNodes[p->pTable[Truth]] == 0 ); + p->pNodes[p->pTable[Truth]] = n; } -int Dtt_PrintStats( int nNodes, int nVars, Vec_Wec_t * vFunNodes, word nSteps, abctime clk, int fDelay ) + +int Dtt_PrintStats( int nNodes, int nVars, Vec_Wec_t * vFunNodes, word nSteps, abctime clk, int fDelay, word nMultis ) { int nNew = Vec_IntSize(Vec_WecEntry(vFunNodes, nNodes)); printf("%c =%2d | ", fDelay ? 'D':'N', nNodes ); printf("C =%12.0f | ", (double)(iword)nSteps ); printf("New%d =%10d ", nVars, nNew + (int)(nNodes==0) ); printf("All%d =%10d | ", nVars, Vec_WecSizeSize(vFunNodes)+1 ); + printf("Multi =%10d | ", (int)nMultis ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); //Abc_Print(1, "%9.2f sec\n", 1.0*(Abc_Clock() - clk)/(CLOCKS_PER_SEC)); fflush(stdout); @@ -223,10 +344,61 @@ void Dtt_PrintDistrib( Dtt_Man_t * p ) if ( p->Counts[i] ) printf( "N = %2d : NPN = %6d\n", i, p->Counts[i] ); } -void Dtt_EnumerateLf( int nVars, int nNodeMax, int fDelay, int fVerbose ) +void Dtt_PrintMulti2( Dtt_Man_t * p ) { - abctime clk = Abc_Clock(); word nSteps = 0; - Dtt_Man_t * p = Dtt_ManAlloc( nVars ); int n, i, j; + int i, n; + for ( n = 0; n <= 7; n++ ) + { + printf( "n=%d : ", n); + for ( i = 0; i < p->nClasses; i++ ) + if ( p->pNodes[i] == n ) + printf( "%d ", p->pTimes[i] ); + printf( "\n" ); + } +} +void Dtt_PrintMulti( Dtt_Man_t * p ) +{ + int i, n, Entry, Count, Prev; + for ( n = 0; n < 16; n++ ) + { + Vec_Int_t * vTimes = Vec_IntAlloc( 100 ); + Vec_Int_t * vUsed = Vec_IntAlloc( 100 ); + for ( i = 0; i < p->nClasses; i++ ) + if ( p->pNodes[i] == n ) + Vec_IntPush( vTimes, p->pTimes[i] ); + if ( Vec_IntSize(vTimes) == 0 ) + { + Vec_IntFree(vTimes); + Vec_IntFree(vUsed); + break; + } + Vec_IntSort( vTimes, 0 ); + Count = 1; + Prev = Vec_IntEntry( vTimes, 0 ); + Vec_IntForEachEntryStart( vTimes, Entry, i, 1 ) + if ( Prev == Entry ) + Count++; + else + { + assert( Prev < Entry ); + Vec_IntPushTwo( vUsed, Prev, Count ); + Count = 1; + Prev = Entry; + } + if ( Count > 0 ) + Vec_IntPushTwo( vUsed, Prev, Count ); + printf( "n=%d : ", n); + Vec_IntForEachEntryDouble( vUsed, Prev, Entry, i ) + printf( "%d=%d ", Prev, Entry ); + printf( "\n" ); + Vec_IntFree( vTimes ); + Vec_IntFree( vUsed ); + } +} +void Dtt_EnumerateLf( int nVars, int nNodeMax, int fDelay, int fMulti, int fVerbose ) +{ + abctime clk = Abc_Clock(); word nSteps = 0, nMultis = 0; + Dtt_Man_t * p = Dtt_ManAlloc( nVars, fMulti ); int n, i, j; // constant zero class Vec_IntPushTwo( p->vFanins, 0, 0 ); Vec_IntPush( p->vTruths, 0 ); @@ -245,7 +417,7 @@ void Dtt_EnumerateLf( int nVars, int nNodeMax, int fDelay, int fVerbose ) Dtt_ManSetFun( p, (unsigned)s_Truths6[i] ); p->Counts[0] = 2; // enumerate - Dtt_PrintStats(0, nVars, p->vFunNodes, nSteps, clk, fDelay); + Dtt_PrintStats(0, nVars, p->vFunNodes, nSteps, clk, fDelay, 0); for ( n = 1; n <= nNodeMax; n++ ) { for ( i = 0, j = n - 1; i < n; i++, j = j - 1 + fDelay ) if ( i <= j ) @@ -274,15 +446,25 @@ void Dtt_EnumerateLf( int nVars, int nNodeMax, int fDelay, int fVerbose ) if ( !Dtt_ManGetFun(p, TruthJ ^ Truth) ) Dtt_ManAddFunction( p, n, EntryI, EntryJ, 4, TruthJ ^ Truth ); nSteps += 5; + + if ( p->pTable ) Dtt_ManAddVisited( p, TruthJ & Truth, n ); + if ( p->pTable ) Dtt_ManAddVisited( p, TruthJ & ~Truth, n ); + if ( p->pTable ) Dtt_ManAddVisited( p, ~TruthJ & Truth, n ); + if ( p->pTable ) Dtt_ManAddVisited( p, TruthJ | Truth, n ); + if ( p->pTable ) Dtt_ManAddVisited( p, TruthJ ^ Truth, n ); } + nMultis++; + if ( p->pTable ) Dtt_ManProcessVisited( p ); } } } - if ( Dtt_PrintStats(n, nVars, p->vFunNodes, nSteps, clk, fDelay) == 0 ) + if ( Dtt_PrintStats(n, nVars, p->vFunNodes, nSteps, clk, fDelay, nMultis) == 0 ) break; } if ( fDelay ) Dtt_PrintDistrib( p ); + if ( p->pTable ) + Dtt_PrintMulti( p ); Dtt_ManFree( p ); } |