sbdLut.c 10.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/**CFile****************************************************************

  FileName    [sbdLut.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [SAT-based optimization using internal don't-cares.]

  Synopsis    [CNF computation.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - June 20, 2005.]

  Revision    [$Id: sbdLut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]

***********************************************************************/

#include "sbdInt.h"
22
#include "misc/util/utilTruth.h"
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49

ABC_NAMESPACE_IMPL_START

////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
// count the number of parameter variables in the structure
int Sbd_ProblemCountParams( int nStrs, Sbd_Str_t * pStr0 )
{
    Sbd_Str_t * pStr;  int nPars = 0;
    for ( pStr = pStr0; pStr < pStr0 + nStrs; pStr++ )
50
        nPars += pStr->fLut ? 1 << pStr->nVarIns : pStr->nVarIns;
51 52 53
    return nPars;
}
// add clauses for the structure
54
int Sbd_ProblemAddClauses( sat_solver * pSat, int nVars, int nStrs, int * pVars, Sbd_Str_t * pStr0 )
55 56 57 58 59 60
{   
    // variable order:  inputs, structure outputs, parameters
    Sbd_Str_t * pStr;
    int VarOut = nVars;
    int VarPar = nVars + nStrs;
    int m, k, n, status, pLits[SBD_SIZE_MAX+2];
61
//printf( "Start par = %d.  ", VarPar );
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
    for ( pStr = pStr0; pStr < pStr0 + nStrs; pStr++, VarOut++ )
    {
        if ( pStr->fLut )
        {
            int nMints = 1 << pStr->nVarIns;
            assert( pStr->nVarIns <= 6 );
            for ( m = 0; m < nMints; m++, VarPar++ )
            {
                for ( k = 0; k < pStr->nVarIns; k++ )
                    pLits[k] = Abc_Var2Lit( pVars[pStr->VarIns[k]], (m >> k) & 1 ); 
                for ( n = 0; n < 2; n++ )
                {
                    pLits[pStr->nVarIns]   = Abc_Var2Lit( pVars[VarPar], n );
                    pLits[pStr->nVarIns+1] = Abc_Var2Lit( pVars[VarOut], !n );
                    status = sat_solver_addclause( pSat, pLits, pLits + pStr->nVarIns + 2 );
77 78
                    if ( !status )
                        return 0;
79 80 81 82 83
                }
            }
        }
        else
        {
84
            assert( pStr->nVarIns <= SBD_DIV_MAX );
85 86 87 88 89 90 91 92
            for ( k = 0; k < pStr->nVarIns; k++, VarPar++ )
            {
                for ( n = 0; n < 2; n++ )
                {
                    pLits[0] = Abc_Var2Lit( pVars[VarPar], 1 );
                    pLits[1] = Abc_Var2Lit( pVars[VarOut], n );
                    pLits[2] = Abc_Var2Lit( pVars[pStr->VarIns[k]], !n );
                    status = sat_solver_addclause( pSat, pLits, pLits + 3 );
93 94
                    if ( !status )
                        return 0;
95 96 97 98
                }
            }
        }
    }
99
    return 1;
100 101 102 103 104
}
void Sbd_ProblemAddClausesInit( sat_solver * pSat, int nVars, int nStrs, int * pVars, Sbd_Str_t * pStr0 )
{
    Sbd_Str_t * pStr;
    int VarPar = nVars + nStrs;
105
    int m, m2, status, pLits[SBD_DIV_MAX];
106
    // make sure selector parameters are mutually exclusive
107
    for ( pStr = pStr0; pStr < pStr0 + nStrs; VarPar += pStr->fLut ? 1 << pStr->nVarIns : pStr->nVarIns, pStr++ )
108 109 110
    {
        if ( pStr->fLut )
            continue;
111 112 113 114 115 116 117
        // one variable should be selected
        assert( pStr->nVarIns <= SBD_DIV_MAX );
        for ( m = 0; m < pStr->nVarIns; m++ )
            pLits[m] = Abc_Var2Lit( pVars[VarPar + m], 0 );
        status = sat_solver_addclause( pSat, pLits, pLits + pStr->nVarIns );
        assert( status );
        // two variables cannot be selected
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
        for ( m = 0; m < pStr->nVarIns; m++ )
        for ( m2 = m+1; m2 < pStr->nVarIns; m2++ )
        {
            pLits[0] = Abc_Var2Lit( pVars[VarPar + m], 1 );
            pLits[1] = Abc_Var2Lit( pVars[VarPar + m2], 1 );
            status = sat_solver_addclause( pSat, pLits, pLits + 2 );
            assert( status );
        }
    }
}
void Sbd_ProblemPrintSolution( int nStrs, Sbd_Str_t * pStr0, Vec_Int_t * vLits )
{
    Sbd_Str_t * pStr;
    int m, nIters, iLit = 0;
    printf( "Solution found:\n" );
    for ( pStr = pStr0; pStr < pStr0 + nStrs; pStr++ )
    {
        nIters = pStr->fLut ? 1 << pStr->nVarIns : pStr->nVarIns;
136 137 138 139 140 141 142
        printf( "%s%d : ", pStr->fLut ? "LUT":"SEL", (int)(pStr-pStr0) );
        for ( m = 0; m < nIters; m++, iLit++ )
            printf( "%d", !Abc_LitIsCompl(Vec_IntEntry(vLits, iLit)) );
        printf( "    {" );
        for ( m = 0; m < pStr->nVarIns; m++ )
            printf( " %d", pStr->VarIns[m] );
        printf( " }\n" );
143 144 145
    }
    assert( iLit == Vec_IntSize(vLits) );
}
146
void Sbd_ProblemCollectSolution( int nStrs, Sbd_Str_t * pStr0, Vec_Int_t * vLits )
147
{
148 149 150 151 152 153 154 155 156 157 158
    Sbd_Str_t * pStr;
    int m, nIters, iLit = 0;
    for ( pStr = pStr0; pStr < pStr0 + nStrs; pStr++ )
    {
        pStr->Res = 0;
        if ( pStr->fLut )
        {
            nIters = 1 << pStr->nVarIns;
            for ( m = 0; m < nIters; m++, iLit++ )
                if ( !Abc_LitIsCompl(Vec_IntEntry(vLits, iLit)) )
                    Abc_TtSetBit( &pStr->Res, m );
159
            pStr->Res = Abc_Tt6Stretch( pStr->Res, pStr->nVarIns );
160 161 162 163 164 165 166 167 168 169 170 171 172 173
        }
        else
        {
            nIters = 0;
            for ( m = 0; m < pStr->nVarIns; m++, iLit++ )
                if ( !Abc_LitIsCompl(Vec_IntEntry(vLits, iLit)) )
                {
                    pStr->Res = pStr->VarIns[m];
                    nIters++;
                }
            assert( nIters == 1 );
        }
    }
    assert( iLit == Vec_IntSize(vLits) );
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
}

/**Function*************************************************************

  Synopsis    [Solves QBF problem for the given window.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Sbd_ProblemSolve( Gia_Man_t * p, Vec_Int_t * vMirrors, 
                       int Pivot, Vec_Int_t * vWinObjs, Vec_Int_t * vObj2Var, 
                       Vec_Int_t * vTfo, Vec_Int_t * vRoots, 
190
                       Vec_Int_t * vDivSet, int nStrs, Sbd_Str_t * pStr0 )  // divisors, structures
191 192 193
{
    extern sat_solver * Sbd_ManSatSolver( sat_solver * pSat, Gia_Man_t * p, Vec_Int_t * vMirrors, int Pivot, Vec_Int_t * vWinObjs, Vec_Int_t * vObj2Var, Vec_Int_t * vTfo, Vec_Int_t * vRoots, int fQbf );
    
194 195
    int fVerbose = 0;
    abctime clk = Abc_Clock();
196 197 198 199 200 201 202 203
    Vec_Int_t * vLits    = Vec_IntAlloc( 100 );
    sat_solver * pSatCec = Sbd_ManSatSolver( NULL, p, vMirrors, Pivot, vWinObjs, vObj2Var, vTfo, vRoots, 1 );
    sat_solver * pSatQbf = sat_solver_new();

    int nVars      = Vec_IntSize( vDivSet );
    int nPars      = Sbd_ProblemCountParams( nStrs, pStr0 );

    int VarCecOut  = Vec_IntSize(vWinObjs) + Vec_IntSize(vTfo) + Vec_IntSize(vRoots);
204
    int VarCecPar  = VarCecOut + nStrs;
205 206 207 208 209 210

    int VarQbfPar  = 0;
    int VarQbfFree = nPars;

    int pVarsCec[256];
    int pVarsQbf[256];
211
    int i, iVar, iLit, nIters;
212 213
    int RetValue = 0;

214
    assert( Vec_IntSize(vDivSet) <= SBD_DIV_MAX );
215 216 217 218 219
    assert( nVars + nStrs + nPars <= 256 );

    // collect CEC variables
    Vec_IntForEachEntry( vDivSet, iVar, i )
        pVarsCec[i] = iVar;
220 221
    for ( i = 0; i < nStrs; i++ )
        pVarsCec[nVars + i] = VarCecOut + i;
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
    for ( i = 0; i < nPars; i++ )
        pVarsCec[nVars + nStrs + i] = VarCecPar + i;

    // collect QBF variables
    for ( i = 0; i < nVars + nStrs; i++ )
        pVarsQbf[i] = -1;
    for ( i = 0; i < nPars; i++ )
        pVarsQbf[nVars + nStrs + i] = VarQbfPar + i;

    // add clauses to the CEC problem
    Sbd_ProblemAddClauses( pSatCec, nVars, nStrs, pVarsCec, pStr0 );

    // create QBF solver
    sat_solver_setnvars( pSatQbf, 1000 );
    Sbd_ProblemAddClausesInit( pSatQbf, nVars, nStrs, pVarsQbf, pStr0 );

    // assume all parameter variables are 0
    Vec_IntClear( vLits );
    for ( i = 0; i < nPars; i++ )
        Vec_IntPush( vLits, Abc_Var2Lit(VarCecPar + i, 1) );
242
    for ( nIters = 0; nIters < (1 << nVars); nIters++ )
243 244 245 246 247 248
    {
        // check if these parameters solve the problem
        int status = sat_solver_solve( pSatCec, Vec_IntArray(vLits), Vec_IntLimit(vLits), 0, 0, 0, 0 );
        if ( status == l_False ) // solution found
            break;
        assert( status == l_True );
249 250 251 252 253 254 255 256 257

        if ( fVerbose )
        {
            printf( "Iter %3d : ", nIters );
            for ( i = 0; i < nPars; i++ )
                printf( "%d", !Abc_LitIsCompl(Vec_IntEntry(vLits, i)) );
            printf( "    " );
        }

258 259 260 261 262 263 264
        Vec_IntClear( vLits );
        // create new QBF variables
        for ( i = 0; i < nVars + nStrs; i++ )
            pVarsQbf[i] = VarQbfFree++;
        // set their values
        Vec_IntForEachEntry( vDivSet, iVar, i )
        {
265
            iLit = Abc_Var2Lit( pVarsQbf[i], !sat_solver_var_value(pSatCec, iVar) );
266 267
            status = sat_solver_addclause( pSatQbf, &iLit, &iLit + 1 );
            assert( status );
268 269
            if ( fVerbose )
                printf( "%d", sat_solver_var_value(pSatCec, iVar) );
270 271 272 273
        }
        iLit = Abc_Var2Lit( pVarsQbf[nVars], sat_solver_var_value(pSatCec, VarCecOut) );
        status = sat_solver_addclause( pSatQbf, &iLit, &iLit + 1 );
        assert( status );
274 275
        if ( fVerbose )
            printf( " %d\n", !sat_solver_var_value(pSatCec, VarCecOut) );
276
        // add clauses to the QBF problem
277 278
        if ( !Sbd_ProblemAddClauses( pSatQbf, nVars, nStrs, pVarsQbf, pStr0 ) )
            break; // solution does not exist
279 280 281 282 283 284 285 286
        // check if solution still exists
        status = sat_solver_solve( pSatQbf, NULL, NULL, 0, 0, 0, 0 );
        if ( status == l_False ) // solution does not exist
            break;
        assert( status == l_True ); 
        // find the new values of parameters
        assert( Vec_IntSize(vLits) == 0 );
        for ( i = 0; i < nPars; i++ )
287
            Vec_IntPush( vLits, Abc_Var2Lit(VarCecPar + i, !sat_solver_var_value(pSatQbf, VarQbfPar + i)) );
288 289 290
    }
    if ( Vec_IntSize(vLits) > 0 )
    {
291
        //Sbd_ProblemPrintSolution( nStrs, pStr0, vLits );
292
        Sbd_ProblemCollectSolution( nStrs, pStr0, vLits );
293 294 295 296 297
        RetValue = 1;
    }
    sat_solver_delete( pSatCec );
    sat_solver_delete( pSatQbf );
    Vec_IntFree( vLits );
298 299 300

    if ( fVerbose )
        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
301 302 303 304 305 306 307 308 309 310 311
    return RetValue;
}


////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


ABC_NAMESPACE_IMPL_END