summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2017-12-05 18:22:27 -0800
committerAlan Mishchenko <alanmi@berkeley.edu>2017-12-05 18:22:27 -0800
commit3f35ac8180bf69655662c2ccd2de9411b3533cf4 (patch)
treec2ae71eb5a5ab0a74beed90b2df0ccbaa15b1338
parente5d8335268eddf7d1bade6bfc8f91da677294674 (diff)
downloadabc-3f35ac8180bf69655662c2ccd2de9411b3533cf4.tar.gz
abc-3f35ac8180bf69655662c2ccd2de9411b3533cf4.tar.bz2
abc-3f35ac8180bf69655662c2ccd2de9411b3533cf4.zip
New command 'lutexact'.
-rw-r--r--src/base/abci/abc.c104
-rw-r--r--src/sat/bmc/bmcMaj.c373
-rw-r--r--src/sat/bmc/bmcMaj2.c385
3 files changed, 857 insertions, 5 deletions
diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c
index b1d0df9b..7b24dc8f 100644
--- a/src/base/abci/abc.c
+++ b/src/base/abci/abc.c
@@ -151,6 +151,7 @@ static int Abc_CommandBmsStop ( Abc_Frame_t * pAbc, int argc, cha
static int Abc_CommandBmsPs ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandMajExact ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandTwoExact ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandLutExact ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandComb ( Abc_Frame_t * pAbc, int argc, char ** argv );
@@ -819,6 +820,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_ps", Abc_CommandBmsPs, 0 );
Cmd_CommandAdd( pAbc, "Exact synthesis", "majexact", Abc_CommandMajExact, 0 );
Cmd_CommandAdd( pAbc, "Exact synthesis", "twoexact", Abc_CommandTwoExact, 0 );
+ Cmd_CommandAdd( pAbc, "Exact synthesis", "lutexact", Abc_CommandLutExact, 0 );
Cmd_CommandAdd( pAbc, "Various", "logic", Abc_CommandLogic, 1 );
Cmd_CommandAdd( pAbc, "Various", "comb", Abc_CommandComb, 1 );
@@ -8258,6 +8260,108 @@ usage:
SeeAlso []
***********************************************************************/
+int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ extern void Exa3_ManExactSynthesis( char * pTtStr, int nVars, int nNodes, int nLutSize, int fVerbose );
+ extern void Exa3_ManExactSynthesis2( char * pTtStr, int nVars, int nNodes, int nLutSize, int fVerbose );
+ int c, nVars = 5, nNodes = 5, nLutSize = 3, fGlucose = 0, fVerbose = 1; char * pTtStr = NULL;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "INKgvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nVars = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nVars < 0 )
+ goto usage;
+ break;
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nNodes = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nNodes < 0 )
+ goto usage;
+ break;
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLutSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLutSize < 0 )
+ goto usage;
+ break;
+ case 'g':
+ fGlucose ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( argc == globalUtilOptind + 1 )
+ pTtStr = argv[globalUtilOptind];
+ if ( pTtStr == NULL )
+ {
+ Abc_Print( -1, "Truth table should be given on the command line.\n" );
+ return 1;
+ }
+ if ( nVars > 10 )
+ {
+ Abc_Print( -1, "Function should not have more than 10 inputs.\n" );
+ return 1;
+ }
+ if ( nLutSize > 6 )
+ {
+ Abc_Print( -1, "Node size should not be more than 6 inputs.\n" );
+ return 1;
+ }
+ if ( fGlucose )
+ Exa3_ManExactSynthesis( pTtStr, nVars, nNodes, nLutSize, fVerbose );
+ else
+ Exa3_ManExactSynthesis2( pTtStr, nVars, nNodes, nLutSize, fVerbose );
+ return 0;
+
+usage:
+ Abc_Print( -2, "usage: lutexact [-INK <num>] [-fcgvh] <hex>\n" );
+ Abc_Print( -2, "\t exact synthesis of multi-input function using two-input gates\n" );
+ Abc_Print( -2, "\t-I <num> : the number of input variables [default = %d]\n", nVars );
+ Abc_Print( -2, "\t-N <num> : the number of K-input nodes [default = %d]\n", nNodes );
+ Abc_Print( -2, "\t-K <num> : the number of node fanins [default = %d]\n", nLutSize );
+ Abc_Print( -2, "\t-g : toggle using Glucose 3.0 by Gilles Audemard and Laurent Simon [default = %s]\n", fGlucose ? "yes" : "no" );
+ Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no" );
+ Abc_Print( -2, "\t-h : print the command usage\n" );
+ Abc_Print( -2, "\t<hex> : truth table in hex notation\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Abc_Ntk_t * pNtk, * pNtkRes;
diff --git a/src/sat/bmc/bmcMaj.c b/src/sat/bmc/bmcMaj.c
index e33dbf7b..463e9197 100644
--- a/src/sat/bmc/bmcMaj.c
+++ b/src/sat/bmc/bmcMaj.c
@@ -118,7 +118,7 @@ int Maj_ManMarkup( Maj_Man_t * p )
}
}
}
- //printf( "The number of parameter variables = %d.\n", p->iVar );
+ printf( "The number of parameter variables = %d.\n", p->iVar );
return p->iVar;
// printout
for ( i = p->nVars + 2; i < p->nObjs; i++ )
@@ -445,7 +445,7 @@ int Exa_ManMarkup( Exa_Man_t * p )
}
}
}
- //printf( "The number of parameter variables = %d.\n", p->iVar );
+ printf( "The number of parameter variables = %d.\n", p->iVar );
return p->iVar;
// printout
for ( i = p->nVars; i < p->nObjs; i++ )
@@ -736,6 +736,375 @@ void Exa_ManExactSynthesis( char * pTtStr, int nVars, int nNodes, int fVerbose )
Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal );
}
+
+
+
+typedef struct Exa3_Man_t_ Exa3_Man_t;
+struct Exa3_Man_t_
+{
+ int nVars; // inputs
+ int nNodes; // internal nodes
+ int nLutSize; // lut size
+ int LutMask; // lut mask
+ int nObjs; // total objects (nVars inputs + nNodes internal nodes)
+ int nWords; // the truth table size in 64-bit words
+ int iVar; // the next available SAT variable
+ word * pTruth; // truth table
+ Vec_Wrd_t * vInfo; // nVars + nNodes + 1
+ int VarMarks[MAJ_NOBJS][6][MAJ_NOBJS]; // variable marks
+ int VarVals[MAJ_NOBJS]; // values of the first nVars variables
+ Vec_Wec_t * vOutLits; // output vars
+ bmcg_sat_solver * pSat; // SAT solver
+};
+
+static inline word * Exa3_ManTruth( Exa3_Man_t * p, int v ) { return Vec_WrdEntryP( p->vInfo, p->nWords * v ); }
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Vec_Wrd_t * Exa3_ManTruthTables( Exa3_Man_t * p )
+{
+ Vec_Wrd_t * vInfo = p->vInfo = Vec_WrdStart( p->nWords * (p->nObjs+1) ); int i;
+ for ( i = 0; i < p->nVars; i++ )
+ Abc_TtIthVar( Exa3_ManTruth(p, i), i, p->nVars );
+ //Dau_DsdPrintFromTruth( Exa3_ManTruth(p, p->nObjs), p->nVars );
+ return vInfo;
+}
+static int Exa3_ManMarkup( Exa3_Man_t * p )
+{
+ int i, k, j;
+ assert( p->nObjs <= MAJ_NOBJS );
+ // assign variables for truth tables
+ p->iVar = 1 + p->LutMask * p->nNodes;
+ for ( i = p->nVars; i < p->nObjs; i++ )
+ {
+ for ( k = 0; k < p->nLutSize; k++ )
+ {
+ for ( j = 0; j < i - k; j++ )
+ {
+ Vec_WecPush( p->vOutLits, j, Abc_Var2Lit(p->iVar, 0) );
+ p->VarMarks[i][k][j] = p->iVar++;
+ }
+ }
+ }
+ printf( "The number of parameter variables = %d.\n", p->iVar );
+ return p->iVar;
+ // printout
+ for ( i = p->nVars; i < p->nObjs; i++ )
+ {
+ printf( "Node %d\n", i );
+ for ( j = 0; j < p->nObjs; j++ )
+ {
+ for ( k = 0; k < p->nLutSize; k++ )
+ printf( "%3d ", p->VarMarks[i][k][j] );
+ printf( "\n" );
+ }
+ }
+ return p->iVar;
+}
+static Exa3_Man_t * Exa3_ManAlloc( int nVars, int nNodes, int nLutSize, word * pTruth )
+{
+ Exa3_Man_t * p = ABC_CALLOC( Exa3_Man_t, 1 );
+ p->nVars = nVars;
+ p->nNodes = nNodes;
+ p->nLutSize = nLutSize;
+ p->LutMask = (1 << nLutSize) - 1;
+ p->nObjs = nVars + nNodes;
+ p->nWords = Abc_TtWordNum(nVars);
+ p->pTruth = pTruth;
+ p->vOutLits = Vec_WecStart( p->nObjs );
+ p->iVar = Exa3_ManMarkup( p );
+ p->vInfo = Exa3_ManTruthTables( p );
+ p->pSat = bmcg_sat_solver_start();
+ bmcg_sat_solver_set_nvars( p->pSat, p->iVar );
+ return p;
+}
+static void Exa3_ManFree( Exa3_Man_t * p )
+{
+ bmcg_sat_solver_stop( p->pSat );
+ Vec_WrdFree( p->vInfo );
+ Vec_WecFree( p->vOutLits );
+ ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Exa3_ManFindFanin( Exa3_Man_t * p, int i, int k )
+{
+ int j, Count = 0, iVar = -1;
+ for ( j = 0; j < p->nObjs; j++ )
+ if ( p->VarMarks[i][k][j] && bmcg_sat_solver_read_cex_varvalue(p->pSat, p->VarMarks[i][k][j]) )
+ {
+ iVar = j;
+ Count++;
+ }
+ assert( Count == 1 );
+ return iVar;
+}
+static inline int Exa3_ManEval( Exa3_Man_t * p )
+{
+ static int Flag = 0;
+ int i, k, j, iMint; word * pFanins[6];
+ for ( i = p->nVars; i < p->nObjs; i++ )
+ {
+ int iVarStart = 1 + p->LutMask*(i - p->nVars);
+ for ( k = 0; k < p->nLutSize; k++ )
+ pFanins[k] = Exa3_ManTruth( p, Exa3_ManFindFanin(p, i, k) );
+ Abc_TtConst0( Exa3_ManTruth(p, i), p->nWords );
+ for ( k = 1; k <= p->LutMask; k++ )
+ {
+ if ( !bmcg_sat_solver_read_cex_varvalue(p->pSat, iVarStart+k-1) )
+ continue;
+// Abc_TtAndCompl( Exa3_ManTruth(p, p->nObjs), pFanins[0], !(k&1), pFanins[1], !(k>>1), p->nWords );
+ Abc_TtConst1( Exa3_ManTruth(p, p->nObjs), p->nWords );
+ for ( j = 0; j < p->nLutSize; j++ )
+ Abc_TtAndCompl( Exa3_ManTruth(p, p->nObjs), Exa3_ManTruth(p, p->nObjs), 0, pFanins[j], !((k >> j) & 1), p->nWords );
+ Abc_TtOr( Exa3_ManTruth(p, i), Exa3_ManTruth(p, i), Exa3_ManTruth(p, p->nObjs), p->nWords );
+ }
+ }
+ if ( Flag && p->nVars >= 6 )
+ iMint = Abc_TtFindLastDiffBit( Exa3_ManTruth(p, p->nObjs-1), p->pTruth, p->nVars );
+ else
+ iMint = Abc_TtFindFirstDiffBit( Exa3_ManTruth(p, p->nObjs-1), p->pTruth, p->nVars );
+ //Flag ^= 1;
+ assert( iMint < (1 << p->nVars) );
+ return iMint;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Exa3_ManPrintSolution( Exa3_Man_t * p, int fCompl )
+{
+ int i, k, iVar;
+ printf( "Realization of given %d-input function using %d %d-input LUTs:\n", p->nVars, p->nNodes, p->nLutSize );
+ for ( i = p->nObjs - 1; i >= p->nVars; i-- )
+ {
+ int Val, iVarStart = 1 + p->LutMask*(i - p->nVars);
+ printf( "%02d = %d\'b", i, 1 << p->nLutSize );
+ for ( k = p->LutMask - 1; k >= 0; k-- )
+ {
+ Val = bmcg_sat_solver_read_cex_varvalue(p->pSat, iVarStart+k);
+ if ( i == p->nObjs - 1 && fCompl )
+ printf( "%d", !Val );
+ else
+ printf( "%d", Val );
+ }
+ if ( i == p->nObjs - 1 && fCompl )
+ printf( "1(" );
+ else
+ printf( "0(" );
+
+ for ( k = p->nLutSize - 1; k >= 0; k-- )
+ {
+ iVar = Exa3_ManFindFanin( p, i, k );
+ if ( iVar >= 0 && iVar < p->nVars )
+ printf( " %c", 'a'+iVar );
+ else
+ printf( " %02d", iVar );
+ }
+ printf( " )\n" );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Exa3_ManAddCnfStart( Exa3_Man_t * p )
+{
+ int pLits[MAJ_NOBJS], pLits2[2], i, j, k, n, m;
+ // input constraints
+ for ( i = p->nVars; i < p->nObjs; i++ )
+ {
+ int iVarStart = 1 + p->LutMask*(i - p->nVars);
+ for ( k = 0; k < p->nLutSize; k++ )
+ {
+ int nLits = 0;
+ for ( j = 0; j < p->nObjs; j++ )
+ if ( p->VarMarks[i][k][j] )
+ pLits[nLits++] = Abc_Var2Lit( p->VarMarks[i][k][j], 0 );
+ assert( nLits > 0 );
+ // input uniqueness
+ if ( !bmcg_sat_solver_addclause( p->pSat, pLits, nLits ) )
+ return 0;
+ for ( n = 0; n < nLits; n++ )
+ for ( m = n+1; m < nLits; m++ )
+ {
+ pLits2[0] = Abc_LitNot(pLits[n]);
+ pLits2[1] = Abc_LitNot(pLits[m]);
+ if ( !bmcg_sat_solver_addclause( p->pSat, pLits2, 2 ) )
+ return 0;
+ }
+ if ( k == p->nLutSize - 1 )
+ break;
+ // symmetry breaking
+ for ( j = 0; j < p->nObjs; j++ ) if ( p->VarMarks[i][k][j] )
+ for ( n = j; n < p->nObjs; n++ ) if ( p->VarMarks[i][k+1][n] )
+ {
+ pLits2[0] = Abc_Var2Lit( p->VarMarks[i][k][j], 1 );
+ pLits2[1] = Abc_Var2Lit( p->VarMarks[i][k+1][n], 1 );
+ if ( !bmcg_sat_solver_addclause( p->pSat, pLits2, 2 ) )
+ return 0;
+ }
+ }
+ if ( p->nLutSize != 2 )
+ continue;
+ // two-input functions
+ for ( k = 0; k < 3; k++ )
+ {
+ pLits[0] = Abc_Var2Lit( iVarStart, k==1 );
+ pLits[1] = Abc_Var2Lit( iVarStart+1, k==2 );
+ pLits[2] = Abc_Var2Lit( iVarStart+2, k!=0 );
+ if ( !bmcg_sat_solver_addclause( p->pSat, pLits, 3 ) )
+ return 0;
+ }
+ }
+ // outputs should be used
+ for ( i = 0; i < p->nObjs - 1; i++ )
+ {
+ Vec_Int_t * vArray = Vec_WecEntry(p->vOutLits, i);
+ assert( Vec_IntSize(vArray) > 0 );
+ if ( !bmcg_sat_solver_addclause( p->pSat, Vec_IntArray(vArray), Vec_IntSize(vArray) ) )
+ return 0;
+ }
+ return 1;
+}
+static int Exa3_ManAddCnf( Exa3_Man_t * p, int iMint )
+{
+ // save minterm values
+ int i, k, n, j, Value = Abc_TtGetBit(p->pTruth, iMint);
+ for ( i = 0; i < p->nVars; i++ )
+ p->VarVals[i] = (iMint >> i) & 1;
+// sat_solver_setnvars( p->pSat, p->iVar + (p->nLutSize+1)*p->nNodes );
+ bmcg_sat_solver_set_nvars( p->pSat, p->iVar + (p->nLutSize+1)*p->nNodes );
+ //printf( "Adding clauses for minterm %d with value %d.\n", iMint, Value );
+ for ( i = p->nVars; i < p->nObjs; i++ )
+ {
+ // fanin connectivity
+ int iVarStart = 1 + p->LutMask*(i - p->nVars);
+ int iBaseSatVarI = p->iVar + (p->nLutSize+1)*(i - p->nVars);
+ for ( k = 0; k < p->nLutSize; k++ )
+ {
+ for ( j = 0; j < p->nObjs; j++ ) if ( p->VarMarks[i][k][j] )
+ {
+ int iBaseSatVarJ = p->iVar + (p->nLutSize+1)*(j - p->nVars);
+ for ( n = 0; n < 2; n++ )
+ {
+ int pLits[3], nLits = 0;
+ pLits[nLits++] = Abc_Var2Lit( p->VarMarks[i][k][j], 1 );
+ pLits[nLits++] = Abc_Var2Lit( iBaseSatVarI + k, n );
+ if ( j >= p->nVars )
+ pLits[nLits++] = Abc_Var2Lit( iBaseSatVarJ + p->nLutSize, !n );
+ else if ( p->VarVals[j] == n )
+ continue;
+ if ( !bmcg_sat_solver_addclause( p->pSat, pLits, nLits ) )
+ return 0;
+ }
+ }
+ }
+ // node functionality
+ for ( n = 0; n < 2; n++ )
+ {
+ if ( i == p->nObjs - 1 && n == Value )
+ continue;
+ for ( k = 0; k <= p->LutMask; k++ )
+ {
+ int pLits[8], nLits = 0;
+ if ( k == 0 && n == 1 )
+ continue;
+ //pLits[nLits++] = Abc_Var2Lit( iBaseSatVarI + 0, (k&1) );
+ //pLits[nLits++] = Abc_Var2Lit( iBaseSatVarI + 1, (k>>1) );
+ //if ( i != p->nObjs - 1 ) pLits[nLits++] = Abc_Var2Lit( iBaseSatVarI + 2, !n );
+ for ( j = 0; j < p->nLutSize; j++ )
+ pLits[nLits++] = Abc_Var2Lit( iBaseSatVarI + j, (k >> j) & 1 );
+ if ( i != p->nObjs - 1 ) pLits[nLits++] = Abc_Var2Lit( iBaseSatVarI + j, !n );
+ if ( k > 0 ) pLits[nLits++] = Abc_Var2Lit( iVarStart + k-1, n );
+ assert( nLits <= p->nLutSize+2 );
+ if ( !bmcg_sat_solver_addclause( p->pSat, pLits, nLits ) )
+ return 0;
+ }
+ }
+ }
+ p->iVar += (p->nLutSize+1)*p->nNodes;
+ return 1;
+}
+void Exa3_ManExactSynthesis( char * pTtStr, int nVars, int nNodes, int nLutSize, int fVerbose )
+{
+ int i, status, iMint = 1;
+ abctime clkTotal = Abc_Clock();
+ Exa3_Man_t * p; int fCompl = 0;
+ word pTruth[16]; Abc_TtReadHex( pTruth, pTtStr );
+ assert( nVars <= 10 );
+ assert( nLutSize <= 6 );
+ p = Exa3_ManAlloc( nVars, nNodes, nLutSize, pTruth );
+ if ( pTruth[0] & 1 ) { fCompl = 1; Abc_TtNot( pTruth, p->nWords ); }
+ status = Exa3_ManAddCnfStart( p );
+ assert( status );
+ printf( "Running exact synthesis for %d-input function with %d %d-input LUTs...\n", p->nVars, p->nNodes, p->nLutSize );
+ for ( i = 0; iMint != -1; i++ )
+ {
+ abctime clk = Abc_Clock();
+ if ( !Exa3_ManAddCnf( p, iMint ) )
+ break;
+ status = bmcg_sat_solver_solve( p->pSat, NULL, 0 );
+ if ( fVerbose )
+ {
+ printf( "Iter %3d : ", i );
+ Extra_PrintBinary( stdout, (unsigned *)&iMint, p->nVars );
+ printf( " Var =%5d ", p->iVar );
+ printf( "Cla =%6d ", bmcg_sat_solver_clausenum(p->pSat) );
+ printf( "Conf =%9d ", bmcg_sat_solver_conflictnum(p->pSat) );
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+ }
+ if ( status == GLUCOSE_UNSAT )
+ {
+ printf( "The problem has no solution.\n" );
+ break;
+ }
+ iMint = Exa3_ManEval( p );
+ }
+ if ( iMint == -1 )
+ Exa3_ManPrintSolution( p, fCompl );
+ Exa3_ManFree( p );
+ Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal );
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/sat/bmc/bmcMaj2.c b/src/sat/bmc/bmcMaj2.c
index 1679e7e5..1c61fec1 100644
--- a/src/sat/bmc/bmcMaj2.c
+++ b/src/sat/bmc/bmcMaj2.c
@@ -198,7 +198,7 @@ static int Maj_ManMarkup( Maj_Man_t * p )
}
}
}
- //printf( "The number of parameter variables = %d.\n", p->iVar );
+ printf( "The number of parameter variables = %d.\n", p->iVar );
if ( !p->fVerbose )
return p->iVar;
// printout
@@ -540,7 +540,6 @@ static int Exa_ManMarkup( Exa_Man_t * p )
assert( p->nObjs <= MAJ_NOBJS );
// assign variables for truth tables
p->iVar = 1 + p->nNodes * 3;
- // assign variables for other nodes
for ( i = p->nVars; i < p->nObjs; i++ )
{
for ( k = 0; k < 2; k++ )
@@ -552,7 +551,7 @@ static int Exa_ManMarkup( Exa_Man_t * p )
}
}
}
- //printf( "The number of parameter variables = %d.\n", p->iVar );
+ printf( "The number of parameter variables = %d.\n", p->iVar );
return p->iVar;
// printout
for ( i = p->nVars; i < p->nObjs; i++ )
@@ -843,6 +842,386 @@ void Exa_ManExactSynthesis2( char * pTtStr, int nVars, int nNodes, int fVerbose
Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal );
}
+
+
+
+
+
+typedef struct Exa3_Man_t_ Exa3_Man_t;
+struct Exa3_Man_t_
+{
+ int nVars; // inputs
+ int nNodes; // internal nodes
+ int nLutSize; // lut size
+ int LutMask; // lut mask
+ int nObjs; // total objects (nVars inputs + nNodes internal nodes)
+ int nWords; // the truth table size in 64-bit words
+ int iVar; // the next available SAT variable
+ word * pTruth; // truth table
+ Vec_Wrd_t * vInfo; // nVars + nNodes + 1
+ int VarMarks[MAJ_NOBJS][6][MAJ_NOBJS]; // variable marks
+ int VarVals[MAJ_NOBJS]; // values of the first nVars variables
+ Vec_Wec_t * vOutLits; // output vars
+ sat_solver * pSat; // SAT solver
+};
+
+static inline word * Exa3_ManTruth( Exa3_Man_t * p, int v ) { return Vec_WrdEntryP( p->vInfo, p->nWords * v ); }
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Vec_Wrd_t * Exa3_ManTruthTables( Exa3_Man_t * p )
+{
+ Vec_Wrd_t * vInfo = p->vInfo = Vec_WrdStart( p->nWords * (p->nObjs+1) ); int i;
+ for ( i = 0; i < p->nVars; i++ )
+ Abc_TtIthVar( Exa3_ManTruth(p, i), i, p->nVars );
+ //Dau_DsdPrintFromTruth( Exa3_ManTruth(p, p->nObjs), p->nVars );
+ return vInfo;
+}
+static int Exa3_ManMarkup( Exa3_Man_t * p )
+{
+ int i, k, j;
+ assert( p->nObjs <= MAJ_NOBJS );
+ // assign variables for truth tables
+ p->iVar = 1 + p->LutMask * p->nNodes;
+ for ( i = p->nVars; i < p->nObjs; i++ )
+ {
+ for ( k = 0; k < p->nLutSize; k++ )
+ {
+ for ( j = 0; j < i - k; j++ )
+ {
+ Vec_WecPush( p->vOutLits, j, Abc_Var2Lit(p->iVar, 0) );
+ p->VarMarks[i][k][j] = p->iVar++;
+ }
+ }
+ }
+ printf( "The number of parameter variables = %d.\n", p->iVar );
+ return p->iVar;
+ // printout
+ for ( i = p->nVars; i < p->nObjs; i++ )
+ {
+ printf( "Node %d\n", i );
+ for ( j = 0; j < p->nObjs; j++ )
+ {
+ for ( k = 0; k < p->nLutSize; k++ )
+ printf( "%3d ", p->VarMarks[i][k][j] );
+ printf( "\n" );
+ }
+ }
+ return p->iVar;
+}
+static Exa3_Man_t * Exa3_ManAlloc( int nVars, int nNodes, int nLutSize, word * pTruth )
+{
+ Exa3_Man_t * p = ABC_CALLOC( Exa3_Man_t, 1 );
+ p->nVars = nVars;
+ p->nNodes = nNodes;
+ p->nLutSize = nLutSize;
+ p->LutMask = (1 << nLutSize) - 1;
+ p->nObjs = nVars + nNodes;
+ p->nWords = Abc_TtWordNum(nVars);
+ p->pTruth = pTruth;
+ p->vOutLits = Vec_WecStart( p->nObjs );
+ p->iVar = Exa3_ManMarkup( p );
+ p->vInfo = Exa3_ManTruthTables( p );
+ p->pSat = sat_solver_new();
+ sat_solver_setnvars( p->pSat, p->iVar );
+ return p;
+}
+static void Exa3_ManFree( Exa3_Man_t * p )
+{
+ sat_solver_delete( p->pSat );
+ Vec_WrdFree( p->vInfo );
+ Vec_WecFree( p->vOutLits );
+ ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Exa3_ManFindFanin( Exa3_Man_t * p, int i, int k )
+{
+ int j, Count = 0, iVar = -1;
+ for ( j = 0; j < p->nObjs; j++ )
+ if ( p->VarMarks[i][k][j] && sat_solver_var_value(p->pSat, p->VarMarks[i][k][j]) )
+ {
+ iVar = j;
+ Count++;
+ }
+ assert( Count == 1 );
+ return iVar;
+}
+static inline int Exa3_ManEval( Exa3_Man_t * p )
+{
+ static int Flag = 0;
+ int i, k, j, iMint; word * pFanins[6];
+ for ( i = p->nVars; i < p->nObjs; i++ )
+ {
+ int iVarStart = 1 + p->LutMask*(i - p->nVars);
+ for ( k = 0; k < p->nLutSize; k++ )
+ pFanins[k] = Exa3_ManTruth( p, Exa3_ManFindFanin(p, i, k) );
+ Abc_TtConst0( Exa3_ManTruth(p, i), p->nWords );
+ for ( k = 1; k <= p->LutMask; k++ )
+ {
+ if ( !sat_solver_var_value(p->pSat, iVarStart+k-1) )
+ continue;
+// Abc_TtAndCompl( Exa3_ManTruth(p, p->nObjs), pFanins[0], !(k&1), pFanins[1], !(k>>1), p->nWords );
+ Abc_TtConst1( Exa3_ManTruth(p, p->nObjs), p->nWords );
+ for ( j = 0; j < p->nLutSize; j++ )
+ Abc_TtAndCompl( Exa3_ManTruth(p, p->nObjs), Exa3_ManTruth(p, p->nObjs), 0, pFanins[j], !((k >> j) & 1), p->nWords );
+ Abc_TtOr( Exa3_ManTruth(p, i), Exa3_ManTruth(p, i), Exa3_ManTruth(p, p->nObjs), p->nWords );
+ }
+ }
+ if ( Flag && p->nVars >= 6 )
+ iMint = Abc_TtFindLastDiffBit( Exa3_ManTruth(p, p->nObjs-1), p->pTruth, p->nVars );
+ else
+ iMint = Abc_TtFindFirstDiffBit( Exa3_ManTruth(p, p->nObjs-1), p->pTruth, p->nVars );
+ //Flag ^= 1;
+ assert( iMint < (1 << p->nVars) );
+ return iMint;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Exa3_ManPrintSolution( Exa3_Man_t * p, int fCompl )
+{
+ int i, k, iVar;
+ printf( "Realization of given %d-input function using %d %d-input LUTs:\n", p->nVars, p->nNodes, p->nLutSize );
+ for ( i = p->nObjs - 1; i >= p->nVars; i-- )
+ {
+ int Val, iVarStart = 1 + p->LutMask*(i - p->nVars);
+
+// int Val1 = sat_solver_var_value(p->pSat, iVarStart);
+// int Val2 = sat_solver_var_value(p->pSat, iVarStart+1);
+// int Val3 = sat_solver_var_value(p->pSat, iVarStart+2);
+// if ( i == p->nObjs - 1 && fCompl )
+// printf( "%02d = 4\'b%d%d%d1(", i, !Val3, !Val2, !Val1 );
+// else
+// printf( "%02d = 4\'b%d%d%d0(", i, Val3, Val2, Val1 );
+
+ printf( "%02d = %d\'b", i, 1 << p->nLutSize );
+ for ( k = p->LutMask - 1; k >= 0; k-- )
+ {
+ Val = sat_solver_var_value(p->pSat, iVarStart+k);
+ if ( i == p->nObjs - 1 && fCompl )
+ printf( "%d", !Val );
+ else
+ printf( "%d", Val );
+ }
+ if ( i == p->nObjs - 1 && fCompl )
+ printf( "1(" );
+ else
+ printf( "0(" );
+
+ for ( k = p->nLutSize - 1; k >= 0; k-- )
+ {
+ iVar = Exa3_ManFindFanin( p, i, k );
+ if ( iVar >= 0 && iVar < p->nVars )
+ printf( " %c", 'a'+iVar );
+ else
+ printf( " %02d", iVar );
+ }
+ printf( " )\n" );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Exa3_ManAddCnfStart( Exa3_Man_t * p )
+{
+ int pLits[MAJ_NOBJS], pLits2[2], i, j, k, n, m;
+ // input constraints
+ for ( i = p->nVars; i < p->nObjs; i++ )
+ {
+ int iVarStart = 1 + p->LutMask*(i - p->nVars);
+ for ( k = 0; k < p->nLutSize; k++ )
+ {
+ int nLits = 0;
+ for ( j = 0; j < p->nObjs; j++ )
+ if ( p->VarMarks[i][k][j] )
+ pLits[nLits++] = Abc_Var2Lit( p->VarMarks[i][k][j], 0 );
+ assert( nLits > 0 );
+ // input uniqueness
+ if ( !sat_solver_addclause( p->pSat, pLits, pLits+nLits ) )
+ return 0;
+ for ( n = 0; n < nLits; n++ )
+ for ( m = n+1; m < nLits; m++ )
+ {
+ pLits2[0] = Abc_LitNot(pLits[n]);
+ pLits2[1] = Abc_LitNot(pLits[m]);
+ if ( !sat_solver_addclause( p->pSat, pLits2, pLits2+2 ) )
+ return 0;
+ }
+ if ( k == p->nLutSize - 1 )
+ break;
+ // symmetry breaking
+ for ( j = 0; j < p->nObjs; j++ ) if ( p->VarMarks[i][k][j] )
+ for ( n = j; n < p->nObjs; n++ ) if ( p->VarMarks[i][k+1][n] )
+ {
+ pLits2[0] = Abc_Var2Lit( p->VarMarks[i][k][j], 1 );
+ pLits2[1] = Abc_Var2Lit( p->VarMarks[i][k+1][n], 1 );
+ if ( !sat_solver_addclause( p->pSat, pLits2, pLits2+2 ) )
+ return 0;
+ }
+ }
+ if ( p->nLutSize != 2 )
+ continue;
+ // two-input functions
+ for ( k = 0; k < 3; k++ )
+ {
+ pLits[0] = Abc_Var2Lit( iVarStart, k==1 );
+ pLits[1] = Abc_Var2Lit( iVarStart+1, k==2 );
+ pLits[2] = Abc_Var2Lit( iVarStart+2, k!=0 );
+ if ( !sat_solver_addclause( p->pSat, pLits, pLits+3 ) )
+ return 0;
+ }
+ }
+ // outputs should be used
+ for ( i = 0; i < p->nObjs - 1; i++ )
+ {
+ Vec_Int_t * vArray = Vec_WecEntry(p->vOutLits, i);
+ assert( Vec_IntSize(vArray) > 0 );
+ if ( !sat_solver_addclause( p->pSat, Vec_IntArray(vArray), Vec_IntLimit(vArray) ) )
+ return 0;
+ }
+ return 1;
+}
+static int Exa3_ManAddCnf( Exa3_Man_t * p, int iMint )
+{
+ // save minterm values
+ int i, k, n, j, Value = Abc_TtGetBit(p->pTruth, iMint);
+ for ( i = 0; i < p->nVars; i++ )
+ p->VarVals[i] = (iMint >> i) & 1;
+ sat_solver_setnvars( p->pSat, p->iVar + (p->nLutSize+1)*p->nNodes );
+ //printf( "Adding clauses for minterm %d with value %d.\n", iMint, Value );
+ for ( i = p->nVars; i < p->nObjs; i++ )
+ {
+ // fanin connectivity
+ int iVarStart = 1 + p->LutMask*(i - p->nVars);
+ int iBaseSatVarI = p->iVar + (p->nLutSize+1)*(i - p->nVars);
+ for ( k = 0; k < p->nLutSize; k++ )
+ {
+ for ( j = 0; j < p->nObjs; j++ ) if ( p->VarMarks[i][k][j] )
+ {
+ int iBaseSatVarJ = p->iVar + (p->nLutSize+1)*(j - p->nVars);
+ for ( n = 0; n < 2; n++ )
+ {
+ int pLits[3], nLits = 0;
+ pLits[nLits++] = Abc_Var2Lit( p->VarMarks[i][k][j], 1 );
+ pLits[nLits++] = Abc_Var2Lit( iBaseSatVarI + k, n );
+ if ( j >= p->nVars )
+ pLits[nLits++] = Abc_Var2Lit( iBaseSatVarJ + p->nLutSize, !n );
+ else if ( p->VarVals[j] == n )
+ continue;
+ if ( !sat_solver_addclause( p->pSat, pLits, pLits+nLits ) )
+ return 0;
+ }
+ }
+ }
+ // node functionality
+ for ( n = 0; n < 2; n++ )
+ {
+ if ( i == p->nObjs - 1 && n == Value )
+ continue;
+ for ( k = 0; k <= p->LutMask; k++ )
+ {
+ int pLits[8], nLits = 0;
+ if ( k == 0 && n == 1 )
+ continue;
+ //pLits[nLits++] = Abc_Var2Lit( iBaseSatVarI + 0, (k&1) );
+ //pLits[nLits++] = Abc_Var2Lit( iBaseSatVarI + 1, (k>>1) );
+ //if ( i != p->nObjs - 1 ) pLits[nLits++] = Abc_Var2Lit( iBaseSatVarI + 2, !n );
+ for ( j = 0; j < p->nLutSize; j++ )
+ pLits[nLits++] = Abc_Var2Lit( iBaseSatVarI + j, (k >> j) & 1 );
+ if ( i != p->nObjs - 1 ) pLits[nLits++] = Abc_Var2Lit( iBaseSatVarI + j, !n );
+ if ( k > 0 ) pLits[nLits++] = Abc_Var2Lit( iVarStart + k-1, n );
+ assert( nLits <= p->nLutSize+2 );
+ if ( !sat_solver_addclause( p->pSat, pLits, pLits+nLits ) )
+ return 0;
+ }
+ }
+ }
+ p->iVar += (p->nLutSize+1)*p->nNodes;
+ return 1;
+}
+void Exa3_ManExactSynthesis2( char * pTtStr, int nVars, int nNodes, int nLutSize, int fVerbose )
+{
+ int i, status, iMint = 1;
+ abctime clkTotal = Abc_Clock();
+ Exa3_Man_t * p; int fCompl = 0;
+ word pTruth[16]; Abc_TtReadHex( pTruth, pTtStr );
+ assert( nVars <= 10 );
+ assert( nLutSize <= 6 );
+ p = Exa3_ManAlloc( nVars, nNodes, nLutSize, pTruth );
+ if ( pTruth[0] & 1 ) { fCompl = 1; Abc_TtNot( pTruth, p->nWords ); }
+ status = Exa3_ManAddCnfStart( p );
+ assert( status );
+ printf( "Running exact synthesis for %d-input function with %d %d-input LUTs...\n", p->nVars, p->nNodes, p->nLutSize );
+ for ( i = 0; iMint != -1; i++ )
+ {
+ abctime clk = Abc_Clock();
+ if ( !Exa3_ManAddCnf( p, iMint ) )
+ break;
+ status = sat_solver_solve( p->pSat, NULL, NULL, 0, 0, 0, 0 );
+ if ( fVerbose )
+ {
+ printf( "Iter %3d : ", i );
+ Extra_PrintBinary( stdout, (unsigned *)&iMint, p->nVars );
+ printf( " Var =%5d ", p->iVar );
+ printf( "Cla =%6d ", sat_solver_nclauses(p->pSat) );
+ printf( "Conf =%9d ", sat_solver_nconflicts(p->pSat) );
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+ }
+ if ( status == l_False )
+ {
+ printf( "The problem has no solution.\n" );
+ break;
+ }
+ iMint = Exa3_ManEval( p );
+ }
+ if ( iMint == -1 )
+ Exa3_ManPrintSolution( p, fCompl );
+ Exa3_ManFree( p );
+ Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal );
+}
+
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////