/**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/extra/extra.h" #include "misc/util/utilTruth.h" #include "sat/glucose/AbcGlucose.h" #include "aig/miniaig/miniaig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define MAJ_NOBJS 64 // 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 int fUseLine; // use cascade topology 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++ ) { if ( p->fUseLine && k == 0 ) { j = i-1; Vec_WecPush( p->vOutLits, j, Abc_Var2Lit(p->iVar, 0) ); p->VarMarks[i][k][j] = p->iVar++; continue; } 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( "%3d ", p->VarMarks[i][k][j] ); printf( "\n" ); } } return p->iVar; } Maj_Man_t * Maj_ManAlloc( int nVars, int nNodes, int fUseConst, int fUseLine ) { 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->fUseLine = fUseLine; 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 fUseMiddle = 1; static int Flag = 0; 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 ); } if ( fUseMiddle ) { iMint = -1; for ( i = 0; i < (1 << p->nVars); i++ ) { int nOnes = Abc_TtBitCount16(i); if ( nOnes < p->nVars/2 || nOnes > p->nVars/2+1 ) continue; if ( Abc_TtGetBit(Maj_ManTruth(p, p->nObjs), i) == Abc_TtGetBit(Maj_ManTruth(p, p->nObjs-1), i) ) continue; iMint = i; break; } } else { if ( Flag && p->nVars >= 6 ) iMint = Abc_TtFindLastDiffBit( Maj_ManTruth(p, p->nObjs-1), Maj_ManTruth(p, p->nObjs), p->nVars ); else iMint = Abc_TtFindFirstDiffBit( Maj_ManTruth(p, p->nObjs-1), Maj_ManTruth(p, p->nObjs), p->nVars ); } //Flag ^= 1; assert( iMint < (1 << p->nVars) ); 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++ ) for ( i = p->nObjs - 1; i >= p->nVars + 2; i-- ) { printf( "%02d = MAJ(", i-2 ); for ( k = 2; k >= 0; 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++ ) { 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; } int Maj_ManExactSynthesis( int nVars, int nNodes, int fUseConst, int fUseLine, int fVerbose ) { int i, iMint = 0; abctime clkTotal = Abc_Clock(); Maj_Man_t * p = Maj_ManAlloc( nVars, nNodes, fUseConst, fUseLine ); 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 ); 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 = Maj_ManEval( p ); } if ( iMint == -1 ) Maj_ManPrintSolution( p ); Maj_ManFree( p ); Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); return iMint == -1; } typedef struct Exa_Man_t_ Exa_Man_t; struct Exa_Man_t_ { Bmc_EsPar_t * pPars; // parameters int nVars; // inputs int nNodes; // internal nodes 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][2][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 FILE * pFile; int nCnfClauses; }; static inline word * Exa_ManTruth( Exa_Man_t * p, int v ) { return Vec_WrdEntryP( p->vInfo, p->nWords * v ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wrd_t * Exa_ManTruthTables( Exa_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( Exa_ManTruth(p, i), i, p->nVars ); //Dau_DsdPrintFromTruth( Exa_ManTruth(p, p->nObjs), p->nVars ); return vInfo; } int Exa_ManMarkup( Exa_Man_t * p ) { int i, k, j; assert( p->nObjs <= MAJ_NOBJS ); // assign functionality p->iVar = 1 + 3*p->nNodes;// // assign connectivity variables for ( i = p->nVars; i < p->nObjs; i++ ) { for ( k = 0; k < 2; k++ ) { if ( p->pPars->fFewerVars && i == p->nObjs - 1 && k == 0 ) { j = p->nObjs - 2; Vec_WecPush( p->vOutLits, j, Abc_Var2Lit(p->iVar, 0) ); p->VarMarks[i][k][j] = p->iVar++; continue; } for ( j = p->pPars->fFewerVars ? 1 - k : 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 < 2; k++ ) printf( "%3d ", p->VarMarks[i][k][j] ); printf( "\n" ); } } return p->iVar; } Exa_Man_t * Exa_ManAlloc( Bmc_EsPar_t * pPars, word * pTruth ) { Exa_Man_t * p = ABC_CALLOC( Exa_Man_t, 1 ); p->pPars = pPars; p->nVars = pPars->nVars; p->nNodes = pPars->nNodes; p->nObjs = pPars->nVars + pPars->nNodes; p->nWords = Abc_TtWordNum(pPars->nVars); p->pTruth = pTruth; p->vOutLits = Vec_WecStart( p->nObjs ); p->iVar = Exa_ManMarkup( p ); p->vInfo = Exa_ManTruthTables( p ); p->pSat = bmcg_sat_solver_start(); bmcg_sat_solver_set_nvars( p->pSat, p->iVar ); if ( pPars->RuntimeLim ) bmcg_sat_solver_set_runtime_limit( p->pSat, Abc_Clock() + pPars->RuntimeLim * CLOCKS_PER_SEC ); if ( pPars->fDumpCnf ) { char Buffer[1000]; sprintf( Buffer, "%s_%d_%d.cnf", p->pPars->pTtStr, 2, p->nNodes ); p->pFile = fopen( Buffer, "wb" ); fputs( "p cnf \n", p->pFile ); } return p; } void Exa_ManFree( Exa_Man_t * p ) { if ( p->pFile ) { char Buffer[1000]; sprintf( Buffer, "%s_%d_%d.cnf", p->pPars->pTtStr, 2, p->nNodes ); rewind( p->pFile ); fprintf( p->pFile, "p cnf %d %d", bmcg_sat_solver_varnum(p->pSat), p->nCnfClauses ); fclose( p->pFile ); printf( "CNF was dumped into file \"%s\".\n", Buffer ); } 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 Exa_ManFindFanin( Exa_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 Exa_ManEval( Exa_Man_t * p ) { static int Flag = 0; int i, k, iMint; word * pFanins[2]; for ( i = p->nVars; i < p->nObjs; i++ ) { int iVarStart = 1 + 3*(i - p->nVars);// for ( k = 0; k < 2; k++ ) pFanins[k] = Exa_ManTruth( p, Exa_ManFindFanin(p, i, k) ); Abc_TtConst0( Exa_ManTruth(p, i), p->nWords ); for ( k = 1; k < 4; k++ ) { if ( !bmcg_sat_solver_read_cex_varvalue(p->pSat, iVarStart+k-1) ) continue; Abc_TtAndCompl( Exa_ManTruth(p, p->nObjs), pFanins[0], !(k&1), pFanins[1], !(k>>1), p->nWords ); Abc_TtOr( Exa_ManTruth(p, i), Exa_ManTruth(p, i), Exa_ManTruth(p, p->nObjs), p->nWords ); } } if ( Flag && p->nVars >= 6 ) iMint = Abc_TtFindLastDiffBit( Exa_ManTruth(p, p->nObjs-1), p->pTruth, p->nVars ); else iMint = Abc_TtFindFirstDiffBit( Exa_ManTruth(p, p->nObjs-1), p->pTruth, p->nVars ); //Flag ^= 1; assert( iMint < (1 << p->nVars) ); return iMint; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Exa_ManDumpBlif( Exa_Man_t * p, int fCompl ) { char Buffer[1000]; char FileName[1100]; FILE * pFile; int i, k, iVar; if ( fCompl ) Abc_TtNot( p->pTruth, p->nWords ); Extra_PrintHexadecimalString( Buffer, (unsigned *)p->pTruth, p->nVars ); if ( fCompl ) Abc_TtNot( p->pTruth, p->nWords ); sprintf( FileName, "%s_%d_%d.blif", Buffer, 2, p->nNodes ); pFile = fopen( FileName, "wb" ); fprintf( pFile, "# Realization of the %d-input function %s using %d two-input gates:\n", p->nVars, Buffer, p->nNodes ); fprintf( pFile, ".model %s_%d_%d\n", Buffer, 2, p->nNodes ); fprintf( pFile, ".inputs" ); for ( i = 0; i < p->nVars; i++ ) fprintf( pFile, " %c", 'a'+i ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs F\n" ); for ( i = p->nObjs - 1; i >= p->nVars; i-- ) { int iVarStart = 1 + 3*(i - p->nVars);// int Val1 = bmcg_sat_solver_read_cex_varvalue(p->pSat, iVarStart); int Val2 = bmcg_sat_solver_read_cex_varvalue(p->pSat, iVarStart+1); int Val3 = bmcg_sat_solver_read_cex_varvalue(p->pSat, iVarStart+2); fprintf( pFile, ".names" ); for ( k = 1; k >= 0; k-- ) { iVar = Exa_ManFindFanin( p, i, k ); if ( iVar >= 0 && iVar < p->nVars ) fprintf( pFile, " %c", 'a'+iVar ); else fprintf( pFile, " %02d", iVar ); } if ( i == p->nObjs - 1 ) fprintf( pFile, " F\n" ); else fprintf( pFile, " %02d\n", i ); if ( i == p->nObjs - 1 && fCompl ) fprintf( pFile, "00 1\n" ); if ( (i == p->nObjs - 1 && fCompl) ^ Val1 ) fprintf( pFile, "01 1\n" ); if ( (i == p->nObjs - 1 && fCompl) ^ Val2 ) fprintf( pFile, "10 1\n" ); if ( (i == p->nObjs - 1 && fCompl) ^ Val3 ) fprintf( pFile, "11 1\n" ); } fprintf( pFile, ".end\n\n" ); fclose( pFile ); printf( "Solution was dumped into file \"%s\".\n", FileName ); } void Exa_ManPrintSolution( Exa_Man_t * p, int fCompl ) { int i, k, iVar; printf( "Realization of given %d-input function using %d two-input gates:\n", p->nVars, p->nNodes ); // for ( i = p->nVars + 2; i < p->nObjs; i++ ) for ( i = p->nObjs - 1; i >= p->nVars; i-- ) { int iVarStart = 1 + 3*(i - p->nVars);// int Val1 = bmcg_sat_solver_read_cex_varvalue(p->pSat, iVarStart); int Val2 = bmcg_sat_solver_read_cex_varvalue(p->pSat, iVarStart+1); int Val3 = bmcg_sat_solver_read_cex_varvalue(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 ); for ( k = 1; k >= 0; k-- ) { iVar = Exa_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 inline int Exa_ManAddClause( Exa_Man_t * p, int * pLits, int nLits ) { int i; if ( p->pFile ) { p->nCnfClauses++; for ( i = 0; i < nLits; i++ ) fprintf( p->pFile, "%s%d ", Abc_LitIsCompl(pLits[i]) ? "-" : "", Abc_Lit2Var(pLits[i]) ); fprintf( p->pFile, "0\n" ); } return bmcg_sat_solver_addclause( p->pSat, pLits, nLits ); } int Exa_ManAddCnfAdd( Exa_Man_t * p, int * pnAdded ) { int pLits[MAJ_NOBJS], pLits2[2], i, j, k, n, m; *pnAdded = 0; for ( i = p->nVars; i < p->nObjs; i++ ) { for ( k = 0; k < 2; k++ ) { int nLits = 0; 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]) ) pLits[nLits++] = Abc_Var2Lit( p->VarMarks[i][k][j], 0 ); assert( nLits > 0 ); // input uniqueness for ( n = 0; n < nLits; n++ ) for ( m = n+1; m < nLits; m++ ) { (*pnAdded)++; pLits2[0] = Abc_LitNot(pLits[n]); pLits2[1] = Abc_LitNot(pLits[m]); if ( !Exa_ManAddClause( p, pLits2, 2 ) ) return 0; } if ( k == 1 ) break; // symmetry breaking 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]) ) for ( n = j; n < p->nObjs; n++ ) if ( p->VarMarks[i][k+1][n] && bmcg_sat_solver_read_cex_varvalue(p->pSat, p->VarMarks[i][k+1][j]) ) { (*pnAdded)++; pLits2[0] = Abc_Var2Lit( p->VarMarks[i][k][j], 1 ); pLits2[1] = Abc_Var2Lit( p->VarMarks[i][k+1][n], 1 ); if ( !Exa_ManAddClause( p, pLits2, 2 ) ) return 0; } } } return 1; } int Exa_ManSolverSolve( Exa_Man_t * p ) { int nAdded = 1; while ( nAdded ) { int status = bmcg_sat_solver_solve( p->pSat, NULL, 0 ); if ( status != GLUCOSE_SAT ) return status; status = Exa_ManAddCnfAdd( p, &nAdded ); //printf( "Added %d clauses.\n", nAdded ); if ( status != GLUCOSE_SAT ) return status; } return GLUCOSE_SAT; } int Exa_ManAddCnfStart( Exa_Man_t * p, int fOnlyAnd ) { int pLits[MAJ_NOBJS], pLits2[3], i, j, k, n, m; // input constraints for ( i = p->nVars; i < p->nObjs; i++ ) { int iVarStart = 1 + 3*(i - p->nVars);// for ( k = 0; k < 2; 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 ); if ( !Exa_ManAddClause( p, pLits, nLits ) ) return 0; // input uniqueness if ( !p->pPars->fDynConstr ) { 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 ( !Exa_ManAddClause( p, pLits2, 2 ) ) return 0; } } if ( k == 1 ) break; // symmetry breaking if ( !p->pPars->fDynConstr ) { 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 ( !Exa_ManAddClause( p, pLits2, 2 ) ) return 0; } } } #ifdef USE_NODE_ORDER // node ordering for ( j = p->nVars; j < i; j++ ) for ( n = 0; n < p->nObjs; n++ ) if ( p->VarMarks[i][0][n] ) for ( m = n+1; m < p->nObjs; m++ ) if ( p->VarMarks[j][0][m] ) { pLits2[0] = Abc_Var2Lit( p->VarMarks[i][0][n], 1 ); pLits2[1] = Abc_Var2Lit( p->VarMarks[j][0][m], 1 ); if ( !Exa_ManAddClause( p, pLits2, 2 ) ) return 0; } #endif // unique functions for ( j = p->nVars; j < i; j++ ) for ( k = 0; k < 2; k++ ) if ( p->VarMarks[i][k][j] ) { pLits2[0] = Abc_Var2Lit( p->VarMarks[i][k][j], 1 ); for ( n = 0; n < p->nObjs; n++ ) for ( m = 0; m < 2; m++ ) { if ( p->VarMarks[i][!k][n] && p->VarMarks[j][m][n] ) { pLits2[1] = Abc_Var2Lit( p->VarMarks[i][!k][n], 1 ); pLits2[2] = Abc_Var2Lit( p->VarMarks[j][m][n], 1 ); if ( !Exa_ManAddClause( p, pLits2, 3 ) ) return 0; } } } // 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 ( !Exa_ManAddClause( p, pLits, 3 ) ) return 0; } if ( fOnlyAnd ) { pLits[0] = Abc_Var2Lit( iVarStart, 1 ); pLits[1] = Abc_Var2Lit( iVarStart+1, 1 ); pLits[2] = Abc_Var2Lit( iVarStart+2, 0 ); if ( !Exa_ManAddClause( p, 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 ( !Exa_ManAddClause( p, Vec_IntArray(vArray), Vec_IntSize(vArray) ) ) return 0; } return 1; } int Exa_ManAddCnf( Exa_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; bmcg_sat_solver_set_nvars( p->pSat, p->iVar + 3*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 + 3*(i - p->nVars);// int iBaseSatVarI = p->iVar + 3*(i - p->nVars); for ( k = 0; k < 2; k++ ) { for ( j = 0; j < p->nObjs; j++ ) if ( p->VarMarks[i][k][j] ) { int iBaseSatVarJ = p->iVar + 3*(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 + 2, !n ); else if ( p->VarVals[j] == n ) continue; if ( !Exa_ManAddClause( p, pLits, nLits ) ) return 0; } } } // node functionality for ( n = 0; n < 2; n++ ) { if ( i == p->nObjs - 1 && n == Value ) continue; for ( k = 0; k < 4; k++ ) { int pLits[4], 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 ); if ( k > 0 ) pLits[nLits++] = Abc_Var2Lit( iVarStart + k-1, n ); assert( nLits <= 4 ); if ( !Exa_ManAddClause( p, pLits, nLits ) ) return 0; } } } p->iVar += 3*p->nNodes; return 1; } void Exa_ManExactSynthesis( Bmc_EsPar_t * pPars ) { int i, status, iMint = 1; abctime clkTotal = Abc_Clock(); Exa_Man_t * p; int fCompl = 0; word pTruth[16]; Abc_TtReadHex( pTruth, pPars->pTtStr ); assert( pPars->nVars <= 10 ); p = Exa_ManAlloc( pPars, pTruth ); if ( pTruth[0] & 1 ) { fCompl = 1; Abc_TtNot( pTruth, p->nWords ); } status = Exa_ManAddCnfStart( p, pPars->fOnlyAnd ); assert( status ); printf( "Running exact synthesis for %d-input function with %d two-input gates...\n", p->nVars, p->nNodes ); for ( i = 0; iMint != -1; i++ ) { abctime clk = Abc_Clock(); if ( !Exa_ManAddCnf( p, iMint ) ) break; if ( pPars->fDynConstr ) status = Exa_ManSolverSolve( p ); else status = bmcg_sat_solver_solve( p->pSat, NULL, 0 ); if ( pPars->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; } if ( status == GLUCOSE_UNDEC ) { printf( "The problem timed out after %d sec.\n", pPars->RuntimeLim ); break; } iMint = Exa_ManEval( p ); } if ( iMint == -1 ) { Exa_ManPrintSolution( p, fCompl ); Exa_ManDumpBlif( p, fCompl ); } Exa_ManFree( p ); Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); } typedef struct Exa3_Man_t_ Exa3_Man_t; struct Exa3_Man_t_ { Bmc_EsPar_t * pPars; // parameters 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 Vec_Bit_t * vUsed2; // bit masks Vec_Bit_t * vUsed3; // bit masks 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 int nUsed[2]; }; static inline word * Exa3_ManTruth( Exa3_Man_t * p, int v ) { return Vec_WrdEntryP( p->vInfo, p->nWords * v ); } static inline int Exa3_ManIsUsed2( Exa3_Man_t * p, int m, int n, int i, int j ) { int Pos = ((m * p->pPars->nNodes + n - p->pPars->nVars) * p->nObjs + i) * p->nObjs + j; p->nUsed[0]++; assert( i < n && j < n && i < j ); if ( Vec_BitEntry(p->vUsed2, Pos) ) return 1; p->nUsed[1]++; Vec_BitWriteEntry( p->vUsed2, Pos, 1 ); return 0; } static inline int Exa3_ManIsUsed3( Exa3_Man_t * p, int m, int n, int i, int j, int k ) { int Pos = (((m * p->pPars->nNodes + n - p->pPars->nVars) * p->nObjs + i) * p->nObjs + j) * p->nObjs + k; p->nUsed[0]++; assert( i < n && j < n && k < n && i < j && j < k ); if ( Vec_BitEntry(p->vUsed3, Pos) ) return 1; p->nUsed[1]++; Vec_BitWriteEntry( p->vUsed3, Pos, 1 ); return 0; } /**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 functionality variables p->iVar = 1 + p->LutMask * p->nNodes; // assign connectivity variables for ( i = p->nVars; i < p->nObjs; i++ ) { for ( k = 0; k < p->nLutSize; k++ ) { if ( p->pPars->fFewerVars && i == p->nObjs - 1 && k == 0 ) { j = p->nObjs - 2; Vec_WecPush( p->vOutLits, j, Abc_Var2Lit(p->iVar, 0) ); p->VarMarks[i][k][j] = p->iVar++; continue; } for ( j = p->pPars->fFewerVars ? p->nLutSize - 1 - k : 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->nObjs - 1; i >= p->nVars; i-- ) { printf( " Node %2d\n", i ); for ( j = 0; j < p->nObjs; j++ ) { printf( "Fanin %2d : ", 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( Bmc_EsPar_t * pPars, word * pTruth ) { Exa3_Man_t * p = ABC_CALLOC( Exa3_Man_t, 1 ); p->pPars = pPars; p->nVars = pPars->nVars; p->nNodes = pPars->nNodes; p->nLutSize = pPars->nLutSize; p->LutMask = (1 << pPars->nLutSize) - 1; p->nObjs = pPars->nVars + pPars->nNodes; p->nWords = Abc_TtWordNum(pPars->nVars); p->pTruth = pTruth; p->vOutLits = Vec_WecStart( p->nObjs ); p->iVar = Exa3_ManMarkup( p ); p->vInfo = Exa3_ManTruthTables( p ); if ( p->pPars->nLutSize == 2 ) p->vUsed2 = Vec_BitStart( (1 << p->pPars->nVars) * p->pPars->nNodes * p->nObjs * p->nObjs ); else if ( p->pPars->nLutSize == 3 ) p->vUsed3 = Vec_BitStart( (1 << p->pPars->nVars) * p->pPars->nNodes * p->nObjs * p->nObjs * p->nObjs ); p->pSat = bmcg_sat_solver_start(); bmcg_sat_solver_set_nvars( p->pSat, p->iVar ); if ( pPars->RuntimeLim ) bmcg_sat_solver_set_runtime_limit( p->pSat, Abc_Clock() + pPars->RuntimeLim * CLOCKS_PER_SEC ); return p; } static void Exa3_ManFree( Exa3_Man_t * p ) { bmcg_sat_solver_stop( p->pSat ); Vec_WrdFree( p->vInfo ); Vec_BitFreeP( &p->vUsed2 ); Vec_BitFreeP( &p->vUsed3 ); 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 fOnlyAnd ) { 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; } } //#ifdef USE_NODE_ORDER // node ordering if ( p->pPars->fUseIncr ) { for ( j = p->nVars; j < i; j++ ) for ( n = 0; n < p->nObjs; n++ ) if ( p->VarMarks[i][0][n] ) for ( m = n+1; m < p->nObjs; m++ ) if ( p->VarMarks[j][0][m] ) { pLits2[0] = Abc_Var2Lit( p->VarMarks[i][0][n], 1 ); pLits2[1] = Abc_Var2Lit( p->VarMarks[j][0][m], 1 ); if ( !bmcg_sat_solver_addclause( p->pSat, pLits2, 2 ) ) return 0; } } //#endif 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; } if ( fOnlyAnd ) { pLits[0] = Abc_Var2Lit( iVarStart, 1 ); pLits[1] = Abc_Var2Lit( iVarStart+1, 1 ); pLits[2] = Abc_Var2Lit( iVarStart+2, 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[16], 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; } static int Exa3_ManAddCnf2( Exa3_Man_t * p, int iMint ) { int iBaseSatVar = p->iVar + p->nNodes*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; //printf( "Adding clauses for minterm %d with value %d.\n", iMint, Value ); for ( i = p->nVars; i < p->nObjs; i++ ) { // int iBaseSatVarI = p->iVar + (p->nLutSize+1)*(i - p->nVars); int iVarStart = 1 + p->LutMask*(i - p->nVars); // collect fanin variables int pFanins[16]; for ( j = 0; j < p->nLutSize; j++ ) pFanins[j] = Exa3_ManFindFanin(p, i, j); // check cache if ( p->pPars->nLutSize == 2 && Exa3_ManIsUsed2(p, iMint, i, pFanins[1], pFanins[0]) ) continue; if ( p->pPars->nLutSize == 3 && Exa3_ManIsUsed3(p, iMint, i, pFanins[2], pFanins[1], pFanins[0]) ) continue; // 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[16], nLits = 0; if ( k == 0 && n == 1 ) continue; for ( j = 0; j < p->nLutSize; j++ ) { // pLits[nLits++] = Abc_Var2Lit( iBaseSatVar + j, (k >> j) & 1 ); pLits[nLits++] = Abc_Var2Lit( p->VarMarks[i][j][pFanins[j]], 1 ); if ( pFanins[j] >= p->nVars ) pLits[nLits++] = Abc_Var2Lit( iBaseSatVar + pFanins[j] - p->nVars, (k >> j) & 1 ); else if ( p->VarVals[pFanins[j]] != ((k >> j) & 1) ) break; } if ( j < p->nLutSize ) continue; // if ( i != p->nObjs - 1 ) pLits[nLits++] = Abc_Var2Lit( iBaseSatVar + j, !n ); if ( i != p->nObjs - 1 ) pLits[nLits++] = Abc_Var2Lit( iBaseSatVar + i - p->nVars, !n ); if ( k > 0 ) pLits[nLits++] = Abc_Var2Lit( iVarStart + k-1, n ); assert( nLits <= 2*p->nLutSize+2 ); if ( !bmcg_sat_solver_addclause( p->pSat, pLits, nLits ) ) return 0; } } } return 1; } void Exa3_ManPrint( Exa3_Man_t * p, int i, int iMint, abctime clk ) { printf( "Iter%6d : ", i ); Extra_PrintBinary( stdout, (unsigned *)&iMint, p->nVars ); printf( " Var =%5d ", bmcg_sat_solver_varnum(p->pSat) ); printf( "Cla =%6d ", bmcg_sat_solver_clausenum(p->pSat) ); printf( "Conf =%9d ", bmcg_sat_solver_conflictnum(p->pSat) ); Abc_PrintTime( 1, "Time", clk ); } void Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ) { int i, status, iMint = 1; abctime clkTotal = Abc_Clock(); Exa3_Man_t * p; int fCompl = 0; word pTruth[16]; Abc_TtReadHex( pTruth, pPars->pTtStr ); assert( pPars->nVars <= 10 ); assert( pPars->nLutSize <= 6 ); p = Exa3_ManAlloc( pPars, pTruth ); if ( pTruth[0] & 1 ) { fCompl = 1; Abc_TtNot( pTruth, p->nWords ); } status = Exa3_ManAddCnfStart( p, pPars->fOnlyAnd ); assert( status ); printf( "Running exact synthesis for %d-input function with %d %d-input LUTs...\n", p->nVars, p->nNodes, p->nLutSize ); if ( pPars->fUseIncr ) { bmcg_sat_solver_set_nvars( p->pSat, p->iVar + p->nNodes*(1 << p->nVars) ); status = bmcg_sat_solver_solve( p->pSat, NULL, 0 ); assert( status == GLUCOSE_SAT ); } for ( i = 0; iMint != -1; i++ ) { if ( pPars->fUseIncr ? !Exa3_ManAddCnf2( p, iMint ) : !Exa3_ManAddCnf( p, iMint ) ) break; status = bmcg_sat_solver_solve( p->pSat, NULL, 0 ); if ( pPars->fVerbose && (!pPars->fUseIncr || i % 100 == 0) ) Exa3_ManPrint( p, i, iMint, Abc_Clock() - clkTotal ); if ( status == GLUCOSE_UNSAT || status == GLUCOSE_UNDEC ) break; iMint = Exa3_ManEval( p ); } if ( pPars->fVerbose && status != GLUCOSE_UNDEC ) Exa3_ManPrint( p, i, iMint, Abc_Clock() - clkTotal ); if ( iMint == -1 ) Exa3_ManPrintSolution( p, fCompl ); else if ( status == GLUCOSE_UNDEC ) printf( "The problem timed out after %d sec.\n", pPars->RuntimeLim ); else printf( "The problem has no solution.\n" ); printf( "Added = %d. Tried = %d. ", p->nUsed[1], p->nUsed[0] ); Exa3_ManFree( p ); Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Exa_ManIsNormalized( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut ) { int i, Count = 0; word Temp; Vec_WrdForEachEntry( vSimsIn, Temp, i ) if ( Temp & 1 ) Count++; if ( Count ) printf( "The data for %d divisors are not normalized.\n", Count ); if ( !(Vec_WrdEntry(vSimsOut, 0) & 1) ) printf( "The output data is not normalized.\n" ); // else if ( Count == 0 ) // printf( "The data is fully normalized.\n" ); } static inline void Exa_ManPrintFanin( int nIns, int nDivs, int iNode, int fComp ) { if ( iNode == 0 ) printf( " %s", fComp ? "const1" : "const0" ); else if ( iNode > 0 && iNode <= nIns ) printf( " %s%c", fComp ? "~" : "", 'a'+iNode-1 ); else if ( iNode > nIns && iNode < nDivs ) printf( " %s%c", fComp ? "~" : "", 'A'+iNode-nIns-1 ); else printf( " %s%d", fComp ? "~" : "", iNode ); } void Exa_ManMiniPrint( Mini_Aig_t * p, int nIns ) { int i, nDivs = 1 + Mini_AigPiNum(p), nNodes = Mini_AigAndNum(p); printf( "This %d-var function (%d divisors) has %d gates (%d xor) and %d levels:\n", nIns, nDivs, nNodes, Mini_AigXorNum(p), Mini_AigLevelNum(p) ); for ( i = nDivs + nNodes; i < Mini_AigNodeNum(p); i++ ) { int Lit0 = Mini_AigNodeFanin0( p, i ); printf( "%2d = ", i ); Exa_ManPrintFanin( nIns, nDivs, Abc_Lit2Var(Lit0), Abc_LitIsCompl(Lit0) ); printf( "\n" ); } for ( i = nDivs + nNodes - 1; i >= nDivs; i-- ) { int Lit0 = Mini_AigNodeFanin0( p, i ); int Lit1 = Mini_AigNodeFanin1( p, i ); printf( "%2d = ", i ); if ( Lit0 < Lit1 ) { Exa_ManPrintFanin( nIns, nDivs, Abc_Lit2Var(Lit0), Abc_LitIsCompl(Lit0) ); printf( " &" ); Exa_ManPrintFanin( nIns, nDivs, Abc_Lit2Var(Lit1), Abc_LitIsCompl(Lit1) ); } else { Exa_ManPrintFanin( nIns, nDivs, Abc_Lit2Var(Lit1), Abc_LitIsCompl(Lit1) ); printf( " ^" ); Exa_ManPrintFanin( nIns, nDivs, Abc_Lit2Var(Lit0), Abc_LitIsCompl(Lit0) ); } printf( "\n" ); } } void Exa_ManMiniVerify( Mini_Aig_t * p, Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut ) { extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); int i, nDivs = 1 + Mini_AigPiNum(p), nNodes = Mini_AigAndNum(p); int k, nOuts = Mini_AigPoNum(p), nErrors = 0; word Outs[6] = {0}; Vec_Wrd_t * vSimsIn2 = Vec_WrdStart( 64 ); assert( nOuts <= 6 ); assert( Vec_WrdSize(vSimsIn) <= 64 ); assert( Vec_WrdSize(vSimsIn) == Vec_WrdSize(vSimsOut) ); Vec_WrdFillExtra( vSimsIn, 64, 0 ); Extra_BitMatrixTransposeP( vSimsIn, 1, vSimsIn2, 1 ); assert( Mini_AigNodeNum(p) <= 64 ); for ( i = nDivs; i < nDivs + nNodes; i++ ) { int Lit0 = Mini_AigNodeFanin0( p, i ); int Lit1 = Mini_AigNodeFanin1( p, i ); word Sim0 = Vec_WrdEntry( vSimsIn2, Abc_Lit2Var(Lit0) ); word Sim1 = Vec_WrdEntry( vSimsIn2, Abc_Lit2Var(Lit1) ); Sim0 = Abc_LitIsCompl(Lit0) ? ~Sim0 : Sim0; Sim1 = Abc_LitIsCompl(Lit1) ? ~Sim1 : Sim1; Vec_WrdWriteEntry( vSimsIn2, i, Lit0 < Lit1 ? Sim0 & Sim1 : Sim0 ^ Sim1 ); } for ( i = nDivs + nNodes; i < Mini_AigNodeNum(p); i++ ) { int Lit0 = Mini_AigNodeFanin0( p, i ); word Sim0 = Vec_WrdEntry( vSimsIn2, Abc_Lit2Var(Lit0) ); Outs[i - (nDivs + nNodes)] = Abc_LitIsCompl(Lit0) ? ~Sim0 : Sim0; } Vec_WrdFree( vSimsIn2 ); for ( i = 0; i < Vec_WrdSize(vSimsOut); i++ ) { int iOutMint = 0; for ( k = 0; k < nOuts; k++ ) if ( (Outs[k] >> i) & 1 ) iOutMint |= 1 << k; nErrors += !Abc_TtGetBit(Vec_WrdEntryP(vSimsOut, i), iOutMint); } if ( nErrors == 0 ) printf( "Verification successful. " ); else printf( "Verification failed for %d (out of %d) minterms.\n", nErrors, Vec_WrdSize(vSimsOut) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Exa4_ManParse( char * pFileName ) { Vec_Int_t * vRes = NULL; char * pToken, pBuffer[1000]; FILE * pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { Abc_Print( -1, "Cannot open file \"%s\".\n", pFileName ); return NULL; } while ( fgets( pBuffer, 1000, pFile ) != NULL ) { if ( pBuffer[0] == 's' ) { if ( strncmp(pBuffer+2, "SAT", 3) ) break; assert( vRes == NULL ); vRes = Vec_IntAlloc( 100 ); } else if ( pBuffer[0] == 'v' ) { pToken = strtok( pBuffer+1, " \n\r\t" ); while ( pToken ) { int Token = atoi(pToken); if ( Token == 0 ) break; Vec_IntSetEntryFull( vRes, Abc_AbsInt(Token), Token > 0 ); pToken = strtok( NULL, " \n\r\t" ); } } else if ( pBuffer[0] != 'c' ) assert( 0 ); } fclose( pFile ); return vRes; } Vec_Int_t * Exa4_ManSolve( char * pFileNameIn, char * pFileNameOut, int TimeOut, int fVerbose ) { int fVerboseSolver = 0; abctime clkTotal = Abc_Clock(); Vec_Int_t * vRes = NULL; #ifdef _WIN32 char * pKissat = "kissat.exe"; #else char * pKissat = "kissat"; #endif char Command[1000], * pCommand = (char *)&Command; { FILE * pFile = fopen( pKissat, "rb" ); if ( pFile == NULL ) { printf( "Cannot find the Kissat binary \"%s\".\n", pKissat ); return NULL; } fclose( pFile ); } if ( TimeOut ) sprintf( pCommand, "%s --time=%d %s %s > %s", pKissat, TimeOut, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut ); else sprintf( pCommand, "%s %s %s > %s", pKissat, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut ); if ( system( pCommand ) == -1 ) { fprintf( stdout, "Command \"%s\" did not succeed.\n", pCommand ); return 0; } vRes = Exa4_ManParse( pFileNameOut ); if ( fVerbose ) { if ( vRes ) printf( "The problem has a solution. " ); else if ( vRes == NULL && TimeOut == 0 ) printf( "The problem has no solution. " ); else if ( vRes == NULL ) printf( "The problem has no solution or timed out after %d sec. ", TimeOut ); Abc_PrintTime( 1, "SAT solver time", Abc_Clock() - clkTotal ); } return vRes; } typedef struct Exa4_Man_t_ Exa4_Man_t; struct Exa4_Man_t_ { Vec_Wrd_t * vSimsIn; // input signatures (nWords = 1, nIns <= 64) Vec_Wrd_t * vSimsOut; // output signatures (nWords = 1, nOuts <= 6) int fVerbose; int nIns; int nDivs; // divisors (const + inputs + tfi + sidedivs) int nNodes; int nOuts; int nObjs; int VarMarks[MAJ_NOBJS][2][MAJ_NOBJS]; int nCnfVars; int nCnfClauses; FILE * pFile; }; /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Exa4_ManMarkup( Exa4_Man_t * p ) { int i, k, j, nVars[3] = {1 + 5*p->nNodes, 0, 3*p->nNodes*Vec_WrdSize(p->vSimsIn)}; assert( p->nObjs <= MAJ_NOBJS ); for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) for ( k = 0; k < 2; k++ ) for ( j = 1+!k; j < i-k; j++ ) p->VarMarks[i][k][j] = nVars[0] + nVars[1]++; for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) for ( j = p->nOuts == 1 ? p->nDivs + p->nNodes - 1 : 0; j < p->nDivs + p->nNodes; j++ ) p->VarMarks[i][0][j] = nVars[0] + nVars[1]++; if ( p->fVerbose ) printf( "Variables: Function = %d. Structure = %d. Internal = %d. Total = %d.\n", nVars[0], nVars[1], nVars[2], nVars[0] + nVars[1] + nVars[2] ); if ( 0 ) { for ( j = 0; j < 2; j++ ) { printf( " : " ); for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) { for ( k = 0; k < 2; k++ ) printf( "%3d ", j ? k : i ); printf( " " ); } printf( " " ); for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) { printf( "%3d ", j ? 0 : i ); printf( " " ); } printf( "\n" ); } for ( j = 0; j < 5 + p->nNodes*9 + p->nOuts*5; j++ ) printf( "-" ); printf( "\n" ); for ( j = p->nObjs - 2; j >= 0; j-- ) { if ( j > 0 && j <= p->nIns ) printf( " %c : ", 'a'+j-1 ); else printf( "%2d : ", j ); for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) { for ( k = 0; k < 2; k++ ) printf( "%3d ", p->VarMarks[i][k][j] ); printf( " " ); } printf( " " ); for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) { printf( "%3d ", p->VarMarks[i][0][j] ); printf( " " ); } printf( "\n" ); } } return nVars[0] + nVars[1] + nVars[2]; } Exa4_Man_t * Exa4_ManAlloc( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, int fVerbose ) { Exa4_Man_t * p = ABC_CALLOC( Exa4_Man_t, 1 ); assert( Vec_WrdSize(vSimsIn) == Vec_WrdSize(vSimsOut) ); p->vSimsIn = vSimsIn; p->vSimsOut = vSimsOut; p->fVerbose = fVerbose; p->nIns = nIns; p->nDivs = nDivs; p->nNodes = nNodes; p->nOuts = nOuts; p->nObjs = p->nDivs + p->nNodes + p->nOuts; p->nCnfVars = Exa4_ManMarkup( p ); return p; } void Exa4_ManFree( Exa4_Man_t * p ) { ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Exa4_ManAddClause( Exa4_Man_t * p, int * pLits, int nLits ) { int i, k = 0; for ( i = 0; i < nLits; i++ ) if ( pLits[i] == 1 ) return 0; else if ( pLits[i] == 0 ) continue; else if ( pLits[i] <= 2*p->nCnfVars ) pLits[k++] = pLits[i]; else assert( 0 ); nLits = k; assert( nLits > 0 ); if ( p->pFile ) { p->nCnfClauses++; for ( i = 0; i < nLits; i++ ) fprintf( p->pFile, "%s%d ", Abc_LitIsCompl(pLits[i]) ? "-" : "", Abc_Lit2Var(pLits[i]) ); fprintf( p->pFile, "0\n" ); } if ( 0 ) { for ( i = 0; i < nLits; i++ ) fprintf( stdout, "%s%d ", Abc_LitIsCompl(pLits[i]) ? "-" : "", Abc_Lit2Var(pLits[i]) ); fprintf( stdout, "\n" ); } return 1; } static inline int Exa4_ManAddClause4( Exa4_Man_t * p, int Lit0, int Lit1, int Lit2, int Lit3 ) { int pLits[4] = { Lit0, Lit1, Lit2, Lit3 }; return Exa4_ManAddClause( p, pLits, 4 ); } int Exa4_ManGenStart( Exa4_Man_t * p, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans ) { int pLits[2*MAJ_NOBJS], i, j, k, n, m, nLits; for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) { int iVarStart = 1 + 5*(i - p->nDivs);// for ( k = 0; k < 2; k++ ) { 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 ); Exa4_ManAddClause( p, pLits, nLits ); for ( n = 0; n < nLits; n++ ) for ( m = n+1; m < nLits; m++ ) Exa4_ManAddClause4( p, Abc_LitNot(pLits[n]), Abc_LitNot(pLits[m]), 0, 0 ); if ( k == 1 ) break; for ( j = 0; j < p->nObjs; j++ ) if ( p->VarMarks[i][0][j] ) for ( n = j; n < p->nObjs; n++ ) if ( p->VarMarks[i][1][n] ) Exa4_ManAddClause4( p, Abc_Var2Lit(p->VarMarks[i][0][j], 1), Abc_Var2Lit(p->VarMarks[i][1][n], 1), 0, 0 ); } if ( fOrderNodes ) for ( j = p->nDivs; j < i; j++ ) for ( n = 0; n < p->nObjs; n++ ) if ( p->VarMarks[i][0][n] ) for ( m = n+1; m < p->nObjs; m++ ) if ( p->VarMarks[j][0][m] ) Exa4_ManAddClause4( p, Abc_Var2Lit(p->VarMarks[i][0][n], 1), Abc_Var2Lit(p->VarMarks[j][0][m], 1), 0, 0 ); for ( j = p->nDivs; j < i; j++ ) for ( k = 0; k < 2; k++ ) if ( p->VarMarks[i][k][j] ) for ( n = 0; n < p->nObjs; n++ ) if ( p->VarMarks[i][!k][n] ) for ( m = 0; m < 2; m++ ) if ( p->VarMarks[j][m][n] ) Exa4_ManAddClause4( p, Abc_Var2Lit(p->VarMarks[i][k][j], 1), Abc_Var2Lit(p->VarMarks[i][!k][n], 1), Abc_Var2Lit(p->VarMarks[j][m][n], 1), 0 ); if ( fFancy ) { nLits = 0; for ( k = 0; k < 5-fOnlyAnd; k++ ) pLits[nLits++] = Abc_Var2Lit( iVarStart+k, 0 ); Exa4_ManAddClause( p, pLits, nLits ); for ( n = 0; n < nLits; n++ ) for ( m = n+1; m < nLits; m++ ) Exa4_ManAddClause4( p, Abc_LitNot(pLits[n]), Abc_LitNot(pLits[m]), 0, 0 ); } else { for ( k = 0; k < 3; k++ ) Exa4_ManAddClause4( p, Abc_Var2Lit(iVarStart, k==1), Abc_Var2Lit(iVarStart+1, k==2), Abc_Var2Lit(iVarStart+2, k!=0), 0); if ( fOnlyAnd ) Exa4_ManAddClause4( p, Abc_Var2Lit(iVarStart, 1), Abc_Var2Lit(iVarStart+1, 1), Abc_Var2Lit(iVarStart+2, 0), 0); } } for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) { nLits = 0; for ( k = 0; k < 2; k++ ) for ( j = i+1; j < p->nObjs; j++ ) if ( p->VarMarks[j][k][i] ) pLits[nLits++] = Abc_Var2Lit( p->VarMarks[j][k][i], 0 ); Exa4_ManAddClause( p, pLits, nLits ); if ( fUniqFans ) for ( n = 0; n < nLits; n++ ) for ( m = n+1; m < nLits; m++ ) Exa4_ManAddClause4( p, Abc_LitNot(pLits[n]), Abc_LitNot(pLits[m]), 0, 0 ); } for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) { nLits = 0; for ( j = 0; j < p->nDivs + p->nNodes; j++ ) if ( p->VarMarks[i][0][j] ) pLits[nLits++] = Abc_Var2Lit( p->VarMarks[i][0][j], 0 ); Exa4_ManAddClause( p, pLits, nLits ); for ( n = 0; n < nLits; n++ ) for ( m = n+1; m < nLits; m++ ) Exa4_ManAddClause4( p, Abc_LitNot(pLits[n]), Abc_LitNot(pLits[m]), 0, 0 ); } return 1; } void Exa4_ManGenMint( Exa4_Man_t * p, int iMint, int fOnlyAnd, int fFancy ) { int iNodeVar = p->nCnfVars + 3*p->nNodes*(iMint - Vec_WrdSize(p->vSimsIn)); int iOutMint = Abc_Tt6FirstBit( Vec_WrdEntry(p->vSimsOut, iMint) ); int i, k, n, j, VarVals[MAJ_NOBJS]; assert( p->nObjs <= MAJ_NOBJS ); assert( iMint < Vec_WrdSize(p->vSimsIn) ); for ( i = 0; i < p->nDivs; i++ ) VarVals[i] = (Vec_WrdEntry(p->vSimsIn, iMint) >> i) & 1; for ( i = 0; i < p->nNodes; i++ ) VarVals[p->nDivs + i] = Abc_Var2Lit(iNodeVar + 3*i + 2, 0); for ( i = 0; i < p->nOuts; i++ ) VarVals[p->nDivs + p->nNodes + i] = (iOutMint >> i) & 1; if ( 0 ) { printf( "Adding minterm %d: ", iMint ); for ( i = 0; i < p->nObjs; i++ ) printf( " %d=%d", i, VarVals[i] ); printf( "\n" ); } for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) { int iVarStart = 1 + 5*(i - p->nDivs);// int iBaseVarI = iNodeVar + 3*(i - p->nDivs); for ( k = 0; k < 2; k++ ) for ( j = 0; j < i; j++ ) if ( p->VarMarks[i][k][j] ) for ( n = 0; n < 2; n++ ) Exa4_ManAddClause4( p, Abc_Var2Lit(p->VarMarks[i][k][j], 1), Abc_Var2Lit(iBaseVarI + k, n), Abc_LitNotCond(VarVals[j], !n), 0); if ( fFancy ) { // Clauses for a*b = c // a + ~c // b + ~c // ~a + ~b + c Exa4_ManAddClause4( p, Abc_Var2Lit(iVarStart + 0, 1), Abc_Var2Lit(iBaseVarI + 0, 0), 0, Abc_Var2Lit(iBaseVarI + 2, 1) ); Exa4_ManAddClause4( p, Abc_Var2Lit(iVarStart + 0, 1), 0, Abc_Var2Lit(iBaseVarI + 1, 0), Abc_Var2Lit(iBaseVarI + 2, 1) ); Exa4_ManAddClause4( p, Abc_Var2Lit(iVarStart + 0, 1), Abc_Var2Lit(iBaseVarI + 0, 1), Abc_Var2Lit(iBaseVarI + 1, 1), Abc_Var2Lit(iBaseVarI + 2, 0) ); Exa4_ManAddClause4( p, Abc_Var2Lit(iVarStart + 1, 1), Abc_Var2Lit(iBaseVarI + 0, 1), 0, Abc_Var2Lit(iBaseVarI + 2, 1) ); Exa4_ManAddClause4( p, Abc_Var2Lit(iVarStart + 1, 1), 0, Abc_Var2Lit(iBaseVarI + 1, 0), Abc_Var2Lit(iBaseVarI + 2, 1) ); Exa4_ManAddClause4( p, Abc_Var2Lit(iVarStart + 1, 1), Abc_Var2Lit(iBaseVarI + 0, 0), Abc_Var2Lit(iBaseVarI + 1, 1), Abc_Var2Lit(iBaseVarI + 2, 0) ); Exa4_ManAddClause4( p, Abc_Var2Lit(iVarStart + 2, 1), Abc_Var2Lit(iBaseVarI + 0, 0), 0, Abc_Var2Lit(iBaseVarI + 2, 1) ); Exa4_ManAddClause4( p, Abc_Var2Lit(iVarStart + 2, 1), 0, Abc_Var2Lit(iBaseVarI + 1, 1), Abc_Var2Lit(iBaseVarI + 2, 1) ); Exa4_ManAddClause4( p, Abc_Var2Lit(iVarStart + 2, 1), Abc_Var2Lit(iBaseVarI + 0, 1), Abc_Var2Lit(iBaseVarI + 1, 0), Abc_Var2Lit(iBaseVarI + 2, 0) ); // Clauses for a+b = c // ~a + c // ~b + c // a + b + ~c Exa4_ManAddClause4( p, Abc_Var2Lit(iVarStart + 3, 1), Abc_Var2Lit(iBaseVarI + 0, 1), 0, Abc_Var2Lit(iBaseVarI + 2, 0) ); Exa4_ManAddClause4( p, Abc_Var2Lit(iVarStart + 3, 1), 0, Abc_Var2Lit(iBaseVarI + 1, 1), Abc_Var2Lit(iBaseVarI + 2, 0) ); Exa4_ManAddClause4( p, Abc_Var2Lit(iVarStart + 3, 1), Abc_Var2Lit(iBaseVarI + 0, 0), Abc_Var2Lit(iBaseVarI + 1, 0), Abc_Var2Lit(iBaseVarI + 2, 1) ); // Clauses for a^b = c // ~a + ~b + ~c // ~a + b + c // a + ~b + c // a + b + ~c if ( !fOnlyAnd ) { Exa4_ManAddClause4( p, Abc_Var2Lit(iVarStart + 4, 1), Abc_Var2Lit(iBaseVarI + 0, 1), Abc_Var2Lit(iBaseVarI + 1, 1), Abc_Var2Lit(iBaseVarI + 2, 1) ); Exa4_ManAddClause4( p, Abc_Var2Lit(iVarStart + 4, 1), Abc_Var2Lit(iBaseVarI + 0, 1), Abc_Var2Lit(iBaseVarI + 1, 0), Abc_Var2Lit(iBaseVarI + 2, 0) ); Exa4_ManAddClause4( p, Abc_Var2Lit(iVarStart + 4, 1), Abc_Var2Lit(iBaseVarI + 0, 0), Abc_Var2Lit(iBaseVarI + 1, 1), Abc_Var2Lit(iBaseVarI + 2, 0) ); Exa4_ManAddClause4( p, Abc_Var2Lit(iVarStart + 4, 1), Abc_Var2Lit(iBaseVarI + 0, 0), Abc_Var2Lit(iBaseVarI + 1, 0), Abc_Var2Lit(iBaseVarI + 2, 1) ); } } else { for ( k = 0; k < 4; k++ ) for ( n = 0; n < 2; n++ ) Exa4_ManAddClause4( p, Abc_Var2Lit(iBaseVarI + 0, k&1), Abc_Var2Lit(iBaseVarI + 1, k>>1), Abc_Var2Lit(iBaseVarI + 2, !n), Abc_Var2Lit(k ? iVarStart + k-1 : 0, n)); } } for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) { for ( j = 0; j < p->nDivs + p->nNodes; j++ ) if ( p->VarMarks[i][0][j] ) for ( n = 0; n < 2; n++ ) Exa4_ManAddClause4( p, Abc_Var2Lit(p->VarMarks[i][0][j], 1), Abc_LitNotCond(VarVals[j], n), Abc_LitNotCond(VarVals[i], !n), 0); } } void Exa4_ManGenCnf( Exa4_Man_t * p, char * pFileName, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans ) { int m; assert( p->pFile == NULL ); p->pFile = fopen( pFileName, "wb" ); fputs( "p cnf \n", p->pFile ); Exa4_ManGenStart( p, fOnlyAnd, fFancy, fOrderNodes, fUniqFans ); for ( m = 1; m < Vec_WrdSize(p->vSimsIn); m++ ) Exa4_ManGenMint( p, m, fOnlyAnd, fFancy ); rewind( p->pFile ); fprintf( p->pFile, "p cnf %d %d", p->nCnfVars, p->nCnfClauses ); fclose( p->pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Exa4_ManFindFanin( Exa4_Man_t * p, Vec_Int_t * vValues, int i, int k ) { int j, Count = 0, iVar = -1; for ( j = 0; j < p->nObjs; j++ ) if ( p->VarMarks[i][k][j] && Vec_IntEntry(vValues, p->VarMarks[i][k][j]) ) { iVar = j; Count++; } assert( Count == 1 ); return iVar; } static inline void Exa4_ManPrintFanin( Exa4_Man_t * p, int iNode, int fComp ) { if ( iNode == 0 ) printf( " %s", fComp ? "const1" : "const0" ); else if ( iNode > 0 && iNode <= p->nIns ) printf( " %s%c", fComp ? "~" : "", 'a'+iNode-1 ); else if ( iNode > p->nIns && iNode < p->nDivs ) printf( " %s%c", fComp ? "~" : "", 'A'+iNode-p->nIns-1 ); else printf( " %s%d", fComp ? "~" : "", iNode ); } void Exa4_ManPrintSolution( Exa4_Man_t * p, Vec_Int_t * vValues, int fFancy ) { int i, k; printf( "Circuit for %d-var function with %d divisors contains %d two-input gates:\n", p->nIns, p->nDivs, p->nNodes ); for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) { int iVar = Exa4_ManFindFanin( p, vValues, i, 0 ); printf( "%2d = ", i ); Exa4_ManPrintFanin( p, iVar, 0 ); printf( "\n" ); } for ( i = p->nDivs + p->nNodes - 1; i >= p->nDivs; i-- ) { int iVarStart = 1 + 5*(i - p->nDivs);// if ( fFancy ) { int Val1 = Vec_IntEntry(vValues, iVarStart); int Val2 = Vec_IntEntry(vValues, iVarStart+1); int Val3 = Vec_IntEntry(vValues, iVarStart+2); int Val4 = Vec_IntEntry(vValues, iVarStart+3); //int Val5 = Vec_IntEntry(vValues, iVarStart+4); printf( "%2d = ", i ); for ( k = 0; k < 2; k++ ) { int iNode = Exa4_ManFindFanin( p, vValues, i, !k ); int fComp = k ? Val1 | Val3 : Val2 | Val3; Exa4_ManPrintFanin( p, iNode, fComp ); if ( k ) break; printf( " %c", (Val1 || Val2 || Val3) ? '&' : (Val4 ? '|' : '^') ); } } else { int Val1 = Vec_IntEntry(vValues, iVarStart); int Val2 = Vec_IntEntry(vValues, iVarStart+1); int Val3 = Vec_IntEntry(vValues, iVarStart+2); printf( "%2d = ", i ); for ( k = 0; k < 2; k++ ) { int iNode = Exa4_ManFindFanin( p, vValues, i, !k ); int fComp = k ? !Val1 && Val2 && !Val3 : Val1 && !Val2 && !Val3; Exa4_ManPrintFanin( p, iNode, fComp ); if ( k ) break; printf( " %c", (Val1 && Val2) ? (Val3 ? '|' : '^') : '&' ); } } printf( "\n" ); } } Mini_Aig_t * Exa4_ManMiniAig( Exa4_Man_t * p, Vec_Int_t * vValues, int fFancy ) { int i, k, Compl[MAJ_NOBJS] = {0}; Mini_Aig_t * pMini = Mini_AigStartSupport( p->nDivs-1, p->nObjs ); for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) { int iNodes[2] = {0}; int iVarStart = 1 + 5*(i - p->nDivs);// if ( fFancy ) { int Val1 = Vec_IntEntry(vValues, iVarStart); int Val2 = Vec_IntEntry(vValues, iVarStart+1); int Val3 = Vec_IntEntry(vValues, iVarStart+2); int Val4 = Vec_IntEntry(vValues, iVarStart+3); int Val5 = Vec_IntEntry(vValues, iVarStart+4); for ( k = 0; k < 2; k++ ) { int iNode = Exa4_ManFindFanin( p, vValues, i, !k ); int fComp = k ? Val1 | Val3 : Val2 | Val3; iNodes[k] = Abc_Var2Lit(iNode, fComp ^ Compl[iNode]); } if ( Val1 || Val2 || Val3 ) Mini_AigAnd( pMini, iNodes[0], iNodes[1] ); else { if ( Val4 ) Mini_AigOr( pMini, iNodes[0], iNodes[1] ); else if ( Val5 ) Mini_AigXorSpecial( pMini, iNodes[0], iNodes[1] ); else assert( 0 ); } } else { int Val1 = Vec_IntEntry(vValues, iVarStart); int Val2 = Vec_IntEntry(vValues, iVarStart+1); int Val3 = Vec_IntEntry(vValues, iVarStart+2); Compl[i] = Val1 && Val2 && Val3; for ( k = 0; k < 2; k++ ) { int iNode = Exa4_ManFindFanin( p, vValues, i, !k ); int fComp = k ? !Val1 && Val2 && !Val3 : Val1 && !Val2 && !Val3; iNodes[k] = Abc_Var2Lit(iNode, fComp ^ Compl[iNode]); } if ( Val1 && Val2 ) { if ( Val3 ) Mini_AigOr( pMini, iNodes[0], iNodes[1] ); else Mini_AigXorSpecial( pMini, iNodes[0], iNodes[1] ); } else Mini_AigAnd( pMini, iNodes[0], iNodes[1] ); } } for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) { int iVar = Exa4_ManFindFanin( p, vValues, i, 0 ); Mini_AigCreatePo( pMini, Abc_Var2Lit(iVar, Compl[iVar]) ); } assert( p->nObjs == Mini_AigNodeNum(pMini) ); return pMini; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mini_Aig_t * Exa4_ManGenTest( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, int TimeOut, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans, int fVerbose ) { Mini_Aig_t * pMini = NULL; abctime clkTotal = Abc_Clock(); Vec_Int_t * vValues = NULL; char * pFileNameIn = "_temp_.cnf"; char * pFileNameOut = "_temp_out.cnf"; Exa4_Man_t * p = Exa4_ManAlloc( vSimsIn, vSimsOut, nIns, nDivs, nOuts, nNodes, fVerbose ); Exa_ManIsNormalized( vSimsIn, vSimsOut ); Exa4_ManGenCnf( p, pFileNameIn, fOnlyAnd, fFancy, fOrderNodes, fUniqFans ); if ( fVerbose ) printf( "Timeout = %d. OnlyAnd = %d. Fancy = %d. OrderNodes = %d. UniqueFans = %d. Verbose = %d.\n", TimeOut, fOnlyAnd, fFancy, fOrderNodes, fUniqFans, fVerbose ); if ( fVerbose ) printf( "CNF with %d variables and %d clauses was dumped into file \"%s\".\n", p->nCnfVars, p->nCnfClauses, pFileNameIn ); vValues = Exa4_ManSolve( pFileNameIn, pFileNameOut, TimeOut, fVerbose ); if ( vValues ) pMini = Exa4_ManMiniAig( p, vValues, fFancy ); //if ( vValues ) Exa4_ManPrintSolution( p, vValues, fFancy ); if ( vValues ) Exa_ManMiniPrint( pMini, p->nIns ); if ( vValues ) Exa_ManMiniVerify( pMini, vSimsIn, vSimsOut ); Vec_IntFreeP( &vValues ); Exa4_ManFree( p ); Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); return pMini; } void Exa_ManExactSynthesis4_( Bmc_EsPar_t * pPars ) { Mini_Aig_t * pMini = NULL; int i, m; Vec_Wrd_t * vSimsIn = Vec_WrdStart( 8 ); Vec_Wrd_t * vSimsOut = Vec_WrdStart( 8 ); int Truths[2] = { 0x96, 0xE8 }; for ( m = 0; m < 8; m++ ) { int iOutMint = 0; for ( i = 0; i < 2; i++ ) if ( (Truths[i] >> m) & 1 ) iOutMint |= 1 << i; Abc_TtSetBit( Vec_WrdEntryP(vSimsOut, m), iOutMint ); for ( i = 0; i < 3; i++ ) if ( (m >> i) & 1 ) Abc_TtSetBit( Vec_WrdEntryP(vSimsIn, m), 1+i ); } pMini = Exa4_ManGenTest( vSimsIn, vSimsOut, 3, 4, 2, pPars->nNodes, pPars->RuntimeLim, pPars->fOnlyAnd, pPars->fFewerVars, pPars->fOrderNodes, pPars->fUniqFans, pPars->fVerbose ); if ( pMini ) Mini_AigStop( pMini ); Vec_WrdFree( vSimsIn ); Vec_WrdFree( vSimsOut ); } void Exa_ManExactSynthesis4( Bmc_EsPar_t * pPars ) { Mini_Aig_t * pMini = NULL; int i, m, nMints = 1 << pPars->nVars, fCompl = 0; Vec_Wrd_t * vSimsIn = Vec_WrdStart( nMints ); Vec_Wrd_t * vSimsOut = Vec_WrdStart( nMints ); word pTruth[16]; Abc_TtReadHex( pTruth, pPars->pTtStr ); if ( pTruth[0] & 1 ) { fCompl = 1; Abc_TtNot( pTruth, Abc_TtWordNum(pPars->nVars) ); } assert( pPars->nVars <= 10 ); for ( m = 0; m < nMints; m++ ) { Abc_TtSetBit( Vec_WrdEntryP(vSimsOut, m), Abc_TtGetBit(pTruth, m) ); for ( i = 0; i < pPars->nVars; i++ ) if ( (m >> i) & 1 ) Abc_TtSetBit( Vec_WrdEntryP(vSimsIn, m), 1+i ); } assert( Vec_WrdSize(vSimsIn) == (1 << pPars->nVars) ); pMini = Exa4_ManGenTest( vSimsIn, vSimsOut, pPars->nVars, 1+pPars->nVars, 1, pPars->nNodes, pPars->RuntimeLim, pPars->fOnlyAnd, pPars->fFewerVars, pPars->fOrderNodes, pPars->fUniqFans, pPars->fVerbose ); if ( pMini ) Mini_AigStop( pMini ); if ( fCompl ) printf( "The resulting circuit, if computed, will be complemented.\n" ); Vec_WrdFree( vSimsIn ); Vec_WrdFree( vSimsOut ); } typedef struct Exa5_Man_t_ Exa5_Man_t; struct Exa5_Man_t_ { Vec_Wrd_t * vSimsIn; Vec_Wrd_t * vSimsOut; int fVerbose; int nIns; int nDivs; // divisors (const + inputs + tfi + sidedivs) int nNodes; int nOuts; int nObjs; int VarMarks[MAJ_NOBJS][MAJ_NOBJS]; int nCnfVars; int nCnfClauses; FILE * pFile; Vec_Int_t * vFans; }; /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Exa5_ManMarkup( Exa5_Man_t * p ) { int i, j, k, nVars[3] = {1 + 3*p->nNodes, 0, p->nNodes*Vec_WrdSize(p->vSimsIn)}; assert( p->nObjs <= MAJ_NOBJS ); Vec_IntFill( p->vFans, 1 + 3*p->nNodes, 0 ); for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) for ( j = 2; j < i; j++ ) { p->VarMarks[i][j] = nVars[0] + nVars[1]; Vec_IntPush( p->vFans, 0 ); for ( k = 1; k < j; k++ ) Vec_IntPush( p->vFans, (i << 16) | (j << 8) | k ); nVars[1] += j; } assert( Vec_IntSize(p->vFans) == nVars[0] + nVars[1] ); for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) for ( j = p->nOuts == 1 ? p->nDivs + p->nNodes - 1 : 0; j < p->nDivs + p->nNodes; j++ ) p->VarMarks[i][j] = nVars[0] + nVars[1]++; if ( p->fVerbose ) printf( "Variables: Function = %d. Structure = %d. Internal = %d. Total = %d.\n", nVars[0], nVars[1], nVars[2], nVars[0] + nVars[1] + nVars[2] ); if ( 0 ) { { printf( " : " ); for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) { printf( "%3d ", i ); printf( " " ); } printf( " " ); for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) { printf( "%3d ", i ); printf( " " ); } printf( "\n" ); } for ( j = 0; j < 5 + p->nNodes*5 + p->nOuts*5; j++ ) printf( "-" ); printf( "\n" ); for ( j = p->nObjs - 2; j >= 0; j-- ) { if ( j > 0 && j <= p->nIns ) printf( " %c : ", 'a'+j-1 ); else printf( "%2d : ", j ); for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) { printf( "%3d ", p->VarMarks[i][j] ); printf( " " ); } printf( " " ); for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) { printf( "%3d ", p->VarMarks[i][j] ); printf( " " ); } printf( "\n" ); } } return nVars[0] + nVars[1] + nVars[2]; } Exa5_Man_t * Exa5_ManAlloc( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, int fVerbose ) { Exa5_Man_t * p = ABC_CALLOC( Exa5_Man_t, 1 ); assert( Vec_WrdSize(vSimsIn) == Vec_WrdSize(vSimsOut) ); p->vSimsIn = vSimsIn; p->vSimsOut = vSimsOut; p->fVerbose = fVerbose; p->nIns = nIns; p->nDivs = nDivs; p->nNodes = nNodes; p->nOuts = nOuts; p->nObjs = p->nDivs + p->nNodes + p->nOuts; p->vFans = Vec_IntAlloc( 5000 ); p->nCnfVars = Exa5_ManMarkup( p ); return p; } void Exa5_ManFree( Exa5_Man_t * p ) { Vec_IntFree( p->vFans ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Exa5_ManAddClause( Exa5_Man_t * p, int * pLits, int nLits ) { int i, k = 0; for ( i = 0; i < nLits; i++ ) if ( pLits[i] == 1 ) return 0; else if ( pLits[i] == 0 ) continue; else if ( pLits[i] <= 2*p->nCnfVars ) pLits[k++] = pLits[i]; else assert( 0 ); nLits = k; assert( nLits > 0 ); if ( p->pFile ) { p->nCnfClauses++; for ( i = 0; i < nLits; i++ ) fprintf( p->pFile, "%s%d ", Abc_LitIsCompl(pLits[i]) ? "-" : "", Abc_Lit2Var(pLits[i]) ); fprintf( p->pFile, "0\n" ); } if ( 0 ) { for ( i = 0; i < nLits; i++ ) fprintf( stdout, "%s%d ", Abc_LitIsCompl(pLits[i]) ? "-" : "", Abc_Lit2Var(pLits[i]) ); fprintf( stdout, "\n" ); } return 1; } static inline int Exa5_ManAddClause4( Exa5_Man_t * p, int Lit0, int Lit1, int Lit2, int Lit3, int Lit4 ) { int pLits[5] = { Lit0, Lit1, Lit2, Lit3, Lit4 }; return Exa5_ManAddClause( p, pLits, 5 ); } static inline void Exa5_ManAddOneHot( Exa5_Man_t * p, int * pLits, int nLits ) { int n, m; for ( n = 0; n < nLits; n++ ) for ( m = n+1; m < nLits; m++ ) Exa5_ManAddClause4( p, Abc_LitNot(pLits[n]), Abc_LitNot(pLits[m]), 0, 0, 0 ); } static inline void Exa5_ManAddGroup( Exa5_Man_t * p, int iVar, int nVars ) { int i, pLits[MAJ_NOBJS]; assert( nVars+1 <= MAJ_NOBJS ); pLits[0] = Abc_Var2Lit( iVar, 1 ); for ( i = 1; i <= nVars; i++ ) pLits[i] = Abc_Var2Lit( iVar+i, 0 ); Exa5_ManAddClause( p, pLits, nVars+1 ); Exa5_ManAddOneHot( p, pLits+1, nVars ); for ( i = 1; i <= nVars; i++ ) Exa5_ManAddClause4( p, Abc_LitNot(pLits[0]), Abc_LitNot(pLits[i]), 0, 0, 0 ); } int Exa5_ManGenStart( Exa5_Man_t * p, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans ) { Vec_Int_t * vArray = Vec_IntAlloc( 100 ); int pLits[MAJ_NOBJS], i, j, k, n, m, nLits, iObj; for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) { int iVarStart = 1 + 3*(i - p->nDivs);// nLits = 0; for ( j = 0; j < i; j++ ) if ( p->VarMarks[i][j] ) Exa5_ManAddGroup( p, p->VarMarks[i][j], j-1 ), pLits[nLits++] = Abc_Var2Lit(p->VarMarks[i][j], 0); Exa5_ManAddClause( p, pLits, nLits ); Exa5_ManAddOneHot( p, pLits, nLits ); if ( fOrderNodes ) for ( j = p->nDivs; j < i; j++ ) for ( n = 0; n < p->nObjs; n++ ) if ( p->VarMarks[i][n] ) for ( m = n+1; m < p->nObjs; m++ ) if ( p->VarMarks[j][m] ) Exa5_ManAddClause4( p, Abc_Var2Lit(p->VarMarks[i][n], 1), Abc_Var2Lit(p->VarMarks[j][m], 1), 0, 0, 0 ); for ( j = p->nDivs; j < i; j++ ) if ( p->VarMarks[i][j] ) { // go through all variables of i that point to j and k for ( n = 1; n < j; n++ ) { int iVar = p->VarMarks[i][j] + n; // variable of i pointing to j int iObj = Vec_IntEntry( p->vFans, iVar ); int iNode0 = (iObj >> 0) & 0xFF; int iNode1 = (iObj >> 8) & 0xFF; int iNode2 = (iObj >> 16) & 0xFF; assert( iObj > 0 ); assert( iNode1 == j ); assert( iNode2 == i ); // go through all variables of j and block those that point to k assert( p->VarMarks[j][2] > 0 ); assert( p->VarMarks[j+1][2] > 0 ); for ( m = p->VarMarks[j][2]+1; m < p->VarMarks[j+1][2]; m++ ) { int jObj = Vec_IntEntry( p->vFans, m ); int jNode0 = (jObj >> 0) & 0xFF; int jNode1 = (jObj >> 8) & 0xFF; int jNode2 = (jObj >> 16) & 0xFF; if ( jObj == 0 ) continue; assert( jNode2 == j ); if ( iNode0 == jNode0 || iNode0 == jNode1 ) Exa5_ManAddClause4( p, Abc_Var2Lit(iVar, 1), Abc_Var2Lit(m, 1), 0, 0, 0 ); } } } for ( k = 0; k < 3; k++ ) Exa5_ManAddClause4( p, Abc_Var2Lit(iVarStart, k==1), Abc_Var2Lit(iVarStart+1, k==2), Abc_Var2Lit(iVarStart+2, k!=0), 0, 0); if ( fOnlyAnd ) Exa5_ManAddClause4( p, Abc_Var2Lit(iVarStart, 1), Abc_Var2Lit(iVarStart+1, 1), Abc_Var2Lit(iVarStart+2, 0), 0, 0); } for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) { Vec_IntClear( vArray ); Vec_IntForEachEntry( p->vFans, iObj, k ) if ( iObj && ((iObj & 0xFF) == i || ((iObj >> 8) & 0xFF) == i) ) Vec_IntPush( vArray, Abc_Var2Lit(k, 0) ); for ( k = p->nDivs + p->nNodes; k < p->nObjs; k++ ) if ( p->VarMarks[k][i] ) Vec_IntPush( vArray, Abc_Var2Lit(p->VarMarks[k][i], 0) ); Exa5_ManAddClause( p, Vec_IntArray(vArray), Vec_IntSize(vArray) ); if ( fUniqFans ) Exa5_ManAddOneHot( p, Vec_IntArray(vArray), Vec_IntSize(vArray) ); } Vec_IntFree( vArray ); for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) { nLits = 0; for ( j = 0; j < p->nDivs + p->nNodes; j++ ) if ( p->VarMarks[i][j] ) pLits[nLits++] = Abc_Var2Lit( p->VarMarks[i][j], 0 ); Exa5_ManAddClause( p, pLits, nLits ); Exa5_ManAddOneHot( p, pLits, nLits ); } return 1; } void Exa5_ManGenMint( Exa5_Man_t * p, int iMint, int fOnlyAnd, int fFancy ) { int iNodeVar = p->nCnfVars + p->nNodes*(iMint - Vec_WrdSize(p->vSimsIn)); int iOutMint = Abc_Tt6FirstBit( Vec_WrdEntry(p->vSimsOut, iMint) ); int i, k, n, j, VarVals[MAJ_NOBJS], iNodes[3], iVarStart, iObj; assert( p->nObjs <= MAJ_NOBJS ); assert( iMint < Vec_WrdSize(p->vSimsIn) ); for ( i = 0; i < p->nDivs; i++ ) VarVals[i] = (Vec_WrdEntry(p->vSimsIn, iMint) >> i) & 1; for ( i = 0; i < p->nNodes; i++ ) VarVals[p->nDivs + i] = Abc_Var2Lit(iNodeVar + i, 0); for ( i = 0; i < p->nOuts; i++ ) VarVals[p->nDivs + p->nNodes + i] = (iOutMint >> i) & 1; if ( 0 ) { printf( "Adding minterm %d: ", iMint ); for ( i = 0; i < p->nObjs; i++ ) printf( " %d=%d", i, VarVals[i] ); printf( "\n" ); } Vec_IntForEachEntry( p->vFans, iObj, i ) { if ( iObj == 0 ) continue; iNodes[1] = (iObj >> 0) & 0xFF; iNodes[0] = (iObj >> 8) & 0xFF; iNodes[2] = (iObj >> 16) & 0xFF; iVarStart = 1 + 3*(iNodes[2] - p->nDivs);// for ( k = 0; k < 4; k++ ) for ( n = 0; n < 2; n++ ) Exa5_ManAddClause4( p, Abc_Var2Lit(i, 1), Abc_LitNotCond(VarVals[iNodes[0]], k&1), Abc_LitNotCond(VarVals[iNodes[1]], k>>1), Abc_LitNotCond(VarVals[iNodes[2]], !n), Abc_Var2Lit(k ? iVarStart + k-1 : 0, n)); } for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) { for ( j = 0; j < p->nDivs + p->nNodes; j++ ) if ( p->VarMarks[i][j] ) for ( n = 0; n < 2; n++ ) Exa5_ManAddClause4( p, Abc_Var2Lit(p->VarMarks[i][j], 1), Abc_LitNotCond(VarVals[j], n), Abc_LitNotCond(VarVals[i], !n), 0, 0); } } void Exa5_ManGenCnf( Exa5_Man_t * p, char * pFileName, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans ) { int m; assert( p->pFile == NULL ); p->pFile = fopen( pFileName, "wb" ); fputs( "p cnf \n", p->pFile ); Exa5_ManGenStart( p, fOnlyAnd, fFancy, fOrderNodes, fUniqFans ); for ( m = 1; m < Vec_WrdSize(p->vSimsIn); m++ ) Exa5_ManGenMint( p, m, fOnlyAnd, fFancy ); rewind( p->pFile ); fprintf( p->pFile, "p cnf %d %d", p->nCnfVars, p->nCnfClauses ); fclose( p->pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Exa5_ManFindFanin( Exa5_Man_t * p, Vec_Int_t * vValues, int i ) { int j, Count = 0, iVar = -1; for ( j = 0; j < p->nObjs; j++ ) if ( p->VarMarks[i][j] && Vec_IntEntry(vValues, p->VarMarks[i][j]) ) { iVar = j; Count++; } assert( Count == 1 ); return iVar; } static inline void Exa5_ManPrintFanin( Exa5_Man_t * p, int iNode, int fComp ) { if ( iNode == 0 ) printf( " %s", fComp ? "const1" : "const0" ); else if ( iNode > 0 && iNode <= p->nIns ) printf( " %s%c", fComp ? "~" : "", 'a'+iNode-1 ); else if ( iNode > p->nIns && iNode < p->nDivs ) printf( " %s%c", fComp ? "~" : "", 'A'+iNode-p->nIns-1 ); else printf( " %s%d", fComp ? "~" : "", iNode ); } void Exa5_ManPrintSolution( Exa5_Man_t * p, Vec_Int_t * vValues, int fFancy ) { int Fan0[MAJ_NOBJS] = {0}; int Fan1[MAJ_NOBJS] = {0}; int Count[MAJ_NOBJS] = {0}; int i, k, iObj, iNodes[3]; printf( "Circuit for %d-var function with %d divisors contains %d two-input gates:\n", p->nIns, p->nDivs, p->nNodes ); Vec_IntForEachEntry( p->vFans, iObj, i ) { if ( iObj == 0 || Vec_IntEntry(vValues, i) == 0 ) continue; iNodes[0] = (iObj >> 0) & 0xFF; iNodes[1] = (iObj >> 8) & 0xFF; iNodes[2] = (iObj >> 16) & 0xFF; assert( p->nDivs <= iNodes[2] && iNodes[2] < p->nDivs + p->nNodes ); Fan0[iNodes[2]] = iNodes[0]; Fan1[iNodes[2]] = iNodes[1]; Count[iNodes[2]]++; } for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) { int iVar = Exa5_ManFindFanin( p, vValues, i ); printf( "%2d = ", i ); Exa5_ManPrintFanin( p, iVar, 0 ); printf( "\n" ); } for ( i = p->nDivs + p->nNodes - 1; i >= p->nDivs; i-- ) { int iVarStart = 1 + 3*(i - p->nDivs);// int Val1 = Vec_IntEntry(vValues, iVarStart); int Val2 = Vec_IntEntry(vValues, iVarStart+1); int Val3 = Vec_IntEntry(vValues, iVarStart+2); assert( Count[i] == 1 ); printf( "%2d = ", i ); for ( k = 0; k < 2; k++ ) { int iNode = k ? Fan1[i] : Fan0[i]; int fComp = k ? !Val1 && Val2 && !Val3 : Val1 && !Val2 && !Val3; Exa5_ManPrintFanin( p, iNode, fComp ); if ( k ) break; printf( " %c", (Val1 && Val2) ? (Val3 ? '|' : '^') : '&' ); } printf( "\n" ); } } Mini_Aig_t * Exa5_ManMiniAig( Exa5_Man_t * p, Vec_Int_t * vValues ) { Mini_Aig_t * pMini = Mini_AigStartSupport( p->nDivs-1, p->nObjs ); int Compl[MAJ_NOBJS] = {0}; int Fan0[MAJ_NOBJS] = {0}; int Fan1[MAJ_NOBJS] = {0}; int Count[MAJ_NOBJS] = {0}; int i, k, iObj, iNodes[3]; Vec_IntForEachEntry( p->vFans, iObj, i ) { if ( iObj == 0 || Vec_IntEntry(vValues, i) == 0 ) continue; iNodes[0] = (iObj >> 0) & 0xFF; iNodes[1] = (iObj >> 8) & 0xFF; iNodes[2] = (iObj >> 16) & 0xFF; assert( p->nDivs <= iNodes[2] && iNodes[2] < p->nDivs + p->nNodes ); Fan0[iNodes[2]] = iNodes[0]; Fan1[iNodes[2]] = iNodes[1]; Count[iNodes[2]]++; } assert( p->nDivs == Mini_AigNodeNum(pMini) ); for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) { int iNodes[2] = {0}; int iVarStart = 1 + 3*(i - p->nDivs);// int Val1 = Vec_IntEntry(vValues, iVarStart); int Val2 = Vec_IntEntry(vValues, iVarStart+1); int Val3 = Vec_IntEntry(vValues, iVarStart+2); assert( Count[i] == 1 ); Compl[i] = Val1 && Val2 && Val3; for ( k = 0; k < 2; k++ ) { int iNode = k ? Fan1[i] : Fan0[i]; int fComp = k ? !Val1 && Val2 && !Val3 : Val1 && !Val2 && !Val3; iNodes[k] = Abc_Var2Lit(iNode, fComp ^ Compl[iNode]); } if ( Val1 && Val2 ) { if ( Val3 ) Mini_AigOr( pMini, iNodes[0], iNodes[1] ); else Mini_AigXorSpecial( pMini, iNodes[0], iNodes[1] ); } else Mini_AigAnd( pMini, iNodes[0], iNodes[1] ); } for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) { int iVar = Exa5_ManFindFanin( p, vValues, i ); Mini_AigCreatePo( pMini, Abc_Var2Lit(iVar, Compl[iVar]) ); } assert( p->nObjs == Mini_AigNodeNum(pMini) ); return pMini; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mini_Aig_t * Exa5_ManGenTest( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, int TimeOut, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans, int fVerbose ) { abctime clkTotal = Abc_Clock(); Mini_Aig_t * pMini = NULL; Vec_Int_t * vValues = NULL; char * pFileNameIn = "_temp_.cnf"; char * pFileNameOut = "_temp_out.cnf"; Exa5_Man_t * p = Exa5_ManAlloc( vSimsIn, vSimsOut, nIns, nDivs, nOuts, nNodes, fVerbose ); Exa_ManIsNormalized( vSimsIn, vSimsOut ); Exa5_ManGenCnf( p, pFileNameIn, fOnlyAnd, fFancy, fOrderNodes, fUniqFans ); if ( fVerbose ) printf( "Timeout = %d. OnlyAnd = %d. Fancy = %d. OrderNodes = %d. UniqueFans = %d. Verbose = %d.\n", TimeOut, fOnlyAnd, fFancy, fOrderNodes, fUniqFans, fVerbose ); if ( fVerbose ) printf( "CNF with %d variables and %d clauses was dumped into file \"%s\".\n", p->nCnfVars, p->nCnfClauses, pFileNameIn ); vValues = Exa4_ManSolve( pFileNameIn, pFileNameOut, TimeOut, fVerbose ); if ( vValues ) pMini = Exa5_ManMiniAig( p, vValues ); //if ( vValues ) Exa5_ManPrintSolution( p, vValues, fFancy ); if ( vValues ) Exa_ManMiniPrint( pMini, p->nIns ); if ( vValues ) Exa_ManMiniVerify( pMini, vSimsIn, vSimsOut ); Vec_IntFreeP( &vValues ); Exa5_ManFree( p ); Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); return pMini; } void Exa_ManExactSynthesis5( Bmc_EsPar_t * pPars ) { Mini_Aig_t * pMini = NULL; int i, m, nMints = 1 << pPars->nVars, fCompl = 0; Vec_Wrd_t * vSimsIn = Vec_WrdStart( nMints ); Vec_Wrd_t * vSimsOut = Vec_WrdStart( nMints ); word pTruth[16]; Abc_TtReadHex( pTruth, pPars->pTtStr ); if ( pTruth[0] & 1 ) { fCompl = 1; Abc_TtNot( pTruth, Abc_TtWordNum(pPars->nVars) ); } assert( pPars->nVars <= 10 ); for ( m = 0; m < nMints; m++ ) { Abc_TtSetBit( Vec_WrdEntryP(vSimsOut, m), Abc_TtGetBit(pTruth, m) ); for ( i = 0; i < pPars->nVars; i++ ) if ( (m >> i) & 1 ) Abc_TtSetBit( Vec_WrdEntryP(vSimsIn, m), 1+i ); } assert( Vec_WrdSize(vSimsIn) == (1 << pPars->nVars) ); pMini = Exa5_ManGenTest( vSimsIn, vSimsOut, pPars->nVars, 1+pPars->nVars, 1, pPars->nNodes, pPars->RuntimeLim, pPars->fOnlyAnd, pPars->fFewerVars, pPars->fOrderNodes, pPars->fUniqFans, pPars->fVerbose ); if ( pMini ) Mini_AigStop( pMini ); if ( fCompl ) printf( "The resulting circuit, if computed, will be complemented.\n" ); Vec_WrdFree( vSimsIn ); Vec_WrdFree( vSimsOut ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END