| /**CFile**************************************************************** |
| |
| FileName [sbd.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [SAT-based optimization using internal don't-cares.] |
| |
| Synopsis [] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: sbd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "sbdInt.h" |
| #include "misc/util/utilTruth.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| #define MAX_M 8 // max inputs |
| #define MAX_N 30 // max nodes |
| #define MAX_K 6 // max lutsize |
| #define MAX_D 8 // max delays |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| // new AIG manager |
| typedef struct Sbd_Pro_t_ Sbd_Pro_t; |
| struct Sbd_Pro_t_ |
| { |
| int nLuts; // LUT count |
| int nSize; // LUT size |
| int nDivs; // divisor count |
| int nVars; // intermediate variables (nLuts * nSize) |
| int nPars; // total parameter count (nLuts * (1 << nSize) + nLuts * nSize * nDivs) |
| int pPars1[SBD_LUTS_MAX][1<<SBD_SIZE_MAX]; // lut parameters |
| int pPars2[SBD_LUTS_MAX][SBD_SIZE_MAX][SBD_DIV_MAX]; // topo parameters |
| int pVars[SBD_LUTS_MAX][SBD_SIZE_MAX+1]; // internal variables |
| int pDivs[SBD_DIV_MAX]; // divisor variables (external) |
| }; |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Int_t * Sbd_ProblemSetup( Sbd_Pro_t * p, int nLuts, int nSize, int nDivs ) |
| { |
| Vec_Int_t * vCnf = Vec_IntAlloc( 1000 ); |
| int i, k, d, v, n, iVar = 0; |
| assert( nLuts >= 1 && nLuts <= 2 ); |
| memset( p, 0, sizeof(Sbd_Pro_t) ); |
| p->nLuts = nLuts; |
| p->nSize = nSize; |
| p->nDivs = nDivs; |
| p->nVars = nLuts * nSize; |
| p->nPars = nLuts * (1 << nSize) + nLuts * nSize * nDivs; |
| // set parameters |
| for ( i = 0; i < nLuts; i++ ) |
| for ( k = 0; k < (1 << nSize); k++ ) |
| p->pPars1[i][k] = iVar++; |
| for ( i = 0; i < nLuts; i++ ) |
| for ( k = 0; k < nSize; k++ ) |
| for ( d = 0; d < nDivs; d++ ) |
| p->pPars2[i][k][d] = iVar++; |
| // set intermediate variables |
| for ( i = 0; i < nLuts; i++ ) |
| for ( k = 0; k < nSize; k++ ) |
| p->pVars[i][k] = iVar++; |
| // set top variables |
| for ( i = 1; i < nLuts; i++ ) |
| p->pVars[i][nSize] = p->pVars[i-1][0]; |
| // set divisor variables |
| for ( d = 0; d < nDivs; d++ ) |
| p->pDivs[d] = iVar++; |
| assert( iVar == p->nPars + p->nVars + p->nDivs ); |
| |
| // input compatiblity clauses |
| for ( i = 0; i < nLuts; i++ ) |
| for ( k = (i > 0); k < nSize; k++ ) |
| for ( d = 0; d < nDivs; d++ ) |
| for ( n = 0; n < nDivs; n++ ) |
| { |
| if ( n < d ) |
| { |
| Vec_IntPush( vCnf, Abc_Var2Lit(p->pPars2[i][k][d], 0) ); |
| Vec_IntPush( vCnf, Abc_Var2Lit(p->pPars2[i][k][n], 0) ); |
| Vec_IntPush( vCnf, -1 ); |
| } |
| else if ( k < nSize-1 ) |
| { |
| Vec_IntPush( vCnf, Abc_Var2Lit(p->pPars2[i][k][d], 0) ); |
| Vec_IntPush( vCnf, Abc_Var2Lit(p->pPars2[i][k+1][n], 0) ); |
| Vec_IntPush( vCnf, -1 ); |
| } |
| } |
| |
| // create LUT clauses |
| for ( i = 0; i < nLuts; i++ ) |
| for ( k = 0; k < (1 << nSize); k++ ) |
| for ( n = 0; n < 2; n++ ) |
| { |
| for ( v = 0; v < nSize; v++ ) |
| Vec_IntPush( vCnf, Abc_Var2Lit(p->pPars1[i][v], (k >> v) & 1) ); |
| Vec_IntPush( vCnf, Abc_Var2Lit(p->pVars[i][nSize], n) ); |
| Vec_IntPush( vCnf, Abc_Var2Lit(p->pPars1[i][k], !n) ); |
| Vec_IntPush( vCnf, -1 ); |
| } |
| |
| // create input clauses |
| for ( i = 0; i < nLuts; i++ ) |
| for ( k = (i > 0); k < nSize; k++ ) |
| for ( d = 0; d < nDivs; d++ ) |
| for ( n = 0; n < 2; n++ ) |
| { |
| Vec_IntPush( vCnf, Abc_Var2Lit(p->pPars2[i][k][d], 0) ); |
| Vec_IntPush( vCnf, Abc_Var2Lit(p->pPars1[i][k], n) ); |
| Vec_IntPush( vCnf, Abc_Var2Lit(p->pDivs[d], !n) ); |
| Vec_IntPush( vCnf, -1 ); |
| } |
| |
| return vCnf; |
| } |
| // add clauses to the don't-care computation solver |
| void Sbd_ProblemLoad1( Sbd_Pro_t * p, Vec_Int_t * vCnf, int iStartVar, int * pDivVars, int iTopVar, sat_solver * pSat ) |
| { |
| int pLits[8], nLits, i, k, iLit, RetValue; |
| int ThisTopVar = p->pVars[0][p->nSize]; |
| int FirstDivVar = p->nPars + p->nVars; |
| // add clauses |
| for ( i = 0; i < Vec_IntSize(vCnf); i++ ) |
| { |
| assert( Vec_IntEntry(vCnf, i) != -1 ); |
| for ( k = i+1; k < Vec_IntSize(vCnf); k++ ) |
| if ( Vec_IntEntry(vCnf, i) == -1 ) |
| break; |
| nLits = 0; |
| Vec_IntForEachEntryStartStop( vCnf, iLit, i, i, k ) { |
| if ( Abc_Lit2Var(iLit) == ThisTopVar ) |
| pLits[nLits++] = Abc_Var2Lit( ThisTopVar, Abc_LitIsCompl(iLit) ); |
| else if ( Abc_Lit2Var(iLit) >= FirstDivVar ) |
| pLits[nLits++] = Abc_Var2Lit( pDivVars[Abc_Lit2Var(iLit)-FirstDivVar], Abc_LitIsCompl(iLit) ); |
| else |
| pLits[nLits++] = iLit + 2 * iStartVar; |
| } |
| assert( nLits <= 8 ); |
| RetValue = sat_solver_addclause( pSat, pLits, pLits + nLits ); |
| assert( RetValue ); |
| } |
| } |
| // add clauses to the functionality evaluation solver |
| void Sbd_ProblemLoad2( Sbd_Pro_t * p, Vec_Wec_t * vCnf, int iStartVar, int * pDivVarValues, int iTopVarValue, sat_solver * pSat ) |
| { |
| Vec_Int_t * vLevel; |
| int pLits[8], nLits, i, k, iLit, RetValue; |
| int ThisTopVar = p->pVars[0][p->nSize]; |
| int FirstDivVar = p->nPars + p->nVars; |
| int FirstIntVar = p->nPars; |
| // add clauses |
| Vec_WecForEachLevel( vCnf, vLevel, i ) |
| { |
| nLits = 0; |
| Vec_IntForEachEntry( vLevel, iLit, k ) { |
| if ( Abc_Lit2Var(iLit) == ThisTopVar ) |
| { |
| if ( Abc_LitIsCompl(iLit) == iTopVarValue ) |
| break; |
| continue; |
| } |
| else if ( Abc_Lit2Var(iLit) >= FirstDivVar ) |
| { |
| if ( Abc_LitIsCompl(iLit) == pDivVarValues[Abc_Lit2Var(iLit)-FirstDivVar] ) |
| break; |
| continue; |
| } |
| else if ( Abc_Lit2Var(iLit) >= FirstIntVar ) |
| pLits[nLits++] = iLit + 2 * iStartVar; |
| else |
| pLits[nLits++] = iLit; |
| } |
| if ( k < Vec_IntSize(vLevel) ) |
| continue; |
| assert( nLits <= 8 ); |
| RetValue = sat_solver_addclause( pSat, pLits, pLits + nLits ); |
| assert( RetValue ); |
| } |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| sat_solver * Sbd_SolverTopo( int M, int N, int K, int pVars[MAX_N][MAX_M+MAX_N][MAX_K], int pVars2[MAX_M+MAX_N][MAX_D], int pDelays[], int Req, int * pnVars ) // inputs, nodes, lutsize |
| { |
| sat_solver * pSat = NULL; |
| Vec_Int_t * vTemp = Vec_IntAlloc(100); |
| // assign vars |
| int RetValue, n, i, j, j2, k, k2, d, Count, nVars = 0; |
| for ( n = 0; n < N; n++ ) |
| for ( i = 0; i < M+N; i++ ) |
| for ( k = 0; k < K; k++ ) |
| pVars[n][i][k] = -1; |
| for ( n = 0; n < N; n++ ) |
| for ( i = 0; i < M+n; i++ ) |
| for ( k = 0; k < K; k++ ) |
| pVars[n][i][k] = nVars++; |
| printf( "Number of topo vars = %d.\n", nVars ); |
| *pnVars = nVars; |
| // add constraints |
| pSat = sat_solver_new(); |
| sat_solver_setnvars( pSat, nVars ); |
| // each node is used |
| for ( i = 0; i < M+N-1; i++ ) |
| { |
| Vec_IntClear( vTemp ); |
| for ( n = 0; n < N; n++ ) |
| for ( k = 0; k < K; k++ ) |
| if ( pVars[n][i][k] >= 0 ) |
| Vec_IntPush( vTemp, Abc_Var2Lit(pVars[n][i][k], 0) ); |
| RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); |
| assert( RetValue ); |
| } |
| printf( "Added %d node connectivity constraints.\n", i ); |
| // each fanin of each node is connected exactly once |
| Count = 0; |
| for ( n = 0; n < N; n++ ) |
| for ( k = 0; k < K; k++ ) |
| { |
| // connected |
| Vec_IntClear( vTemp ); |
| for ( i = 0; i < M+n; i++ ) |
| Vec_IntPush( vTemp, Abc_Var2Lit(pVars[n][i][k], 0) ); |
| RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); |
| assert( RetValue ); |
| // exactly once |
| for ( i = 0; i < M+n; i++ ) |
| for ( j = i+1; j < M+n; j++ ) |
| { |
| Vec_IntFillTwo( vTemp, 2, Abc_Var2Lit(pVars[n][i][k], 1), Abc_Var2Lit(pVars[n][j][k], 1) ); |
| RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); |
| assert( RetValue ); |
| Count++; |
| } |
| } |
| printf( "Added %d fanin connectivity constraints.\n", Count ); |
| // node fanins are unique |
| Count = 0; |
| for ( n = 0; n < N; n++ ) |
| for ( i = 0; i < M+n; i++ ) |
| for ( k = 0; k < K; k++ ) |
| for ( j = i; j < M+n; j++ ) |
| for ( k2 = k+1; k2 < K; k2++ ) |
| { |
| Vec_IntFillTwo( vTemp, 2, Abc_Var2Lit(pVars[n][i][k], 1), Abc_Var2Lit(pVars[n][j][k2], 1) ); |
| RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); |
| assert( RetValue ); |
| Count++; |
| } |
| printf( "Added %d fanin exclusivity constraints.\n", Count ); |
| // nodes are ordered |
| Count = 0; |
| for ( n = 1; n < N; n++ ) |
| for ( i = 0; i < M+n-1; i++ ) |
| { |
| // first of n cannot be smaller than first of n-1 (but can be equal) |
| for ( j = i+1; j < M+n-1; j++ ) |
| { |
| Vec_IntFillTwo( vTemp, 2, Abc_Var2Lit(pVars[n][i][0], 1), Abc_Var2Lit(pVars[n-1][j][0], 1) ); |
| RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); |
| assert( RetValue ); |
| Count++; |
| } |
| // if first nodes of n and n-1 are equal, second nodes are ordered |
| Vec_IntFillTwo( vTemp, 2, Abc_Var2Lit(pVars[n][i][0], 1), Abc_Var2Lit(pVars[n-1][i][0], 1) ); |
| for ( j = 0; j < i; j++ ) |
| for ( j2 = j+1; j2 < i; j2++ ) |
| { |
| Vec_IntPushTwo( vTemp, Abc_Var2Lit(pVars[n][j][1], 1), Abc_Var2Lit(pVars[n-1][j2][1], 1) ); |
| RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); |
| assert( RetValue ); |
| Vec_IntShrink( vTemp, 2 ); |
| Count++; |
| } |
| } |
| printf( "Added %d node ordering constraints.\n", Count ); |
| // exclude fanins of two-input nodes |
| Count = 0; |
| if ( K == 2 ) |
| for ( n = 1; n < N; n++ ) |
| for ( i = M; i < M+n; i++ ) |
| for ( j = 0; j < i; j++ ) |
| for ( k = 0; k < K; k++ ) |
| { |
| Vec_IntClear( vTemp ); |
| Vec_IntPush( vTemp, Abc_Var2Lit(pVars[n][i][0], 1) ); |
| Vec_IntPush( vTemp, Abc_Var2Lit(pVars[n][j][1], 1) ); |
| Vec_IntPush( vTemp, Abc_Var2Lit(pVars[i-M][j][k], 1) ); |
| RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); |
| assert( RetValue ); |
| Count++; |
| } |
| printf( "Added %d two-node non-triviality constraints.\n", Count ); |
| |
| |
| // assign delay vars |
| assert( Req < MAX_D-1 ); |
| for ( i = 0; i < M+N; i++ ) |
| for ( d = 0; d < MAX_D; d++ ) |
| pVars2[i][d] = nVars++; |
| printf( "Number of total vars = %d.\n", nVars ); |
| // set input delays |
| for ( i = 0; i < M; i++ ) |
| { |
| assert( pDelays[i] < MAX_D-2 ); |
| Vec_IntFill( vTemp, 1, Abc_Var2Lit(pVars2[i][pDelays[i]], 0) ); |
| RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); |
| assert( RetValue ); |
| } |
| // set output delay |
| for ( k = Req; k < MAX_D; k++ ) |
| { |
| Vec_IntFill( vTemp, 1, Abc_Var2Lit(pVars2[M+N-1][Req+1], 1) ); |
| RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); |
| assert( RetValue ); |
| } |
| // set internal nodes |
| for ( n = 0; n < N; n++ ) |
| for ( i = 0; i < M+n; i++ ) |
| for ( k = 0; k < K; k++ ) |
| for ( d = 0; d < MAX_D-1; d++ ) |
| { |
| Vec_IntFill( vTemp, 1, Abc_Var2Lit(pVars[n][i][k], 1) ); |
| Vec_IntPush( vTemp, Abc_Var2Lit(pVars2[i][d], 1) ); |
| Vec_IntPush( vTemp, Abc_Var2Lit(pVars2[M+n][d+1], 0) ); |
| RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); |
| assert( RetValue ); |
| } |
| |
| |
| Vec_IntFree( vTemp ); |
| return pSat; |
| } |
| void Sbd_SolverTopoPrint( sat_solver * pSat, int M, int N, int K, int pVars[MAX_N][MAX_M+MAX_N][MAX_K] ) |
| { |
| int n, i, k; |
| printf( "Solution:\n" ); |
| printf( " | " ); |
| for ( n = 0; n < N; n++ ) |
| printf( "%2d ", M+n ); |
| printf( "\n" ); |
| for ( i = M+N-2; i >= 0; i-- ) |
| { |
| printf( "%2d %c | ", i, i < M ? 'i' : ' ' ); |
| for ( n = 0; n < N; n++ ) |
| { |
| for ( k = K-1; k >= 0; k-- ) |
| if ( pVars[n][i][k] == -1 ) |
| printf( " " ); |
| else |
| printf( "%c", sat_solver_var_value(pSat, pVars[n][i][k]) ? '*' : '.' ); |
| printf( " " ); |
| } |
| printf( "\n" ); |
| } |
| } |
| void Sbd_SolverTopoTest() |
| { |
| int M = 8; // 6; // inputs |
| int N = 3; // 16; // nodes |
| int K = 4; // 2; // lutsize |
| int status, v, nVars, nIter, nSols = 0; |
| int pVars[MAX_N][MAX_M+MAX_N][MAX_K]; // 20 x 32 x 6 = 3840 |
| int pVars2[MAX_M+MAX_N][MAX_D]; // 20 x 32 x 6 = 3840 |
| int pDelays[MAX_M] = {1,0,0,0,1}; |
| abctime clk = Abc_Clock(); |
| Vec_Int_t * vLits = Vec_IntAlloc(100); |
| sat_solver * pSat = Sbd_SolverTopo( M, N, K, pVars, pVars2, pDelays, 2, &nVars ); |
| for ( nIter = 0; nIter < 1000000; nIter++ ) |
| { |
| // find onset minterm |
| status = sat_solver_solve( pSat, NULL, NULL, 0, 0, 0, 0 ); |
| if ( status == l_Undef ) |
| break; |
| if ( status == l_False ) |
| break; |
| assert( status == l_True ); |
| nSols++; |
| // print solution |
| if ( nIter < 5 ) |
| Sbd_SolverTopoPrint( pSat, M, N, K, pVars ); |
| // remember variable values |
| Vec_IntClear( vLits ); |
| for ( v = 0; v < nVars; v++ ) |
| if ( sat_solver_var_value(pSat, v) ) |
| Vec_IntPush( vLits, Abc_Var2Lit(v, 1) ); |
| // add breaking clause |
| status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits) ); |
| if ( status == 0 ) |
| break; |
| //if ( nIter == 5 ) |
| // break; |
| } |
| sat_solver_delete( pSat ); |
| Vec_IntFree( vLits ); |
| printf( "Found %d solutions. ", nSols ); |
| Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); |
| } |
| |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Synthesize random topology.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Sbd_SolverSynth( int M, int N, int K, int pLuts[MAX_N][MAX_K] ) |
| { |
| int Used[MAX_M+MAX_N] = {0}; |
| int nUnused = M; |
| int n, iFan0, iFan1; |
| srand( time(NULL) ); |
| for ( n = 0; nUnused < N - n; n++ ) |
| { |
| iFan0 = iFan1 = 0; |
| while ( (iFan0 = rand() % (M + n)) == (iFan1 = rand() % (M + n)) ) |
| ; |
| pLuts[n][0] = iFan0; |
| pLuts[n][1] = iFan1; |
| if ( Used[iFan0] == 0 ) |
| { |
| Used[iFan0] = 1; |
| nUnused--; |
| } |
| if ( Used[iFan1] == 0 ) |
| { |
| Used[iFan1] = 1; |
| nUnused--; |
| } |
| nUnused++; |
| } |
| if ( nUnused == N - n ) |
| { |
| // undo the first one |
| for ( iFan0 = 0; iFan0 < M+n; iFan0++ ) |
| if ( Used[iFan0] ) |
| { |
| Used[iFan0] = 0; |
| nUnused++; |
| break; |
| } |
| |
| } |
| assert( nUnused == N - n + 1 ); |
| for ( ; n < N; n++ ) |
| { |
| for ( iFan0 = 0; iFan0 < M+n; iFan0++ ) |
| if ( Used[iFan0] == 0 ) |
| { |
| Used[iFan0] = 1; |
| break; |
| } |
| assert( iFan0 < M+n ); |
| for ( iFan1 = 0; iFan1 < M+n; iFan1++ ) |
| if ( Used[iFan1] == 0 ) |
| { |
| Used[iFan1] = 1; |
| break; |
| } |
| assert( iFan1 < M+n ); |
| pLuts[n][0] = iFan0; |
| pLuts[n][1] = iFan1; |
| } |
| |
| printf( "{\n" ); |
| for ( n = 0; n < N; n++ ) |
| printf( " {%d, %d}%s // %d\n", pLuts[n][0], pLuts[n][1], n==N-1 ? "" :",", M+n ); |
| printf( "};\n" ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Compute truth table for the given parameter settings.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| word Sbd_SolverTruth( int M, int N, int K, int pLuts[MAX_N][MAX_K], int pValues[MAX_N*((1<<MAX_K)-1)] ) |
| { |
| int i, k, v, nLutPars = (1 << K) - 1; |
| word Truths[MAX_M+MAX_N]; |
| assert( M <= 6 && N <= MAX_N ); |
| for ( i = 0; i < M; i++ ) |
| Truths[i] = s_Truths6[i]; |
| for ( i = 0; i < N; i++ ) |
| { |
| word Truth = 0, Mint; |
| for ( k = 1; k <= nLutPars; k++ ) |
| { |
| if ( !pValues[i*nLutPars+k-1] ) |
| continue; |
| Mint = ~(word)0; |
| for ( v = 0; v < K; v++ ) |
| Mint &= ((k >> v) & 1) ? Truths[pLuts[i][v]] : ~Truths[pLuts[i][v]]; |
| Truth |= Mint; |
| } |
| Truths[M+i] = Truth; |
| } |
| return Truths[M+N-1]; |
| } |
| word * Sbd_SolverTruthWord( int M, int N, int K, int pLuts[MAX_N][MAX_K], int pValues[MAX_N*((1<<MAX_K)-1)], word * pTruthsElem, int fCompl ) |
| { |
| int i, k, v, nLutPars = (1 << K) - 1; |
| int nWords = Abc_TtWordNum( M ); |
| word * pRes = pTruthsElem + (M+N-1)*nWords; |
| assert( M <= MAX_M && N <= MAX_N ); |
| for ( i = 0; i < N; i++ ) |
| { |
| word * pMint, * pTruth = pTruthsElem + (M+i)*nWords; |
| Abc_TtClear( pTruth, nWords ); |
| for ( k = 1; k <= nLutPars; k++ ) |
| { |
| if ( !pValues[i*nLutPars+k-1] ) |
| continue; |
| pMint = pTruthsElem + (M+N)*nWords; |
| Abc_TtFill( pMint, nWords ); |
| for ( v = 0; v < K; v++ ) |
| { |
| word * pFanin = pTruthsElem + pLuts[i][v]*nWords; |
| Abc_TtAndSharp( pMint, pMint, pFanin, nWords, ((k >> v) & 1) == 0 ); |
| } |
| Abc_TtOr( pTruth, pTruth, pMint, nWords ); |
| } |
| } |
| if ( fCompl ) |
| Abc_TtNot( pRes, nWords ); |
| return pRes; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Sbd_SolverFunc( int M, int N, int K, int pLuts[MAX_N][MAX_K], word * pTruthInit, int * pValues ) |
| { |
| int fVerbose = 0; |
| abctime clk = Abc_Clock(); |
| abctime clk2, clkOther = 0; |
| sat_solver * pSat = NULL; |
| int nWords = Abc_TtWordNum(M); |
| int pLits[MAX_K+2], pLits2[MAX_K+2], nLits; |
| int nLutPars = (1 << K) - 1, nVars = N * nLutPars; |
| int i, k, m, status, iMint, Iter, fCompl = (int)(pTruthInit[0] & 1); |
| // create truth tables |
| word * pTruthNew, * pTruths = ABC_ALLOC( word, Abc_TtWordNum(MAX_N) * (MAX_M + MAX_N + 1) ); |
| Abc_TtElemInit2( pTruths, M ); |
| // create solver |
| pSat = sat_solver_new(); |
| sat_solver_setnvars( pSat, nVars ); |
| printf( "Number of parameters %d x %d = %d.\n", N, nLutPars, nVars ); |
| // start with the last minterm |
| // iMint = (1 << M) - 1; |
| iMint = 1; |
| for ( Iter = 0; Iter < (1 << M); Iter++ ) |
| { |
| // assign the first intermediate variable |
| int nVarStart = sat_solver_nvars(pSat); |
| sat_solver_setnvars( pSat, nVarStart + N - 1 ); |
| // add clauses for nodes |
| //if ( fVerbose ) |
| printf( "Iter %3d : Mint = %3d. Conflicts =%8d.\n", Iter, iMint, sat_solver_nconflicts(pSat) ); |
| for ( i = 0; i < N; i++ ) |
| for ( m = 0; m <= nLutPars; m++ ) |
| { |
| if ( fVerbose ) |
| printf( "i = %d. m = %d.\n", i, m ); |
| // selector variables |
| nLits = 0; |
| for ( k = 0; k < K; k++ ) |
| { |
| if ( pLuts[i][k] >= M ) |
| { |
| assert( pLuts[i][k] - M < N - 1 ); |
| pLits[nLits] = pLits2[nLits] = Abc_Var2Lit( nVarStart + pLuts[i][k] - M, (m >> k) & 1 ); |
| nLits++; |
| } |
| else if ( ((iMint >> pLuts[i][k]) & 1) != ((m >> k) & 1) ) |
| break; |
| } |
| if ( k < K ) |
| continue; |
| // add parameter |
| if ( m ) |
| { |
| pLits[nLits] = Abc_Var2Lit( i*nLutPars + m-1, 1 ); |
| pLits2[nLits] = Abc_Var2Lit( i*nLutPars + m-1, 0 ); |
| nLits++; |
| } |
| // node variable |
| if ( i != N - 1 ) |
| { |
| pLits[nLits] = Abc_Var2Lit( nVarStart + i, 0 ); |
| pLits2[nLits] = Abc_Var2Lit( nVarStart + i, 1 ); |
| nLits++; |
| } |
| // add clauses |
| if ( i != N - 1 || Abc_TtGetBit(pTruthInit, iMint) != fCompl ) |
| { |
| status = sat_solver_addclause( pSat, pLits2, pLits2 + nLits ); |
| if ( status == 0 ) |
| { |
| fCompl = -1; |
| goto finish; |
| } |
| } |
| if ( (i != N - 1 || Abc_TtGetBit(pTruthInit, iMint) == fCompl) && m > 0 ) |
| { |
| status = sat_solver_addclause( pSat, pLits, pLits + nLits ); |
| if ( status == 0 ) |
| { |
| fCompl = -1; |
| goto finish; |
| } |
| } |
| } |
| |
| // run SAT solver |
| status = sat_solver_solve( pSat, NULL, NULL, 0, 0, 0, 0 ); |
| if ( status == l_Undef ) |
| break; |
| if ( status == l_False ) |
| { |
| fCompl = -1; |
| goto finish; |
| } |
| assert( status == l_True ); |
| |
| // collect values |
| for ( i = 0; i < nVars; i++ ) |
| pValues[i] = sat_solver_var_value(pSat, i); |
| |
| clk2 = Abc_Clock(); |
| pTruthNew = Sbd_SolverTruthWord( M, N, K, pLuts, pValues, pTruths, fCompl ); |
| clkOther += Abc_Clock() - clk2; |
| |
| if ( fVerbose ) |
| { |
| for ( i = 0; i < nVars; i++ ) |
| printf( "%d=%d ", i, pValues[i] ); |
| printf( " " ); |
| for ( i = nVars; i < sat_solver_nvars(pSat); i++ ) |
| printf( "%d=%d ", i, sat_solver_var_value(pSat, i) ); |
| printf( "\n" ); |
| Extra_PrintBinary( stdout, (unsigned *)pTruthInit, (1 << M) ); printf( "\n" ); |
| Extra_PrintBinary( stdout, (unsigned *)pTruthNew, (1 << M) ); printf( "\n" ); |
| } |
| if ( Abc_TtEqual(pTruthInit, pTruthNew, nWords) ) |
| break; |
| |
| // get new minterm |
| iMint = Abc_TtFindFirstDiffBit( pTruthInit, pTruthNew, M ); |
| } |
| finish: |
| printf( "Finished after %d iterations and %d conflicts. ", Iter, sat_solver_nconflicts(pSat) ); |
| sat_solver_delete( pSat ); |
| ABC_FREE( pTruths ); |
| Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); |
| Abc_PrintTime( 1, "Time", clkOther ); |
| return fCompl; |
| } |
| void Sbd_SolverFuncTest() |
| { |
| // int M = 4; // 6; // inputs |
| // int N = 3; // 16; // nodes |
| // int K = 2; // 2; // lutsize |
| // word Truth = ~((word)3 << 8); |
| // int pLuts[MAX_N][MAX_K] = { {0,1}, {2,3}, {4,5}, {6,7}, {8,9} }; |
| |
| /* |
| int M = 6; // 6; // inputs |
| int N = 19; // 16; // nodes |
| int K = 2; // 2; // lutsize |
| word pTruth[4] = { ABC_CONST(0x9ef7a8d9c7193a0f), 0, 0, 0 }; |
| int pLuts[MAX_N][MAX_K] = { |
| {3, 5}, {1, 6}, {0, 5}, {8, 2}, {7, 9}, |
| {0, 1}, {2, 11}, {5, 12}, {3, 13}, {1, 14}, |
| {10, 15}, {11, 2}, {3, 17}, {9, 18}, {0, 13}, |
| {20, 7}, {19, 21}, {4, 16}, {23, 22} |
| }; |
| */ |
| |
| /* |
| int M = 6; // 6; // inputs |
| int N = 5; // 16; // nodes |
| int K = 4; // 2; // lutsize |
| word Truth = ABC_CONST(0x9ef7a8d9c7193a0f); |
| int pLuts[MAX_N][MAX_K] = { |
| {0, 1, 2, 3}, // 6 |
| {1, 2, 3, 4}, // 7 |
| {2, 3, 4, 5}, // 8 |
| {0, 1, 4, 5}, // 9 |
| {6, 7, 8, 9} // 10 |
| }; |
| */ |
| |
| /* |
| int M = 8; // 6; // inputs |
| int N = 7; // 16; // nodes |
| int K = 2; // 2; // lutsize |
| // word pTruth[4] = { 0, 0, 0, ABC_CONST(0x8000000000000000) }; |
| // word pTruth[4] = { ABC_CONST(0x0000000000000001), 0, 0, 0 }; |
| word pTruth[4] = { 0, 0, 0, ABC_CONST(0x0000000000020000) }; |
| int pLuts[MAX_N][MAX_K] = { {0,1}, {2,3}, {4,5}, {6,7}, {8,9}, {10,11}, {12,13} }; |
| */ |
| |
| int M = 8; // 6; // inputs |
| int N = 7; // 16; // nodes |
| int K = 2; // 2; // lutsize |
| word pTruth[4] = { ABC_CONST(0x0000080000020000), ABC_CONST(0x0000000000020000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000020000) }; |
| int pLuts[MAX_N][MAX_K] = { {0,1}, {2,3}, {4,5}, {6,7}, {8,9}, {10,11}, {12,13} }; |
| |
| int pValues[MAX_N*((1<<MAX_K)-1)]; |
| int Res, i, k, nLutPars = (1 << K) - 1; |
| |
| //Sbd_SolverSynth( M, N, K, pLuts ); |
| |
| Res = Sbd_SolverFunc( M, N, K, pLuts, pTruth, pValues ); |
| if ( Res == -1 ) |
| { |
| printf( "Solution does not exist.\n" ); |
| return; |
| } |
| printf( "Result (compl = %d):\n", Res ); |
| for ( i = 0; i < N; i++ ) |
| { |
| for ( k = nLutPars-1; k >= 0; k-- ) |
| printf( "%d", pValues[i*nLutPars+k] ); |
| printf( "0\n" ); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |