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

  FileName    [saigLoc.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Sequential AIG package.]

  Synopsis    [K-step induction for one property only.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

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

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

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

#include "saig.h"
22 23
#include "sat/cnf/cnf.h"
#include "sat/bsat/satSolver.h"
Alan Mishchenko committed
24

25 26 27
ABC_NAMESPACE_IMPL_START


Alan Mishchenko committed
28 29 30 31 32 33 34 35 36 37
////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

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

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

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
  Synopsis    [Returns 1 if two state are equal.]

  Description [Array vState contains indexes of CNF variables for each
  flop in the first N time frames (0 < i < k, i < N, k < N).]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Saig_ManStatesAreEqual( sat_solver * pSat, Vec_Int_t * vState, int nRegs, int i, int k )
{
    int * pStateI = (int *)Vec_IntArray(vState) + nRegs * i;
    int * pStateK = (int *)Vec_IntArray(vState) + nRegs * k;
    int v;
    assert( i && k && i < k );
    assert( nRegs * k <= Vec_IntSize(vState) );
    // check if the states are available
    for ( v = 0; v < nRegs; v++ )
        if ( pStateI[v] >= 0 && pStateK[v] == -1 )
            return 0;
/*
    printf( "\nchecking uniqueness\n" );
    printf( "%3d : ", i );
    for ( v = 0; v < nRegs; v++ )
        printf( "%d", sat_solver_var_value(pSat, pStateI[v]) );
    printf( "\n" );

    printf( "%3d : ", k );
    for ( v = 0; v < nRegs; v++ )
        printf( "%d", sat_solver_var_value(pSat, pStateK[v]) );
    printf( "\n" );
*/
    for ( v = 0; v < nRegs; v++ )
        if ( pStateI[v] >= 0 )
        {
            if ( sat_solver_var_value(pSat, pStateI[v]) != sat_solver_var_value(pSat, pStateK[v]) )
                return 0;
        }
    return 1;
}

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

  Synopsis    [Add uniqueness constraint.]
Alan Mishchenko committed
83 84 85 86 87 88 89 90

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
void Saig_ManAddUniqueness( sat_solver * pSat, Vec_Int_t * vState, int nRegs, int i, int k, int * pnSatVarNum, int * pnClauses )
{
    int * pStateI = (int *)Vec_IntArray(vState) + nRegs * i;
    int * pStateK = (int *)Vec_IntArray(vState) + nRegs * k;
    int v, iVars, nSatVarsOld, RetValue, * pClause;
    assert( i && k && i < k );
    assert( nRegs * k <= Vec_IntSize(vState) );
    // check if the states are available
    for ( v = 0; v < nRegs; v++ )
        if ( pStateI[v] >= 0 && pStateK[v] == -1 )
        {
//            printf( "Cannot constrain an incomplete state.\n" );
            return;
        }
    // add XORs
    nSatVarsOld = *pnSatVarNum;
    for ( v = 0; v < nRegs; v++ )
        if ( pStateI[v] >= 0 )
        {
            *pnClauses += 4;
            RetValue = Cnf_DataAddXorClause( pSat, pStateI[v], pStateK[v], (*pnSatVarNum)++ );
            if ( RetValue == 0 )
            {
                printf( "SAT solver became UNSAT.\n" );
                return;
            }
        }
    // add OR clause
    (*pnClauses)++;
    iVars = 0;
    pClause = ABC_ALLOC( int, nRegs );
    for ( v = nSatVarsOld; v < *pnSatVarNum; v++ )
        pClause[iVars++] = toLitCond( v, 0 );
    assert( iVars <= nRegs );
    RetValue = sat_solver_addclause( pSat, pClause, pClause + iVars );
    ABC_FREE( pClause );
    if ( RetValue == 0 )
    {
        printf( "SAT solver became UNSAT.\n" );
        return;
    }
}

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

  Synopsis    [Performs induction by unrolling timeframes backward.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
145
int Saig_ManInduction( Aig_Man_t * p, int nFramesMax, int nConfMax, int fUnique, int fUniqueAll, int fGetCex, int fVerbose, int fVeryVerbose )
Alan Mishchenko committed
146 147 148 149
{
    sat_solver * pSat;
    Aig_Man_t * pAigPart;
    Cnf_Dat_t * pCnfPart;
150
    Vec_Int_t * vTopVarNums, * vState, * vTopVarIds = NULL;
Alan Mishchenko committed
151 152
    Vec_Ptr_t * vTop, * vBot;
    Aig_Obj_t * pObjPi, * pObjPiCopy, * pObjPo;
153
    int i, k, f, Lits[2], status = -1, RetValue, nSatVarNum, nConfPrev;
154
    int nOldSize, iReg, iLast, fAdded, nConstrs = 0, nClauses = 0;
155
    clock_t clk;
156
    assert( fUnique == 0 || fUniqueAll == 0 );
Alan Mishchenko committed
157
    assert( Saig_ManPoNum(p) == 1 );
158
    Aig_ManSetCioIds( p );
Alan Mishchenko committed
159 160 161 162

    // start the top by including the PO
    vBot = Vec_PtrAlloc( 100 );
    vTop = Vec_PtrAlloc( 100 );
163
    vState = Vec_IntAlloc( 1000 );
164
    Vec_PtrPush( vTop, Aig_ManCo(p, 0) );
Alan Mishchenko committed
165 166 167 168 169 170 171 172 173 174
    // start the array of CNF variables
    vTopVarNums = Vec_IntAlloc( 100 );
    // start the solver
    pSat = sat_solver_new();
    sat_solver_setnvars( pSat, 1000 );

    // iterate backward unrolling
    RetValue = -1;
    nSatVarNum = 0;
    if ( fVerbose )
175
        printf( "Induction parameters: FramesMax = %5d. ConflictMax = %6d.\n", nFramesMax, nConfMax );
Alan Mishchenko committed
176 177 178 179 180 181 182 183 184 185 186 187 188
    for ( f = 0; ; f++ )
    { 
        if ( f > 0 )
        {
            Aig_ManStop( pAigPart );
            Cnf_DataFree( pCnfPart );
        }
        clk = clock();
        // get the bottom
        Aig_SupportNodes( p, (Aig_Obj_t **)Vec_PtrArray(vTop), Vec_PtrSize(vTop), vBot );
        // derive AIG for the part between top and bottom
        pAigPart = Aig_ManDupSimpleDfsPart( p, vBot, vTop );
        // convert it into CNF
189
        pCnfPart = Cnf_Derive( pAigPart, Aig_ManCoNum(pAigPart) );
Alan Mishchenko committed
190 191
        Cnf_DataLift( pCnfPart, nSatVarNum );
        nSatVarNum += pCnfPart->nVars;
192
        nClauses   += pCnfPart->nClauses;
Alan Mishchenko committed
193

194 195 196
        // remember top frame var IDs
        if ( fGetCex && vTopVarIds == NULL )
        {
197
            vTopVarIds = Vec_IntStartFull( Aig_ManCiNum(p) );
198
            Aig_ManForEachCi( p, pObjPi, i )
199 200 201 202
            {
                if ( pObjPi->pData == NULL )
                    continue;
                pObjPiCopy = (Aig_Obj_t *)pObjPi->pData;
203
                assert( Aig_ObjIsCi(pObjPiCopy) );
204
                if ( Saig_ObjIsPi(p, pObjPi) )
205
                    Vec_IntWriteEntry( vTopVarIds, Aig_ObjCioId(pObjPi) + Saig_ManRegNum(p), pCnfPart->pVarNums[Aig_ObjId(pObjPiCopy)] );
206
                else if ( Saig_ObjIsLo(p, pObjPi) )
207
                    Vec_IntWriteEntry( vTopVarIds, Aig_ObjCioId(pObjPi) - Saig_ManPiNum(p), pCnfPart->pVarNums[Aig_ObjId(pObjPiCopy)] );
208 209 210 211
                else assert( 0 );
            }
        }

Alan Mishchenko committed
212
        // stitch variables of top and bot
213
        assert( Aig_ManCoNum(pAigPart)-1 == Vec_IntSize(vTopVarNums) );
214
        Aig_ManForEachCo( pAigPart, pObjPo, i )
Alan Mishchenko committed
215 216 217 218 219 220 221 222 223 224
        {
            if ( i == 0 )
            {
                // do not perform inductive strengthening
//                if ( f > 0 )
//                    continue;
                // add topmost literal
                Lits[0] = toLitCond( pCnfPart->pVarNums[pObjPo->Id], f>0 );
                if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) )
                    assert( 0 );
225
                nClauses++;
Alan Mishchenko committed
226 227 228 229 230 231 232 233 234 235
                continue;
            }
            Lits[0] = toLitCond( Vec_IntEntry(vTopVarNums, i-1), 0 );
            Lits[1] = toLitCond( pCnfPart->pVarNums[pObjPo->Id], 1 );
            if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
                assert( 0 );
            Lits[0] = toLitCond( Vec_IntEntry(vTopVarNums, i-1), 1 );
            Lits[1] = toLitCond( pCnfPart->pVarNums[pObjPo->Id], 0 );
            if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
                assert( 0 );
236
            nClauses += 2;
Alan Mishchenko committed
237 238 239 240 241 242 243 244 245 246 247
        }
        // add CNF to the SAT solver
        for ( i = 0; i < pCnfPart->nClauses; i++ )
            if ( !sat_solver_addclause( pSat, pCnfPart->pClauses[i], pCnfPart->pClauses[i+1] ) )
                break;
        if ( i < pCnfPart->nClauses )
        {
//            printf( "SAT solver became UNSAT after adding clauses.\n" );
            RetValue = 1;
            break;
        }
248 249 250

        // create new set of POs to derive new top
        Vec_PtrClear( vTop );
251
        Vec_PtrPush( vTop, Aig_ManCo(p, 0) );
252 253 254 255 256
        Vec_IntClear( vTopVarNums );
        nOldSize = Vec_IntSize(vState);
        Vec_IntFillExtra( vState, nOldSize + Aig_ManRegNum(p), -1 );
        Vec_PtrForEachEntry( Aig_Obj_t *, vBot, pObjPi, i )
        {
257
            assert( Aig_ObjIsCi(pObjPi) );
258 259 260 261 262 263 264
            if ( Saig_ObjIsLo(p, pObjPi) )
            {
                pObjPiCopy = (Aig_Obj_t *)pObjPi->pData;
                assert( pObjPiCopy != NULL );
                Vec_PtrPush( vTop, Saig_ObjLoToLi(p, pObjPi) );
                Vec_IntPush( vTopVarNums, pCnfPart->pVarNums[pObjPiCopy->Id] );

265
                iReg = pObjPi->CioId - Saig_ManPiNum(p);
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
                assert( iReg >= 0 && iReg < Aig_ManRegNum(p) );
                Vec_IntWriteEntry( vState, nOldSize+iReg, pCnfPart->pVarNums[pObjPiCopy->Id] );
            }
        } 
        iLast = Vec_IntSize(vState)/Aig_ManRegNum(p);
        if ( fUniqueAll )
        {
            for ( i = 1; i < iLast-1; i++ )
            {
                nConstrs++;
                Saig_ManAddUniqueness( pSat, vState, Aig_ManRegNum(p), i, iLast-1, &nSatVarNum, &nClauses );
                if ( fVeryVerbose )
                    printf( "added constaint for %3d and %3d\n", i, iLast-1 );
            }
        }

nextrun:
        fAdded = 0;
Alan Mishchenko committed
284 285
        // run the SAT solver
        nConfPrev = pSat->stats.conflicts;
Alan Mishchenko committed
286
        status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfMax, 0, 0, 0 );
Alan Mishchenko committed
287 288
        if ( fVerbose )
        {
289
            printf( "%4d : PI =%5d. PO =%5d. AIG =%5d. Var =%7d. Clau =%7d. Conf =%7d. ",
290
                f, Aig_ManCiNum(pAigPart), Aig_ManCoNum(pAigPart), Aig_ManNodeNum(pAigPart), 
291
                nSatVarNum, nClauses, (int)pSat->stats.conflicts-nConfPrev );
Alan Mishchenko committed
292
            ABC_PRT( "Time", clock() - clk );
Alan Mishchenko committed
293 294 295 296 297 298 299 300 301
        }
        if ( status == l_Undef )
            break;
        if ( status == l_False )
        {
            RetValue = 1;
            break;
        }
        assert( status == l_True );
302 303 304 305 306 307 308 309 310 311 312 313 314
        // the problem is SAT - add more clauses
        if ( fVeryVerbose )
        {
            Vec_IntForEachEntry( vState, iReg, i )
            {
                if ( i && (i % Aig_ManRegNum(p)) == 0 )
                    printf( "\n" );
                if ( (i % Aig_ManRegNum(p)) == 0 )
                    printf( "%3d : ", i/Aig_ManRegNum(p) );
                printf( "%c", (iReg >= 0) ? ('0' + sat_solver_var_value(pSat, iReg)) : 'x' );
            }
            printf( "\n" );
        }
Alan Mishchenko committed
315
        if ( f == nFramesMax - 1 )
316 317 318 319 320 321 322 323 324 325 326 327
        {
            // derive counter-example
            assert( status == l_True );
            if ( fGetCex )
            {
                int VarNum, iBit = 0;
                Abc_Cex_t * pCex = Abc_CexAlloc( Aig_ManRegNum(p)-1, Saig_ManPiNum(p), 1 );
                pCex->iFrame = 0;
                pCex->iPo = 0;
                Vec_IntForEachEntryStart( vTopVarIds, VarNum, i, 1 )
                {
                    if ( VarNum >= 0 && sat_solver_var_value( pSat, VarNum ) )
328
                        Abc_InfoSetBit( pCex->pData, iBit );
329 330 331 332 333 334
                    iBit++;
                }
                assert( iBit == pCex->nBits );
                Abc_CexFree( p->pSeqModel );
                p->pSeqModel = pCex;
            }
Alan Mishchenko committed
335
            break;
336
        }
337
        if ( fUnique )
Alan Mishchenko committed
338
        {
339 340
            for ( i = 1; i < iLast; i++ )
            for ( k = i+1; k < iLast; k++ )
Alan Mishchenko committed
341
            {
342 343 344 345 346 347 348
                if ( !Saig_ManStatesAreEqual( pSat, vState, Aig_ManRegNum(p), i, k ) )
                    continue;
                nConstrs++;
                fAdded = 1;
                Saig_ManAddUniqueness( pSat, vState, Aig_ManRegNum(p), i, k, &nSatVarNum, &nClauses );
                if ( fVeryVerbose )
                    printf( "added constaint for %3d and %3d\n", i, k );
Alan Mishchenko committed
349 350
            }
        }
351 352 353 354 355 356 357 358 359
        if ( fAdded )
        {
//            if ( fVeryVerbose )
//                printf( "Trying a new run.\n" );
            goto nextrun;
        }
    }
    if ( fVerbose )
    {
360 361 362
        if ( status == l_Undef )
            printf( "Conflict limit (%d) was reached during iteration %d.\n", nConfMax, f+1 );
        else if ( fUnique || fUniqueAll )
363 364 365
            printf( "Completed %d interations and added %d uniqueness constraints.\n", f+1, nConstrs );
        else
            printf( "Completed %d interations.\n", f+1 );
Alan Mishchenko committed
366 367 368 369 370 371 372 373
    }
    // cleanup
    sat_solver_delete( pSat );
    Aig_ManStop( pAigPart );
    Cnf_DataFree( pCnfPart );
    Vec_IntFree( vTopVarNums );
    Vec_PtrFree( vTop );
    Vec_PtrFree( vBot );
374
    Vec_IntFree( vState );
375
    Vec_IntFreeP( &vTopVarIds );
Alan Mishchenko committed
376 377 378
    return RetValue;
}

379

Alan Mishchenko committed
380 381 382 383 384
////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


385 386
ABC_NAMESPACE_IMPL_END