summaryrefslogtreecommitdiff
path: root/src/opt/dau/dauNpn.c
diff options
context:
space:
mode:
authorRuben Undheim <ruben.undheim@gmail.com>2018-12-03 20:32:04 +0000
committerRuben Undheim <ruben.undheim@gmail.com>2018-12-03 20:32:04 +0000
commit5988cc4cd054db6172af8ea51bf0855777f0d44a (patch)
treebccd7d3893664755b08bae56114024d02dd8c2f2 /src/opt/dau/dauNpn.c
parentbfa5c2f2e843651f29c8c0da0fa1113c99cfc469 (diff)
New upstream version 1.01+20181130git163bba5+dfsg
Diffstat (limited to 'src/opt/dau/dauNpn.c')
-rw-r--r--src/opt/dau/dauNpn.c707
1 files changed, 600 insertions, 107 deletions
diff --git a/src/opt/dau/dauNpn.c b/src/opt/dau/dauNpn.c
index d8c1911..b57ade6 100644
--- a/src/opt/dau/dauNpn.c
+++ b/src/opt/dau/dauNpn.c
@@ -21,6 +21,7 @@
#include "dauInt.h"
#include "misc/util/utilTruth.h"
#include "misc/extra/extra.h"
+#include "bool/lucky/lucky.h"
ABC_NAMESPACE_IMPL_START
@@ -122,6 +123,7 @@ void Dau_TruthEnum()
{
FILE * pFile = fopen( pFileName, "wb" );
int RetValue = fwrite( pTable, 8, nSizeW, pFile );
+ RetValue = 0;
fclose( pFile );
ABC_FREE( pTable );
}
@@ -144,31 +146,42 @@ unsigned * Dau_ReadFile( char * pFileName, int nSizeW )
abctime clk = Abc_Clock();
FILE * pFile = fopen( pFileName, "rb" );
unsigned * p = (unsigned *)ABC_CALLOC(word, nSizeW);
- int RetValue = fread( p, sizeof(word), nSizeW, pFile );
- fclose( pFile );
+ 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 Dau_AddFunction( word tCur, int nVars, unsigned * pTable, Vec_Int_t * vNpns )
+int Dau_AddFunction( word tCur, int nVars, unsigned * pTable, Vec_Int_t * vNpns, Vec_Int_t * vNpns_ )
{
int Digit = (1 << nVars)-1;
word tMask = Abc_Tt6Mask( 1 << nVars );
word tNorm = (tCur >> Digit) & 1 ? ~tCur : tCur;
unsigned t = (unsigned)(tNorm & tMask);
- unsigned tRep = pTable[t];
- unsigned tRep2 = pTable[tRep & 0x7FFFFFFF];
+ unsigned tRep = pTable[t] & 0x7FFFFFFF;
+ unsigned tRep2 = pTable[tRep];
assert( ((tNorm >> Digit) & 1) == 0 );
if ( (tRep2 >> 31) == 0 ) // first time
{
Vec_IntPush( vNpns, tRep2 );
- pTable[tRep & 0x7FFFFFFF] = tRep2 | (1 << 31);
+ if ( Abc_TtSupportSize(&tCur, nVars) < nVars )
+ Vec_IntPush( vNpns_, tRep2 );
+ pTable[tRep] = tRep2 | (1 << 31);
+ return tRep2;
}
-
+ return 0;
}
void Dau_NetworkEnum()
{
abctime clk = Abc_Clock();
int Limit = 2;
+ int UseTwo = 0;
#ifdef USE4VARS
int nVars = 4;
int nSizeW = 1 << 14;
@@ -178,146 +191,626 @@ void Dau_NetworkEnum()
int nSizeW = 1 << 30;
char * pFileName = "tableW30.data";
#endif
- unsigned * pTable = Dau_ReadFile( pFileName, nSizeW );
- Vec_Int_t * vNpns = Vec_IntAlloc( 1000 );
- int i, v, g, k, m, Entry, Count = 1, iPrev = 0, iLast = 1;
+ unsigned * pTable = Dau_ReadFile( pFileName, nSizeW );
+ Vec_Wec_t * vNpns = Vec_WecStart( 32 );
+ Vec_Wec_t * vNpns_ = Vec_WecStart( 32 );
+ int i, v, u, g, k, m, n, Res, Entry;
unsigned Inv = (unsigned)Abc_Tt6Mask(1 << (nVars-1));
+ // create constant function and buffer/inverter function
pTable[0] |= (1 << 31);
pTable[Inv] |= (1 << 31);
- Vec_IntPushTwo( vNpns, 0, Inv );
- Vec_IntForEachEntryStart( vNpns, Entry, i, 1 )
+ Vec_IntPushTwo( Vec_WecEntry(vNpns, 0), 0, Inv );
+ Vec_IntPushTwo( Vec_WecEntry(vNpns_, 0), 0, Inv );
+ printf("Nodes = %2d. New = %6d. Total = %6d. New = %6d. Total = %6d. ",
+ 0, Vec_IntSize(Vec_WecEntry(vNpns, 0)), Vec_WecSizeSize(vNpns),
+ Vec_IntSize(Vec_WecEntry(vNpns_, 0)), Vec_WecSizeSize(vNpns_) );
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+ // numerate other functions based on how many nodes they have
+ for ( n = 1; n < 32; n++ )
{
- word uTruth = (((word)Entry) << 32) | (word)Entry;
- int nSupp = Abc_TtSupportSize( &uTruth, nVars );
- //printf( "Exploring function %4d with %d vars: ", i, nSupp );
- //printf( " %04x\n", (int)uTruth );
- //Dau_DsdPrintFromTruth( &uTruth, 4 );
- for ( v = 0; v < nSupp; v++ )
+ Vec_Int_t * vFuncsN2 = n > 1 ? Vec_WecEntry( vNpns, n-2 ) : NULL;
+ Vec_Int_t * vFuncsN1 = Vec_WecEntry( vNpns, n-1 );
+ Vec_Int_t * vFuncsN = Vec_WecEntry( vNpns, n );
+ Vec_Int_t * vFuncsN_ = Vec_WecEntry( vNpns_,n );
+ Vec_IntForEachEntry( vFuncsN1, Entry, i )
{
- word tGate, tCur;
- word Cof0 = Abc_Tt6Cofactor0( uTruth, nVars-1-v );
- word Cof1 = Abc_Tt6Cofactor1( uTruth, nVars-1-v );
- for ( g = 0; g < Limit; g++ )
+ word uTruth = (((word)Entry) << 32) | (word)Entry;
+ int nSupp = Abc_TtSupportSize( &uTruth, nVars );
+ assert( nSupp == 6 || !Abc_Tt6HasVar(uTruth, nVars-1-nSupp) );
+ //printf( "Exploring function %4d with %d vars: ", i, nSupp );
+ //printf( " %04x\n", (int)uTruth );
+ //Dau_DsdPrintFromTruth( &uTruth, 4 );
+ for ( v = 0; v < nSupp; v++ )
{
- if ( nSupp < nVars )
+ word tGate, tCur;
+ word Cof0 = Abc_Tt6Cofactor0( uTruth, nVars-1-v );
+ word Cof1 = Abc_Tt6Cofactor1( uTruth, nVars-1-v );
+ for ( g = 0; g < Limit; g++ )
{
- if ( g == 0 )
+ if ( nSupp < nVars )
{
- tGate = s_Truths6[nVars-1-v] & s_Truths6[nVars-1-nSupp];
- tCur = (tGate & Cof1) | (~tGate & Cof0);
- Dau_AddFunction( tCur, nVars, pTable, vNpns );
-
- tCur = (tGate & Cof0) | (~tGate & Cof1);
- Dau_AddFunction( tCur, nVars, pTable, vNpns );
+ if ( g == 0 )
+ {
+ tGate = s_Truths6[nVars-1-v] & s_Truths6[nVars-1-nSupp];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+
+ tCur = (tGate & Cof0) | (~tGate & Cof1);
+ Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+ }
+ else
+ {
+ tGate = s_Truths6[nVars-1-v] ^ s_Truths6[nVars-1-nSupp];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+ }
+ }
+ }
+ for ( g = 0; g < Limit; g++ )
+ {
+ // add one cross bar
+ for ( k = 0; k < nSupp; k++ ) if ( k != v )
+ {
+ if ( g == 0 )
+ {
+ tGate = s_Truths6[nVars-1-v] & s_Truths6[nVars-1-k];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+
+ tCur = (tGate & Cof0) | (~tGate & Cof1);
+ Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+
+ tGate = s_Truths6[nVars-1-v] & ~s_Truths6[nVars-1-k];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+
+ tCur = (tGate & Cof0) | (~tGate & Cof1);
+ Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+ }
+ else
+ {
+ tGate = s_Truths6[nVars-1-v] ^ s_Truths6[nVars-1-k];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+ }
}
- else
+ }
+ for ( g = 0; g < Limit; g++ )
+ {
+ // add two cross bars
+ for ( k = 0; k < nSupp; k++ ) if ( k != v )
+ for ( m = k+1; m < nSupp; m++ ) if ( m != v )
{
- tGate = s_Truths6[nVars-1-v] ^ s_Truths6[nVars-1-nSupp];
- tCur = (tGate & Cof1) | (~tGate & Cof0);
- Dau_AddFunction( tCur, nVars, pTable, vNpns );
+ if ( g == 0 )
+ {
+ tGate = s_Truths6[nVars-1-m] & s_Truths6[nVars-1-k];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+
+ tCur = (tGate & Cof0) | (~tGate & Cof1);
+ Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+
+ tGate = s_Truths6[nVars-1-m] & ~s_Truths6[nVars-1-k];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+
+ tCur = (tGate & Cof0) | (~tGate & Cof1);
+ Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+
+ tGate = ~s_Truths6[nVars-1-m] & s_Truths6[nVars-1-k];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+
+ tCur = (tGate & Cof0) | (~tGate & Cof1);
+ Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+
+ tGate = ~s_Truths6[nVars-1-m] & ~s_Truths6[nVars-1-k];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+
+ tCur = (tGate & Cof0) | (~tGate & Cof1);
+ Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+ }
+ else
+ {
+ tGate = s_Truths6[nVars-1-m] ^ s_Truths6[nVars-1-k];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+ }
}
}
}
- for ( g = 0; g < Limit; g++ )
+ }
+ if ( UseTwo && vFuncsN2 )
+ Vec_IntForEachEntry( vFuncsN2, Entry, i )
+ {
+ word uTruth = (((word)Entry) << 32) | (word)Entry;
+ int nSupp = Abc_TtSupportSize( &uTruth, nVars );
+ assert( nSupp == 6 || !Abc_Tt6HasVar(uTruth, nVars-1-nSupp) );
+ //printf( "Exploring function %4d with %d vars: ", i, nSupp );
+ //printf( " %04x\n", (int)uTruth );
+ //Dau_DsdPrintFromTruth( &uTruth, 4 );
+ for ( v = 0; v < nSupp; v++ )
+// for ( u = v+1; u < nSupp; u++ ) if ( u != v )
+ for ( u = 0; u < nSupp; u++ ) if ( u != v )
{
+ word tGate1, tGate2, tCur;
+ word Cof0 = Abc_Tt6Cofactor0( uTruth, nVars-1-v );
+ word Cof1 = Abc_Tt6Cofactor1( uTruth, nVars-1-v );
+
+ word Cof00 = Abc_Tt6Cofactor0( Cof0, nVars-1-u );
+ word Cof01 = Abc_Tt6Cofactor1( Cof0, nVars-1-u );
+ word Cof10 = Abc_Tt6Cofactor0( Cof1, nVars-1-u );
+ word Cof11 = Abc_Tt6Cofactor1( Cof1, nVars-1-u );
+
+ tGate1 = s_Truths6[nVars-1-v] & s_Truths6[nVars-1-u];
+ tGate2 = s_Truths6[nVars-1-v] ^ s_Truths6[nVars-1-u];
+
+ Cof0 = (tGate2 & Cof00) | (~tGate2 & Cof01);
+ Cof1 = (tGate2 & Cof10) | (~tGate2 & Cof11);
+
+ tCur = (tGate1 & Cof1) | (~tGate1 & Cof0);
+ Res = Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+ if ( Res )
+ printf( "Found function %d\n", Res );
+
+ tCur = (tGate1 & Cof0) | (~tGate1 & Cof1);
+ Res = Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ );
+ if ( Res )
+ printf( "Found function %d\n", Res );
+ }
+ }
+ printf("Nodes = %2d. New = %6d. Total = %6d. New = %6d. Total = %6d. ",
+ n, Vec_IntSize(vFuncsN), Vec_WecSizeSize(vNpns), Vec_IntSize(vFuncsN_), Vec_WecSizeSize(vNpns_) );
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+ fflush(stdout);
+ if ( Vec_IntSize(vFuncsN) == 0 )
+ break;
+ }
+// printf( "Functions with 7 nodes:\n" );
+// Vec_IntForEachEntry( Vec_WecEntry(vNpns_,7), Entry, i )
+// printf( "%04x ", Entry );
+// printf( "\n" );
+
+ Vec_WecFree( vNpns );
+ Vec_WecFree( vNpns_ );
+ ABC_FREE( pTable );
+ Abc_PrintTime( 1, "Total time", Abc_Clock() - clk );
+ fflush(stdout);
+}
+void Dau_NetworkEnumTest()
+{
+ //Dau_TruthEnum();
+ Dau_NetworkEnum();
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Count the number of symmetric pairs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dau_CountSymms( word t, int nVars )
+{
+ word Cof0, Cof1;
+ int i, j, nPairs = 0;
+ for ( i = 0; i < nVars; i++ )
+ for ( j = i+1; j < nVars; j++ )
+ nPairs += Abc_TtVarsAreSymmetric(&t, nVars, i, j, &Cof0, &Cof1);
+ return nPairs;
+}
+int Dau_CountSymms2( word t, int nVars )
+{
+ word Cof0, Cof1;
+ int i, j, SymVars = 0;
+ for ( i = 0; i < nVars; i++ )
+ for ( j = i+1; j < nVars; j++ )
+ if ( Abc_TtVarsAreSymmetric(&t, nVars, i, j, &Cof0, &Cof1) )
+ SymVars |= (1 << j);
+ return SymVars;
+}
+int Dau_CountCompl1( word t, int v, int nVars )
+{
+ word tNew = Abc_Tt6Flip(t, v);
+ int k;
+ if ( tNew == ~t )
+ return 1;
+ for ( k = 0; k < nVars; k++ ) if ( k != v )
+ if ( tNew == Abc_Tt6Flip(t, k) )
+ return 1;
+ return 0;
+}
+int Dau_CountCompl( word t, int nVars )
+{
+ int i, nPairs = 0;
+ for ( i = 0; i < nVars; i++ )
+ nPairs += Dau_CountCompl1(t, i, nVars);
+ return nPairs;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs exact canonicization of semi-canonical classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Wrd_t * Dau_ExactNpnForClasses( Vec_Mem_t * vTtMem, Vec_Int_t * vNodSup, int nVars, int nInputs )
+{
+ Vec_Wrd_t * vCanons = Vec_WrdStart( Vec_IntSize(vNodSup) );
+ word pAuxWord[1024], pAuxWord1[1024];
+ word uTruth; int i, Entry;
+ permInfo * pi = setPermInfoPtr(nVars);
+ Vec_IntForEachEntry( vNodSup, Entry, i )
+ {
+ if ( (Entry & 0xF) > nVars )
+ continue;
+ uTruth = *Vec_MemReadEntry( vTtMem, i );
+ simpleMinimal(&uTruth, pAuxWord, pAuxWord1, pi, nVars);
+ Vec_WrdWriteEntry( vCanons, i, uTruth );
+ }
+ freePermInfoPtr(pi);
+ return vCanons;
+}
+void Dau_ExactNpnPrint( Vec_Mem_t * vTtMem, Vec_Int_t * vNodSup, int nVars, int nInputs, int nNodesMax )
+{
+ abctime clk = Abc_Clock(); int n, nTotal = 0;
+ Vec_Wrd_t * vCanons = Dau_ExactNpnForClasses( vTtMem, vNodSup, nVars, nInputs );
+ Vec_Mem_t * vTtMem2 = Vec_MemAlloc( Vec_MemEntrySize(vTtMem), 10 );
+ Vec_MemHashAlloc( vTtMem2, 1<<10 );
+ Abc_PrintTime( 1, "Exact NPN computation time", Abc_Clock() - clk );
+ printf( "Final results:\n" );
+ for ( n = 0; n <= nNodesMax; n++ )
+ {
+ int i, Entry, Entry2, nEntries2, Counter = 0, Counter2 = 0;
+ Vec_IntForEachEntry( vNodSup, Entry, i )
+ {
+ if ( (Entry & 0xF) > nVars || (Entry >> 16) != n )
+ continue;
+ Counter++;
+ nEntries2 = Vec_MemEntryNum(vTtMem2);
+ Entry2 = Vec_MemHashInsert( vTtMem2, Vec_WrdEntryP(vCanons, i) );
+ if ( nEntries2 == Vec_MemEntryNum(vTtMem2) ) // found in the table - not new
+ continue;
+ Counter2++;
+ }
+ nTotal += Counter2;
+ printf( "Nodes = %2d. ", n );
+ printf( "Semi-canonical = %8d. ", Counter );
+ printf( "Canonical = %8d. ", Counter2 );
+ printf( "Total = %8d.", nTotal );
+ printf( "\n" );
+ }
+ Vec_MemHashFree( vTtMem2 );
+ Vec_MemFreeP( &vTtMem2 );
+ Vec_WrdFree( vCanons );
+ fflush(stdout);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Saving hash tables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dau_TablesSave( int nInputs, int nVars, Vec_Mem_t * vTtMem, Vec_Int_t * vNodSup, int nFronts, abctime clk )
+{
+ FILE * pFile;
+ char FileName[100];
+ int i, nWords = Abc_TtWordNum(nInputs);
+ // NPN classes
+ sprintf( FileName, "npn%d%d.ttd", nInputs, nVars );
+ pFile = fopen( FileName, "wb" );
+ for ( i = 0; i < Vec_MemEntryNum(vTtMem); i++ )
+ fwrite( Vec_MemReadEntry(vTtMem, i), 8, nWords, pFile );
+ fwrite( Vec_IntArray(vNodSup), 4, Vec_IntSize(vNodSup), pFile );
+ fclose( pFile );
+// printf( "Dumped files with %10d classes after exploring %10d frontiers.\n",
+// Vec_IntSize(vNodSup), nFronts );
+ printf( "Dumped file \"%s\" with %10d classes after exploring %10d frontiers. ",
+ FileName, Vec_IntSize(vNodSup), nFronts );
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+ fflush(stdout);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Dump functions by the number of nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dau_DumpFuncs( Vec_Mem_t * vTtMem, Vec_Int_t * vNodSup, int nVars, int nMax )
+{
+ FILE * pFile[20];
+ int Counters[20] = {0};
+ int n, i;
+ assert( nVars == 4 || nVars == 5 );
+ for ( n = 0; n <= nMax; n++ )
+ {
+ char FileName[100];
+ sprintf( FileName, "func%d_min%d.tt", nVars, n );
+ pFile[n] = fopen( FileName, "wb" );
+ }
+ for ( i = 0; i < Vec_MemEntryNum(vTtMem); i++ )
+ {
+ word * pTruth = Vec_MemReadEntry( vTtMem, i );
+ int NodSup = Vec_IntEntry( vNodSup, i );
+ if ( (NodSup & 0xF) != nVars )
+ continue;
+ Counters[NodSup >> 16]++;
+ if ( nVars == 4 )
+ fprintf( pFile[NodSup >> 16], "%04x\n", (int)(0xFFFF & pTruth[0]) );
+ else if ( nVars == 5 )
+ fprintf( pFile[NodSup >> 16], "%08x\n", (int)(0xFFFFFFFF & pTruth[0]) );
+ }
+ for ( n = 0; n <= nMax; n++ )
+ {
+ printf( "Dumped %8d %d-node %d-input functions into file.\n", Counters[n], n, nVars );
+ fclose( pFile[n] );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Function enumeration.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dau_CountFuncs( Vec_Int_t * vNodSup, int iStart, int iStop, int nVars )
+{
+ int i, Entry, Count = 0;
+ Vec_IntForEachEntryStartStop( vNodSup, Entry, i, iStart, iStop )
+ Count += ((Entry & 0xF) <= nVars);
+ return Count;
+}
+int Dau_PrintStats( int nNodes, int nInputs, int nVars, Vec_Int_t * vNodSup, int iStart, int iStop, word nSteps, int Count2, abctime clk )
+{
+ int nNew;
+ printf("N =%2d | ", nNodes );
+ printf("C =%12.0f ", (double)(iword)nSteps );
+ printf("New%d =%10d ", nInputs, iStop-iStart );
+ printf("All%d =%10d | ", nInputs, iStop );
+ printf("New%d =%8d ", nVars, nNew = Dau_CountFuncs(vNodSup, iStart, iStop, nVars) );
+ printf("All%d =%8d ", nVars, Dau_CountFuncs(vNodSup, 0, iStop, nVars) );
+ printf("Two =%6d ", Count2 );
+ //Abc_PrintTime( 1, "T", Abc_Clock() - clk );
+ Abc_Print(1, "%9.2f sec\n", 1.0*(Abc_Clock() - clk)/(CLOCKS_PER_SEC));
+ fflush(stdout);
+ return nNew;
+}
+
+
+int Dau_InsertFunction( Abc_TtHieMan_t * pMan, word * pCur, int nNodes, int nInputs, int nVars0, int nVars,
+ Vec_Mem_t * vTtMem, Vec_Int_t * vNodSup, int nFronts, abctime clk )
+{
+ int DumpDelta = 1000000;
+ char Perm[16] = {0};
+ int nVarsNew = Abc_TtMinBase( pCur, NULL, nVars, nInputs );
+ //unsigned Phase = Abc_TtCanonicizeHie( pMan, pCur, nVarsNew, Perm, 1 );
+ unsigned Phase = Abc_TtCanonicizeWrap( Abc_TtCanonicizeAda, pMan, pCur, nVarsNew, Perm, 99 );
+ int nEntries = Vec_MemEntryNum(vTtMem);
+ int Entry = Vec_MemHashInsert( vTtMem, pCur );
+ if ( nEntries == Vec_MemEntryNum(vTtMem) ) // found in the table - not new
+ return 0;
+ Entry = 0;
+ Phase = 0;
+ // this is a new class
+ Vec_IntPush( vNodSup, (nNodes << 16) | nVarsNew );
+ assert( Vec_MemEntryNum(vTtMem) == Vec_IntSize(vNodSup) );
+ if ( Vec_IntSize(vNodSup) % DumpDelta == 0 )
+ Dau_TablesSave( nInputs, nVars0, vTtMem, vNodSup, nFronts, clk );
+ return 1;
+}
+void Dau_FunctionEnum( int nInputs, int nVars, int nNodeMax, int fUseTwo, int fReduce, int fVerbose )
+{
+ abctime clk = Abc_Clock();
+ int nWords = Abc_TtWordNum(nInputs); word nSteps = 0;
+ Abc_TtHieMan_t * pMan = Abc_TtHieManStart( nInputs, 5 );
+ Vec_Mem_t * vTtMem = Vec_MemAlloc( nWords, 16 );
+ Vec_Int_t * vNodSup = Vec_IntAlloc( 1 << 16 );
+ int v, u, k, m, n, Entry, nNew, Limit[32] = {1, 2};
+ word Truth[4] = {0};
+ assert( nVars >= 3 && nVars <= nInputs && nInputs <= 6 );
+ Vec_MemHashAlloc( vTtMem, 1<<16 );
+ // add constant 0
+ Vec_MemHashInsert( vTtMem, Truth );
+ Vec_IntPush( vNodSup, 0 ); // nodes=0, supp=0
+ // add buffer/inverter
+ Abc_TtIthVar( Truth, 0, nInputs );
+ Abc_TtNot( Truth, nWords );
+ Vec_MemHashInsert( vTtMem, Truth );
+ Vec_IntPush( vNodSup, 1 ); // nodes=0, supp=1
+ Dau_PrintStats( 0, nInputs, nVars, vNodSup, 0, 2, nSteps, 0, clk );
+ // numerate other functions based on how many nodes they have
+ for ( n = 1; n <= nNodeMax; n++ )
+ {
+ int Count2 = 0;
+ int fExpand = !(fReduce && n == nNodeMax);
+ for ( Entry = Limit[n-1]; Entry < Limit[n]; Entry++ )
+ {
+ word * pTruth = Vec_MemReadEntry( vTtMem, Entry );
+ int NodSup = Vec_IntEntry(vNodSup, Entry);
+ int nSupp = 0xF & NodSup;
+ int SymVars = Dau_CountSymms2( pTruth[0], nSupp );
+ assert( n-1 == (NodSup >> 16) );
+ assert( !Abc_Tt6HasVar(*pTruth, nSupp) );
+ //printf( "Exploring function %4d with %d vars: ", i, nSupp );
+ //printf( " %04x\n", (int)uTruth );
+ //Dau_DsdPrintFromTruth( &uTruth, 4 );
+ for ( v = 0; v < nSupp; v++ ) if ( (SymVars & (1 << v)) == 0 )
+ {
+ word tGate, tCur;
+ word Cof0 = Abc_Tt6Cofactor0( *pTruth, v );
+ word Cof1 = Abc_Tt6Cofactor1( *pTruth, v );
+ // add one extra variable to support
+ if ( nSupp < nInputs && fExpand )
+ {
+ tGate = s_Truths6[v] & s_Truths6[nSupp];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp+1, vTtMem, vNodSup, Entry, clk );
+
+ tCur = (tGate & Cof0) | (~tGate & Cof1);
+ Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp+1, vTtMem, vNodSup, Entry, clk );
+
+
+ tGate = s_Truths6[v] ^ s_Truths6[nSupp];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp+1, vTtMem, vNodSup, Entry, clk );
+
+ nSteps += 3;
+ }
// add one cross bar
- for ( k = 0; k < nSupp; k++ ) if ( k != v )
+ if ( fExpand )
+ for ( k = 0; k < nSupp; k++ ) if ( k != v && ((SymVars & (1 << k)) == 0 || k == v+1) )
{
- if ( g == 0 )
- {
- tGate = s_Truths6[nVars-1-v] & s_Truths6[nVars-1-k];
- tCur = (tGate & Cof1) | (~tGate & Cof0);
- Dau_AddFunction( tCur, nVars, pTable, vNpns );
+ tGate = s_Truths6[v] & s_Truths6[k];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk );
- tCur = (tGate & Cof0) | (~tGate & Cof1);
- Dau_AddFunction( tCur, nVars, pTable, vNpns );
+ tCur = (tGate & Cof0) | (~tGate & Cof1);
+ Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk );
- tGate = s_Truths6[nVars-1-v] & ~s_Truths6[nVars-1-k];
- tCur = (tGate & Cof1) | (~tGate & Cof0);
- Dau_AddFunction( tCur, nVars, pTable, vNpns );
+ tGate = s_Truths6[v] & ~s_Truths6[k];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk );
- tCur = (tGate & Cof0) | (~tGate & Cof1);
- Dau_AddFunction( tCur, nVars, pTable, vNpns );
- }
- else
- {
- tGate = s_Truths6[nVars-1-v] ^ s_Truths6[nVars-1-k];
- tCur = (tGate & Cof1) | (~tGate & Cof0);
- Dau_AddFunction( tCur, nVars, pTable, vNpns );
- }
+ tCur = (tGate & Cof0) | (~tGate & Cof1);
+ Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk );
+
+
+ tGate = s_Truths6[v] ^ s_Truths6[k];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk );
+
+ nSteps += 5;
}
- }
- for ( g = 0; g < Limit; g++ )
- {
// add two cross bars
- for ( k = 0; k < nSupp; k++ ) if ( k != v )
- for ( m = k+1; m < nSupp; m++ ) if ( m != v )
+ for ( k = 0; k < nSupp; k++ ) if ( k != v )//&& ((SymVars & (1 << k)) == 0) )
+ for ( m = k+1; m < nSupp; m++ ) if ( m != v )//&& ((SymVars & (1 << m)) == 0 || m == k+1) )
{
- if ( g == 0 )
- {
- tGate = s_Truths6[nVars-1-m] & s_Truths6[nVars-1-k];
- tCur = (tGate & Cof1) | (~tGate & Cof0);
- Dau_AddFunction( tCur, nVars, pTable, vNpns );
+ tGate = s_Truths6[m] & s_Truths6[k];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk );
- tCur = (tGate & Cof0) | (~tGate & Cof1);
- Dau_AddFunction( tCur, nVars, pTable, vNpns );
+ tCur = (tGate & Cof0) | (~tGate & Cof1);
+ Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk );
- tGate = s_Truths6[nVars-1-m] & ~s_Truths6[nVars-1-k];
- tCur = (tGate & Cof1) | (~tGate & Cof0);
- Dau_AddFunction( tCur, nVars, pTable, vNpns );
+ tGate = s_Truths6[m] & ~s_Truths6[k];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk );
- tCur = (tGate & Cof0) | (~tGate & Cof1);
- Dau_AddFunction( tCur, nVars, pTable, vNpns );
+ tCur = (tGate & Cof0) | (~tGate & Cof1);
+ Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk );
- tGate = ~s_Truths6[nVars-1-m] & s_Truths6[nVars-1-k];
- tCur = (tGate & Cof1) | (~tGate & Cof0);
- Dau_AddFunction( tCur, nVars, pTable, vNpns );
+ tGate = ~s_Truths6[m] & s_Truths6[k];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk );
- tCur = (tGate & Cof0) | (~tGate & Cof1);
- Dau_AddFunction( tCur, nVars, pTable, vNpns );
+ tCur = (tGate & Cof0) | (~tGate & Cof1);
+ Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk );
- tGate = ~s_Truths6[nVars-1-m] & ~s_Truths6[nVars-1-k];
- tCur = (tGate & Cof1) | (~tGate & Cof0);
- Dau_AddFunction( tCur, nVars, pTable, vNpns );
+ tGate = ~s_Truths6[m] & ~s_Truths6[k];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk );
- tCur = (tGate & Cof0) | (~tGate & Cof1);
- Dau_AddFunction( tCur, nVars, pTable, vNpns );
- }
- else
- {
- tGate = s_Truths6[nVars-1-m] ^ s_Truths6[nVars-1-k];
- tCur = (tGate & Cof1) | (~tGate & Cof0);
- Dau_AddFunction( tCur, nVars, pTable, vNpns );
- }
+ tCur = (tGate & Cof0) | (~tGate & Cof1);
+ Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk );
+
+
+ tGate = s_Truths6[m] ^ s_Truths6[k];
+ tCur = (tGate & Cof1) | (~tGate & Cof0);
+ Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk );
+
+ tGate = s_Truths6[m] ^ s_Truths6[k];
+ tCur = (tGate & Cof0) | (~tGate & Cof1);
+ Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk );
+
+ nSteps += 10;
}
}
- }
- if ( i == iLast )
+ }
+ if ( fUseTwo && n > 2 && fExpand )
+ for ( Entry = Limit[n-2]; Entry < Limit[n-1]; Entry++ )
{
- //printf("Finished %d nodes with %d functions.\n", Count++, Vec_IntSize(vNpns) );
- iPrev = iLast;
- iLast = Vec_IntSize(vNpns)-1;
- printf("Finished %2d nodes with %6d functions out of %6d. ", Count++, iLast - iPrev, Vec_IntSize(vNpns) );
- Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
- fflush(stdout);
+ word * pTruth = Vec_MemReadEntry( vTtMem, Entry );
+ int NodSup = Vec_IntEntry(vNodSup, Entry);
+ int nSupp = 0xF & NodSup; int g1, g2;
+ assert( n-2 == (NodSup >> 16) );
+ assert( !Abc_Tt6HasVar(*pTruth, nSupp) );
+ for ( v = 0; v < nSupp; v++ )
+ for ( u = 0; u < nSupp; u++ ) if ( u != v )
+ {
+ word Cof0 = Abc_Tt6Cofactor0( *pTruth, v );
+ word Cof1 = Abc_Tt6Cofactor1( *pTruth, v );
+
+ word Cof00 = Abc_Tt6Cofactor0( Cof0, u );
+ word Cof01 = Abc_Tt6Cofactor1( Cof0, u );
+ word Cof10 = Abc_Tt6Cofactor0( Cof1, u );
+ word Cof11 = Abc_Tt6Cofactor1( Cof1, u );
+
+ word tGates[5], tCur;
+ tGates[0] = s_Truths6[v] & s_Truths6[u];
+ tGates[1] = s_Truths6[v] & ~s_Truths6[u];
+ tGates[2] = ~s_Truths6[v] & s_Truths6[u];
+ tGates[3] = s_Truths6[v] | s_Truths6[u];
+ tGates[4] = s_Truths6[v] ^ s_Truths6[u];
+
+ for ( g1 = 0; g1 < 5; g1++ )
+ for ( g2 = g1+1; g2 < 5; g2++ )
+ {
+ Cof0 = (tGates[g1] & Cof01) | (~tGates[g1] & Cof00);
+ Cof1 = (tGates[g1] & Cof11) | (~tGates[g1] & Cof10);
+
+ tCur = (tGates[g2] & Cof1) | (~tGates[g2] & Cof0);
+ Count2 += Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk );
+ }
+ }
}
+ Limit[n+1] = Vec_IntSize(vNodSup);
+ nNew = Dau_PrintStats( n, nInputs, nVars, vNodSup, Limit[n], Limit[n+1], nSteps, Count2, clk );
+ if ( nNew == 0 )
+ break;
}
- Vec_IntFree( vNpns );
- ABC_FREE( pTable );
- Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+ Dau_TablesSave( nInputs, nVars, vTtMem, vNodSup, Vec_IntSize(vNodSup), clk );
+ Abc_PrintTime( 1, "Total time", Abc_Clock() - clk );
+ //Dau_DumpFuncs( vTtMem, vNodSup, nVars, nNodeMax );
+ //Dau_ExactNpnPrint( vTtMem, vNodSup, nVars, nInputs, n );
+ Abc_TtHieManStop( pMan );
+ Vec_MemHashFree( vTtMem );
+ Vec_MemFreeP( &vTtMem );
+ Vec_IntFree( vNodSup );
fflush(stdout);
}
-void Dau_NetworkEnumTest()
-{
- //Dau_TruthEnum();
- Dau_NetworkEnum();
-}
-
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-
ABC_NAMESPACE_IMPL_END