mirror of https://github.com/YosysHQ/abc.git
Another variation on exact synthesis.
This commit is contained in:
parent
f97b8d2882
commit
711ea3dfec
|
|
@ -150,6 +150,7 @@ static int Abc_CommandBmsStart ( Abc_Frame_t * pAbc, int argc, cha
|
|||
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_CommandTwoExact ( 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 );
|
||||
|
|
@ -817,6 +818,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
|
|||
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, "Exact synthesis", "twoexact", Abc_CommandTwoExact, 0 );
|
||||
|
||||
Cmd_CommandAdd( pAbc, "Various", "logic", Abc_CommandLogic, 1 );
|
||||
Cmd_CommandAdd( pAbc, "Various", "comb", Abc_CommandComb, 1 );
|
||||
|
|
@ -8136,6 +8138,83 @@ usage:
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
extern void Exa_ManExactSynthesis( char * pTtStr, int nVars, int nNodes, int fVerbose );
|
||||
int c, nVars = 4, nNodes = 3, fVerbose = 1; char * pTtStr = NULL;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "INvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'I':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
nVars = atoi(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( nVars < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'N':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
nNodes = atoi(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( nNodes < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( argc == globalUtilOptind + 1 )
|
||||
pTtStr = argv[globalUtilOptind];
|
||||
if ( pTtStr == NULL )
|
||||
{
|
||||
Abc_Print( -1, "Truth table should be given on the command line.\n" );
|
||||
return 1;
|
||||
}
|
||||
if ( nVars > 10 )
|
||||
{
|
||||
Abc_Print( -1, "Function should not have more than 10 inputs.\n" );
|
||||
return 1;
|
||||
}
|
||||
Exa_ManExactSynthesis( pTtStr, nVars, nNodes, fVerbose );
|
||||
return 0;
|
||||
|
||||
usage:
|
||||
Abc_Print( -2, "usage: twoexact [-IN <num>] [-fcvh] <hex>\n" );
|
||||
Abc_Print( -2, "\t exact synthesis of multi-input function using two-input gates\n" );
|
||||
Abc_Print( -2, "\t-I <num> : the number of input variables [default = %d]\n", nVars );
|
||||
Abc_Print( -2, "\t-N <num> : the number of MAJ3 nodes [default = %d]\n", nNodes );
|
||||
Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n" );
|
||||
Abc_Print( -2, "\t<hex> : truth table in hex notation\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
|
@ -12546,7 +12625,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
// Cba_PrsReadBlifTest();
|
||||
}
|
||||
// Abc_NtkComputePaths( Abc_FrameReadNtk(pAbc) );
|
||||
// Psl_FileTest();
|
||||
Gia_TruthTest();
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: test [-CKDNM] [-aovwh] <file_name>\n" );
|
||||
|
|
|
|||
|
|
@ -1063,7 +1063,7 @@ static inline int Abc_TtReadHex( word * pTruth, char * pString )
|
|||
}
|
||||
}
|
||||
// determine the number of variables
|
||||
nVars = 2 + Abc_Base2Log( nDigits );
|
||||
nVars = 2 + (nDigits == 1 ? 0 : Abc_Base2Log(nDigits));
|
||||
// clean storage
|
||||
for ( k = Abc_TtWordNum(nVars) - 1; k >= 0; k-- )
|
||||
pTruth[k] = 0;
|
||||
|
|
|
|||
|
|
@ -381,6 +381,360 @@ void Maj_ManExactSynthesis( int nVars, int nNodes, int fUseConst, int fUseLine,
|
|||
Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct Exa_Man_t_ Exa_Man_t;
|
||||
struct Exa_Man_t_
|
||||
{
|
||||
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
|
||||
};
|
||||
|
||||
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 variables for truth tables
|
||||
p->iVar = 1 + p->nNodes * 3;
|
||||
// assign variables for other nodes
|
||||
for ( i = p->nVars; i < p->nObjs; i++ )
|
||||
{
|
||||
for ( k = 0; k < 2; k++ )
|
||||
{
|
||||
for ( j = 0; j < i - k; j++ )
|
||||
{
|
||||
Vec_WecPush( p->vOutLits, j, Abc_Var2Lit(p->iVar, 0) );
|
||||
p->VarMarks[i][k][j] = p->iVar++;
|
||||
}
|
||||
}
|
||||
}
|
||||
//printf( "The number of parameter variables = %d.\n", p->iVar );
|
||||
return p->iVar;
|
||||
// printout
|
||||
for ( i = p->nVars; i < p->nObjs; i++ )
|
||||
{
|
||||
printf( "Node %d\n", i );
|
||||
for ( j = 0; j < p->nObjs; j++ )
|
||||
{
|
||||
for ( k = 0; k < 2; k++ )
|
||||
printf( "%3d ", p->VarMarks[i][k][j] );
|
||||
printf( "\n" );
|
||||
}
|
||||
}
|
||||
return p->iVar;
|
||||
}
|
||||
Exa_Man_t * Exa_ManAlloc( int nVars, int nNodes, word * pTruth )
|
||||
{
|
||||
Exa_Man_t * p = ABC_CALLOC( Exa_Man_t, 1 );
|
||||
p->nVars = nVars;
|
||||
p->nNodes = nNodes;
|
||||
p->nObjs = nVars + nNodes;
|
||||
p->nWords = Abc_TtWordNum(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 );
|
||||
return p;
|
||||
}
|
||||
void Exa_ManFree( Exa_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 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_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 []
|
||||
|
||||
***********************************************************************/
|
||||
int Exa_ManAddCnfStart( Exa_Man_t * p )
|
||||
{
|
||||
int pLits[MAJ_NOBJS], pLits2[2], i, j, k, n, m;
|
||||
// input constraints
|
||||
for ( i = p->nVars; i < p->nObjs; i++ )
|
||||
{
|
||||
int iVarStart = 1 + 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 );
|
||||
// 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 == 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;
|
||||
}
|
||||
}
|
||||
// two input functions
|
||||
for ( k = 0; k < 3; k++ )
|
||||
{
|
||||
pLits[0] = Abc_Var2Lit( iVarStart, k==1 );
|
||||
pLits[1] = Abc_Var2Lit( iVarStart+1, k==2 );
|
||||
pLits[2] = Abc_Var2Lit( iVarStart+2, k!=0 );
|
||||
if ( !bmcg_sat_solver_addclause( p->pSat, pLits, 3 ) )
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// outputs should be used
|
||||
for ( i = 0; i < p->nObjs - 1; i++ )
|
||||
{
|
||||
Vec_Int_t * vArray = Vec_WecEntry(p->vOutLits, i);
|
||||
assert( Vec_IntSize(vArray) > 0 );
|
||||
if ( !bmcg_sat_solver_addclause( p->pSat, Vec_IntArray(vArray), Vec_IntSize(vArray) ) )
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
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 ( !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 < 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 ( !bmcg_sat_solver_addclause( p->pSat, pLits, nLits ) )
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
p->iVar += 3*p->nNodes;
|
||||
return 1;
|
||||
}
|
||||
void Exa_ManExactSynthesis( char * pTtStr, int nVars, int nNodes, int fVerbose )
|
||||
{
|
||||
int i, status, iMint = 1;
|
||||
abctime clkTotal = Abc_Clock();
|
||||
Exa_Man_t * p; int fCompl = 0;
|
||||
word pTruth[16]; Abc_TtReadHex( pTruth, pTtStr );
|
||||
assert( nVars <= 10 );
|
||||
p = Exa_ManAlloc( nVars, nNodes, pTruth );
|
||||
if ( pTruth[0] & 1 ) { fCompl = 1; Abc_TtNot( pTruth, p->nWords ); }
|
||||
status = Exa_ManAddCnfStart( p );
|
||||
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;
|
||||
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 = Exa_ManEval( p );
|
||||
}
|
||||
if ( iMint == -1 )
|
||||
Exa_ManPrintSolution( p, fCompl );
|
||||
Exa_ManFree( p );
|
||||
Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
Loading…
Reference in New Issue