From 3f35ac8180bf69655662c2ccd2de9411b3533cf4 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 5 Dec 2017 18:22:27 -0800 Subject: New command 'lutexact'. --- src/base/abci/abc.c | 104 ++++++++++++++ src/sat/bmc/bmcMaj.c | 373 +++++++++++++++++++++++++++++++++++++++++++++++- src/sat/bmc/bmcMaj2.c | 385 +++++++++++++++++++++++++++++++++++++++++++++++++- 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 ); @@ -8247,6 +8249,108 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + 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 ] [-fcgvh] \n" ); + Abc_Print( -2, "\t exact synthesis of multi-input function using two-input gates\n" ); + Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", nVars ); + Abc_Print( -2, "\t-N : the number of K-input nodes [default = %d]\n", nNodes ); + Abc_Print( -2, "\t-K : 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 : truth table in hex notation\n" ); + return 1; +} + /**Function************************************************************* Synopsis [] 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 /// //////////////////////////////////////////////////////////////////////// -- cgit v1.2.3