saigInd.c 13.2 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 22 23 24
/**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"
#include "cnf.h"
#include "satSolver.h"

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 154 155
    int i, k, f, clk, Lits[2], status, RetValue, nSatVarNum, nConfPrev;
    int nOldSize, iReg, iLast, fAdded, nConstrs = 0, nClauses = 0;
    assert( fUnique == 0 || fUniqueAll == 0 );
Alan Mishchenko committed
156 157 158 159 160 161
    assert( Saig_ManPoNum(p) == 1 );
    Aig_ManSetPioNumbers( p );

    // start the top by including the PO
    vBot = Vec_PtrAlloc( 100 );
    vTop = Vec_PtrAlloc( 100 );
162
    vState = Vec_IntAlloc( 1000 );
Alan Mishchenko committed
163 164 165 166 167 168 169 170 171 172 173
    Vec_PtrPush( vTop, Aig_ManPo(p, 0) );
    // 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 )
174
        printf( "Induction parameters: FramesMax = %5d. ConflictMax = %6d.\n", nFramesMax, nConfMax );
Alan Mishchenko committed
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
    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
        pCnfPart = Cnf_Derive( pAigPart, Aig_ManPoNum(pAigPart) );
        Cnf_DataLift( pCnfPart, nSatVarNum );
        nSatVarNum += pCnfPart->nVars;
191
        nClauses   += pCnfPart->nClauses;
Alan Mishchenko committed
192

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

Alan Mishchenko committed
211 212 213 214 215 216 217 218 219 220 221 222 223
        // stitch variables of top and bot
        assert( Aig_ManPoNum(pAigPart)-1 == Vec_IntSize(vTopVarNums) );
        Aig_ManForEachPo( pAigPart, pObjPo, i )
        {
            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 );
224
                nClauses++;
Alan Mishchenko committed
225 226 227 228 229 230 231 232 233 234
                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 );
235
            nClauses += 2;
Alan Mishchenko committed
236 237 238 239 240 241 242 243 244 245 246
        }
        // 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;
        }
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282

        // create new set of POs to derive new top
        Vec_PtrClear( vTop );
        Vec_PtrPush( vTop, Aig_ManPo(p, 0) );
        Vec_IntClear( vTopVarNums );
        nOldSize = Vec_IntSize(vState);
        Vec_IntFillExtra( vState, nOldSize + Aig_ManRegNum(p), -1 );
        Vec_PtrForEachEntry( Aig_Obj_t *, vBot, pObjPi, i )
        {
            assert( Aig_ObjIsPi(pObjPi) );
            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] );

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

378

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


384 385
ABC_NAMESPACE_IMPL_END