summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2017-10-01 18:00:09 +0300
committerAlan Mishchenko <alanmi@berkeley.edu>2017-10-01 18:00:09 +0300
commitd3152aefa7af3a1173647b678959f70d935ae707 (patch)
treea06b823d6cd5f6a3696dea427f5f179a5a700a62
parentc696ae95d0130204bedfb9cb7209748fa6ab0f2e (diff)
downloadabc-d3152aefa7af3a1173647b678959f70d935ae707.tar.gz
abc-d3152aefa7af3a1173647b678959f70d935ae707.tar.bz2
abc-d3152aefa7af3a1173647b678959f70d935ae707.zip
Exact synthesis of majority gates.
-rw-r--r--abclib.dsp4
-rw-r--r--src/base/abci/abc.c75
-rw-r--r--src/misc/util/utilTruth.h215
-rw-r--r--src/sat/bmc/bmcMaj.c373
-rw-r--r--src/sat/bmc/module.make1
5 files changed, 667 insertions, 1 deletions
diff --git a/abclib.dsp b/abclib.dsp
index f07aae07..0fef02ac 100644
--- a/abclib.dsp
+++ b/abclib.dsp
@@ -2019,6 +2019,10 @@ SOURCE=.\src\sat\bmc\bmcLoad.c
# End Source File
# Begin Source File
+SOURCE=.\src\sat\bmc\bmcMaj.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\sat\bmc\bmcMaxi.c
# End Source File
# Begin Source File
diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c
index d7cf43ba..5caf8145 100644
--- a/src/base/abci/abc.c
+++ b/src/base/abci/abc.c
@@ -149,6 +149,7 @@ static int Abc_CommandExact ( Abc_Frame_t * pAbc, int argc, cha
static int Abc_CommandBmsStart ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandBmsStop ( Abc_Frame_t * pAbc, int argc, char ** argv );
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_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandComb ( Abc_Frame_t * pAbc, int argc, char ** argv );
@@ -815,6 +816,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_start", Abc_CommandBmsStart, 0 );
Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_stop", Abc_CommandBmsStop, 0 );
Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_ps", Abc_CommandBmsPs, 0 );
+ Cmd_CommandAdd( pAbc, "Exact synthesis", "majexact", Abc_CommandMajExact, 0 );
Cmd_CommandAdd( pAbc, "Various", "logic", Abc_CommandLogic, 1 );
Cmd_CommandAdd( pAbc, "Various", "comb", Abc_CommandComb, 1 );
@@ -8068,6 +8070,79 @@ usage:
SeeAlso []
***********************************************************************/
+int Abc_CommandMajExact( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ extern void Maj_ManExactSynthesis( int nVars, int nNodes, int fUseConst, int fVerbose );
+ int c, nVars = 3, nNodes = 1, fUseConst = 0, fVerbose = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "NMcvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nVars = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nVars < 0 )
+ goto usage;
+ break;
+ case 'M':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nNodes = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nNodes < 0 )
+ goto usage;
+ break;
+ case 'c':
+ fUseConst ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( (nVars & 1) == 0 )
+ {
+ Abc_Print( -1, "Cannot sythesize MAJ gate with an even number of inputs (%d).\n", nVars );
+ return 1;
+ }
+ Maj_ManExactSynthesis( nVars, nNodes, fUseConst, fVerbose );
+ return 0;
+
+usage:
+ Abc_Print( -2, "usage: majexact [-NM <num>] [-cvh]\n" );
+ Abc_Print( -2, "\t exactly synthesizes N-input MAJ using MAJ3 gates\n" );
+ Abc_Print( -2, "\t-N <num> : the number of input variables [default = %d]\n", nVars );
+ Abc_Print( -2, "\t-M <num> : the number of MAJ3 nodes [default = %d]\n", nNodes );
+ Abc_Print( -2, "\t-c : toggle using constant fanins [default = %s]\n", fUseConst ? "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" );
+ 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/misc/util/utilTruth.h b/src/misc/util/utilTruth.h
index 1c03d4c7..3a9eb7c1 100644
--- a/src/misc/util/utilTruth.h
+++ b/src/misc/util/utilTruth.h
@@ -332,6 +332,12 @@ static inline void Abc_TtMux( word * pOut, word * pCtrl, word * pIn1, word * pIn
for ( w = 0; w < nWords; w++ )
pOut[w] = (pCtrl[w] & pIn1[w]) | (~pCtrl[w] & pIn0[w]);
}
+static inline void Abc_TtMaj( word * pOut, word * pIn0, word * pIn1, word * pIn2, int nWords )
+{
+ int w;
+ for ( w = 0; w < nWords; w++ )
+ pOut[w] = (pIn0[w] & pIn1[w]) | (pIn0[w] & pIn2[w]) | (pIn1[w] & pIn2[w]);
+}
static inline int Abc_TtIntersect( word * pIn1, word * pIn2, int nWords, int fCompl )
{
int w;
@@ -417,7 +423,24 @@ static inline void Abc_TtConst1( word * pIn1, int nWords )
for ( w = 0; w < nWords; w++ )
pIn1[w] = ~(word)0;
}
-
+static inline void Abc_TtIthVar( word * pOut, int iVar, int nVars )
+{
+ int k, nWords = Abc_TtWordNum( nVars );
+ if ( iVar < 6 )
+ {
+ for ( k = 0; k < nWords; k++ )
+ pOut[k] = s_Truths6[iVar];
+ }
+ else
+ {
+ for ( k = 0; k < nWords; k++ )
+ if ( k & (1 << (iVar-6)) )
+ pOut[k] = ~(word)0;
+ else
+ pOut[k] = 0;
+ }
+}
+
/**Function*************************************************************
Synopsis [Compares Cof0 and Cof1.]
@@ -2339,6 +2362,145 @@ static inline int Abc_TtCheckOutAnd( word t, int i, word * pOut )
}
return -1;
}
+static inline int Abc_TtCheckOutAnd7( word * t, int i, word * pOut )
+{
+ assert( i < 7 );
+ if ( i == 6 )
+ {
+ word c0 = t[0];
+ word c1 = t[1];
+ assert( c0 != c1 );
+ if ( c0 == 0 ) // F = i * G
+ {
+ if ( pOut ) pOut[0] = pOut[1] = c1;
+ return 0;
+ }
+ if ( c1 == 0 ) // F = ~i * G
+ {
+ if ( pOut ) pOut[0] = pOut[1] = c0;
+ return 1;
+ }
+ if ( ~c0 == 0 ) // F = ~i + G
+ {
+ if ( pOut ) pOut[0] = pOut[1] = c1;
+ return 2;
+ }
+ if ( ~c1 == 0 ) // F = i + G
+ {
+ if ( pOut ) pOut[0] = pOut[1] = c0;
+ return 3;
+ }
+ if ( c0 == ~c1 ) // F = i # G
+ {
+ if ( pOut ) pOut[0] = pOut[1] = c0;
+ return 4;
+ }
+ }
+ else
+ {
+ int k, Res[2];
+ for ( k = 0; k < 2; k++ )
+ if ( (Res[k] = Abc_TtCheckOutAnd(t[k], i, pOut+k)) == -1 || Res[0] != Res[k] )
+ return -1;
+ return Res[0];
+ }
+ return -1;
+}
+static inline int Abc_TtCheckOutAnd8( word * t, int i, word * pOut )
+{
+ assert( i < 8 );
+ if ( i == 7 )
+ {
+ word * c0 = t;
+ word * c1 = t + 2;
+ assert( c0[0] != c1[0] || c0[1] != c1[1] );
+ if ( c0[0] == 0 && c0[1] == 0 ) // F = i * G
+ {
+ if ( pOut ) pOut[0] = pOut[2] = c1[0], pOut[1] = pOut[3] = c1[1];
+ return 0;
+ }
+ if ( c1[0] == 0 && c1[1] == 0 ) // F = ~i * G
+ {
+ if ( pOut ) pOut[0] = pOut[2] = c0[0], pOut[1] = pOut[3] = c0[1];
+ return 1;
+ }
+ if ( ~c0[0] == 0 && ~c0[1] == 0 ) // F = ~i + G
+ {
+ if ( pOut ) pOut[0] = pOut[2] = c1[0], pOut[1] = pOut[3] = c1[1];
+ return 2;
+ }
+ if ( ~c1[0] == 0 && ~c1[1] == 0 ) // F = i + G
+ {
+ if ( pOut ) pOut[0] = pOut[2] = c0[0], pOut[1] = pOut[3] = c0[1];
+ return 3;
+ }
+ if ( c0[0] == ~c1[0] && c0[1] == ~c1[1] ) // F = i # G
+ {
+ if ( pOut ) pOut[0] = pOut[2] = c0[0], pOut[1] = pOut[3] = c0[1];
+ return 4;
+ }
+ }
+ else if ( i == 6 )
+ {
+ int k, Res[2];
+ for ( k = 0; k < 2; k++ )
+ if ( (Res[k] = Abc_TtCheckOutAnd7(t+2*k, i, pOut+2*k)) == -1 || Res[0] != Res[k] )
+ return -1;
+ return Res[0];
+ }
+ else
+ {
+ int k, Res[4];
+ for ( k = 0; k < 4; k++ )
+ if ( (Res[k] = Abc_TtCheckOutAnd(t[k], i, pOut+k)) == -1 || Res[0] != Res[k] )
+ return -1;
+ return Res[0];
+ }
+ return -1;
+}
+static inline word Abc_TtCheckDecOutOne7( word * t, int * piVar, int * pType )
+{
+ int v, Type, Type2; word Out;
+ for ( v = 6; v >= 0; v-- )
+ if ( (Type = Abc_TtCheckOutAnd7(t, v, NULL)) != -1 )
+ {
+ Abc_TtSwapVars( t, 7, v, 6 );
+ Type2 = Abc_TtCheckOutAnd7(t, 6, &Out);
+ assert( Type == Type2 );
+ *piVar = v;
+ *pType = Type;
+ return Out;
+ }
+ return 0;
+}
+static inline word Abc_TtCheckDecOutOne8( word * t, int * piVar1, int * piVar2, int * pType1, int * pType2 )
+{
+ int v, Type1, Type12, Type2, Type22; word Out[2], Out2;
+ for ( v = 7; v >= 0; v-- )
+ if ( (Type1 = Abc_TtCheckOutAnd8(t, v, NULL)) != -1 )
+ {
+ Abc_TtSwapVars( t, 8, v, 7 );
+ Type12 = Abc_TtCheckOutAnd8(t, 7, Out);
+ assert( Type1 == Type12 );
+ *piVar1 = v;
+ *piVar2 = Type1;
+ break;
+ }
+ if ( v == -1 )
+ return 0;
+ for ( v = 6; v >= 0; v-- )
+ if ( (Type2 = Abc_TtCheckOutAnd7(Out, v, NULL)) != -1 && Abc_Lit2Var(Type2) == Abc_Lit2Var(Type1) )
+ {
+ Abc_TtSwapVars( Out, 7, v, 6 );
+ Type22 = Abc_TtCheckOutAnd7(t, 6, &Out2);
+ assert( Type2 == Type22 );
+ *piVar2 = v;
+ *pType2 = Type2;
+ assert( *piVar2 < *piVar1 );
+ return Out2;
+ }
+ return 0;
+}
/**Function*************************************************************
@@ -2536,6 +2698,57 @@ static inline void Unm_ManCheckTest()
}
+/**Function*************************************************************
+
+ Synopsis [Truth table evaluation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline word Abc_TtEvalLut6( word Ins[6], word Lut, int nVars )
+{
+ word Cube, Res = 0; int k, i;
+ for ( k = 0; k < (1<<nVars); k++ )
+ {
+ if ( ((Lut >> k) & 1) == 0 )
+ continue;
+ Cube = ~(word)0;
+ for ( i = 0; i < nVars; i++ )
+ Cube &= ((k >> i) & 1) ? Ins[i] : ~Ins[i];
+ }
+ return Res;
+}
+static inline unsigned Abc_TtEvalLut5( unsigned Ins[5], int Lut, int nVars )
+{
+ unsigned Cube, Res = 0; int k, i;
+ for ( k = 0; k < (1<<nVars); k++ )
+ {
+ if ( ((Lut >> k) & 1) == 0 )
+ continue;
+ Cube = ~(unsigned)0;
+ for ( i = 0; i < nVars; i++ )
+ Cube &= ((k >> i) & 1) ? Ins[i] : ~Ins[i];
+ }
+ return Res;
+}
+static inline int Abc_TtEvalLut4( int Ins[4], int Lut, int nVars )
+{
+ int Cube, Res = 0; int k, i;
+ for ( k = 0; k < (1<<nVars); k++ )
+ {
+ if ( ((Lut >> k) & 1) == 0 )
+ continue;
+ Cube = ~(int)0;
+ for ( i = 0; i < nVars; i++ )
+ Cube &= ((k >> i) & 1) ? Ins[i] : ~Ins[i];
+ }
+ return Res & ~(~0 << (1<<nVars));
+}
+
/**Function*************************************************************
diff --git a/src/sat/bmc/bmcMaj.c b/src/sat/bmc/bmcMaj.c
new file mode 100644
index 00000000..d22a38c9
--- /dev/null
+++ b/src/sat/bmc/bmcMaj.c
@@ -0,0 +1,373 @@
+/**CFile****************************************************************
+
+ FileName [bmcMaj.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [SAT-based bounded model checking.]
+
+ Synopsis [Exact synthesis with majority gates.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - October 1, 2017.]
+
+ Revision [$Id: bmcMaj.c,v 1.00 2017/10/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bmc.h"
+#include "misc/util/utilTruth.h"
+#include "sat/glucose/AbcGlucose.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define MAJ_NOBJS 32 // Const0 + Const1 + nVars + nNodes
+
+typedef struct Maj_Man_t_ Maj_Man_t;
+struct Maj_Man_t_
+{
+ int nVars; // inputs
+ int nNodes; // internal nodes
+ int nObjs; // total objects (2 consts, nVars inputs, nNodes internal nodes)
+ int nWords; // the truth table size in 64-bit words
+ int iVar; // the next available SAT variable
+ int fUseConst; // use constant fanins
+ Vec_Wrd_t * vInfo; // Const0 + Const1 + nVars + nNodes + Maj(nVars)
+ int VarMarks[MAJ_NOBJS][3][MAJ_NOBJS]; // variable marks
+ int VarVals[MAJ_NOBJS+2]; // values of the first 2 + nVars variables
+ Vec_Wec_t * vOutLits; // output vars
+ bmcg_sat_solver * pSat; // SAT solver
+};
+
+static inline word * Maj_ManTruth( Maj_Man_t * p, int v ) { return Vec_WrdEntryP( p->vInfo, p->nWords * v ); }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Maj_ManValue( int iMint, int nVars )
+{
+ int k, Count = 0;
+ for ( k = 0; k < nVars; k++ )
+ Count += (iMint >> k) & 1;
+ return (int)(Count > nVars/2);
+}
+Vec_Wrd_t * Maj_ManTruthTables( Maj_Man_t * p )
+{
+ Vec_Wrd_t * vInfo = p->vInfo = Vec_WrdStart( p->nWords * (p->nObjs + 1) );
+ int i, nMints = Abc_MaxInt( 64, 1 << p->nVars );
+ Abc_TtFill( Maj_ManTruth(p, 1), p->nWords );
+ for ( i = 0; i < p->nVars; i++ )
+ Abc_TtIthVar( Maj_ManTruth(p, i+2), i, p->nVars );
+ for ( i = 0; i < nMints; i++ )
+ if ( Maj_ManValue(i, p->nVars) )
+ Abc_TtSetBit( Maj_ManTruth(p, p->nObjs), i );
+ //Dau_DsdPrintFromTruth( Maj_ManTruth(p, p->nObjs), p->nVars );
+ return vInfo;
+}
+int Maj_ManMarkup( Maj_Man_t * p )
+{
+ int i, k, j;
+ p->iVar = 1;
+ assert( p->nObjs <= MAJ_NOBJS );
+ // make exception for the first node
+ i = p->nVars + 2;
+ for ( k = 0; k < 3; k++ )
+ {
+ j = 4-k;
+ Vec_WecPush( p->vOutLits, j, Abc_Var2Lit(p->iVar, 0) );
+ p->VarMarks[i][k][j] = p->iVar++;
+ }
+ // assign variables for other nodes
+ for ( i = p->nVars + 3; i < p->nObjs; i++ )
+ {
+ for ( k = 0; k < 3; k++ )
+ {
+ for ( j = (p->fUseConst && k == 2) ? 0 : 2; 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 + 2; i < p->nObjs; i++ )
+ {
+ printf( "Node %d\n", i );
+ for ( j = 0; j < p->nObjs; j++ )
+ {
+ for ( k = 0; k < 3; k++ )
+ printf( "%2d ", p->VarMarks[i][k][j] );
+ printf( "\n" );
+ }
+ }
+ return p->iVar;
+}
+Maj_Man_t * Maj_ManAlloc( int nVars, int nNodes, int fUseConst )
+{
+ Maj_Man_t * p = ABC_CALLOC( Maj_Man_t, 1 );
+ p->nVars = nVars;
+ p->nNodes = nNodes;
+ p->nObjs = 2 + nVars + nNodes;
+ p->fUseConst = fUseConst;
+ p->nWords = Abc_TtWordNum(nVars);
+ p->vOutLits = Vec_WecStart( p->nObjs );
+ p->iVar = Maj_ManMarkup( p );
+ p->VarVals[1] = 1;
+ p->vInfo = Maj_ManTruthTables( p );
+ p->pSat = bmcg_sat_solver_start();
+ bmcg_sat_solver_set_nvars( p->pSat, p->iVar );
+ return p;
+}
+void Maj_ManFree( Maj_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 Maj_ManFindFanin( Maj_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 Maj_ManEval( Maj_Man_t * p )
+{
+ int i, k, iMint; word * pFanins[3];
+ for ( i = p->nVars + 2; i < p->nObjs; i++ )
+ {
+ for ( k = 0; k < 3; k++ )
+ pFanins[k] = Maj_ManTruth( p, Maj_ManFindFanin(p, i, k) );
+ Abc_TtMaj( Maj_ManTruth(p, i), pFanins[0], pFanins[1], pFanins[2], p->nWords );
+ }
+ iMint = Abc_TtFindFirstDiffBit( Maj_ManTruth(p, p->nObjs-1), Maj_ManTruth(p, p->nObjs), p->nWords );
+ return iMint;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Maj_ManPrintSolution( Maj_Man_t * p )
+{
+ int i, k, iVar;
+ printf( "Realization of %d-input majority using %d MAJ3 gates:\n", p->nVars, p->nNodes );
+ for ( i = p->nVars + 2; i < p->nObjs; i++ )
+ {
+ printf( "%02d = MAJ(", i-2 );
+ for ( k = 0; k < 3; k++ )
+ {
+ iVar = Maj_ManFindFanin( p, i, k );
+ if ( iVar >= 2 && iVar < p->nVars + 2 )
+ printf( " %c", 'a'+iVar-2 );
+ else if ( iVar < 2 )
+ printf( " %d", iVar );
+ else
+ printf( " %02d", iVar-2 );
+ }
+ printf( " )\n" );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Maj_ManAddCnfStart( Maj_Man_t * p )
+{
+ int pLits[MAJ_NOBJS], pLits2[2], i, j, k, n, m;
+ // input constraints
+ for ( i = p->nVars + 2; i < p->nObjs; i++ )
+ {
+ for ( k = 0; k < 3; 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 == 2 )
+ 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;
+ }
+ }
+ }
+ // outputs should be used
+ for ( i = 2; 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;
+}
+int Maj_ManAddCnf( Maj_Man_t * p, int iMint )
+{
+ // save minterm values
+ int i, k, n, j, Value = Maj_ManValue(iMint, p->nVars);
+ for ( i = 0; i < p->nVars; i++ )
+ p->VarVals[i+2] = (iMint >> i) & 1;
+ bmcg_sat_solver_set_nvars( p->pSat, p->iVar + 4*p->nNodes );
+ //printf( "Adding clauses for minterm %d.\n", iMint );
+ for ( i = p->nVars + 2; i < p->nObjs; i++ )
+ {
+ // fanin connectivity
+ int iBaseSatVarI = p->iVar + 4*(i - p->nVars - 2);
+ for ( k = 0; k < 3; k++ )
+ {
+ int nLits2 = 0;
+ for ( j = 0; j < p->nObjs; j++ ) if ( p->VarMarks[i][k][j] )
+ {
+ int iBaseSatVarJ = p->iVar + 4*(j - p->nVars - 2);
+ 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 + 2 )
+ pLits[nLits++] = Abc_Var2Lit( iBaseSatVarJ + 3, !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 < 3; k++ )
+ {
+ int pLits[3], nLits = 0;
+ if ( k != 0 ) pLits[nLits++] = Abc_Var2Lit( iBaseSatVarI + 0, n );
+ if ( k != 1 ) pLits[nLits++] = Abc_Var2Lit( iBaseSatVarI + 1, n );
+ if ( k != 2 ) pLits[nLits++] = Abc_Var2Lit( iBaseSatVarI + 2, n );
+ if ( i != p->nObjs - 1 ) pLits[nLits++] = Abc_Var2Lit( iBaseSatVarI + 3, !n );
+ assert( nLits <= 3 );
+ if ( !bmcg_sat_solver_addclause( p->pSat, pLits, nLits ) )
+ return 0;
+ }
+ }
+ }
+ p->iVar += 4*p->nNodes;
+ return 1;
+}
+void Maj_ManExactSynthesis( int nVars, int nNodes, int fUseConst, int fVerbose )
+{
+ int i, iMint = 0;
+ abctime clkTotal = Abc_Clock();
+ Maj_Man_t * p = Maj_ManAlloc( nVars, nNodes, fUseConst );
+ int status = Maj_ManAddCnfStart( p );
+ assert( status );
+ printf( "Running exact synthesis for %d-input majority with %d MAJ3 gates...\n", p->nVars, p->nNodes );
+ for ( i = 0; iMint != -1; i++ )
+ {
+ abctime clk = Abc_Clock();
+ if ( !Maj_ManAddCnf( p, iMint ) )
+ break;
+ status = bmcg_sat_solver_solve( p->pSat, NULL, 0 );
+ if ( fVerbose )
+ {
+ printf( "Iter %3d : ", i );
+ printf( "Vars = %5d ", p->iVar );
+ printf( "Clauses = %5d ", bmcg_sat_solver_clausenum(p->pSat) );
+ printf( "Conflicts = %7d ", 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 = Maj_ManEval( p );
+ }
+ if ( iMint == -1 )
+ Maj_ManPrintSolution( p );
+ Maj_ManFree( p );
+ Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/sat/bmc/module.make b/src/sat/bmc/module.make
index a88db8dd..94fb27cc 100644
--- a/src/sat/bmc/module.make
+++ b/src/sat/bmc/module.make
@@ -22,6 +22,7 @@ SRC += src/sat/bmc/bmcBCore.c \
src/sat/bmc/bmcICheck.c \
src/sat/bmc/bmcInse.c \
src/sat/bmc/bmcLoad.c \
+ src/sat/bmc/bmcMaj.c \
src/sat/bmc/bmcMaxi.c \
src/sat/bmc/bmcMesh.c \
src/sat/bmc/bmcMesh2.c \