llb1Reach.c 33.8 KB
Newer Older
1 2
/**CFile****************************************************************

3
  FileName    [llb1Reach.c]
4 5 6 7 8 9 10 11 12 13 14 15 16

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [BDD based reachability.]

  Synopsis    [Reachability analysis.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

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

17
  Revision    [$Id: llb1Reach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
18 19 20 21 22 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

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

#include "llbInt.h"

ABC_NAMESPACE_IMPL_START

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

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

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

  Synopsis    [Derives global BDD for the node.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
DdNode * Llb_ManConstructOutBdd( Aig_Man_t * pAig, Aig_Obj_t * pNode, DdManager * dd )
{
    DdNode * bBdd0, * bBdd1, * bFunc;
    Vec_Ptr_t * vNodes;
Alan Mishchenko committed
49
    Aig_Obj_t * pObj = NULL;
50
    int i;
51
    abctime TimeStop;
52 53
    if ( Aig_ObjFanin0(pNode) == Aig_ManConst1(pAig) )
        return Cudd_NotCond( Cudd_ReadOne(dd), Aig_ObjFaninC0(pNode) );
54
    TimeStop = dd->TimeStop;  dd->TimeStop = 0;
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
    vNodes = Aig_ManDfsNodes( pAig, &pNode, 1 );
    assert( Vec_PtrSize(vNodes) > 0 );
    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
    {
        if ( !Aig_ObjIsNode(pObj) )
            continue;
        bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
        bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
        pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 );  Cudd_Ref( (DdNode *)pObj->pData );
    }
    bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc );
    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
    {
        if ( !Aig_ObjIsNode(pObj) )
            continue;
        Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
    }
    Vec_PtrFree( vNodes );
73
    if ( Aig_ObjIsCo(pNode) )
74 75
        bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pNode) );
    Cudd_Deref( bFunc );
76
    dd->TimeStop = TimeStop;
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
    return bFunc;
}

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

  Synopsis    [Derives BDD for the group.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
DdNode * Llb_ManConstructGroupBdd( Llb_Man_t * p, Llb_Grp_t * pGroup )
{
    Aig_Obj_t * pObj;
    DdNode * bBdd0, * bBdd1, * bRes, * bXor, * bTemp;
95
    int i, k;
96 97 98 99 100 101 102
    Aig_ManConst1(p->pAig)->pData = Cudd_ReadOne( p->dd );
    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
        pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i )
    {
        bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
        bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
103 104
//        pObj->pData = Extra_bddAndTime( p->dd, bBdd0, bBdd1, p->pPars->TimeTarget );  
        pObj->pData = Cudd_bddAnd( p->dd, bBdd0, bBdd1 );  
105 106 107 108 109 110 111 112
        if ( pObj->pData == NULL )
        {
            Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i )
                if ( pObj->pData )
                    Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData );
            return NULL;
        }
        Cudd_Ref( (DdNode *)pObj->pData );
113 114 115 116
    }
    bRes = Cudd_ReadOne( p->dd );   Cudd_Ref( bRes );
    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
    {
117
        if ( Aig_ObjIsCo(pObj) )
118 119 120 121 122
            bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
        else
            bBdd0 = (DdNode *)pObj->pData;
        bBdd1 = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
        bXor  = Cudd_bddXor( p->dd, bBdd0, bBdd1 );                  Cudd_Ref( bXor );
123 124
//        bRes  = Extra_bddAndTime( p->dd, bTemp = bRes, Cudd_Not(bXor), p->pPars->TimeTarget );  
        bRes  = Cudd_bddAnd( p->dd, bTemp = bRes, Cudd_Not(bXor) );  
125 126 127 128 129 130 131 132 133 134
        if ( bRes == NULL )
        {
            Cudd_RecursiveDeref( p->dd, bTemp );
            Cudd_RecursiveDeref( p->dd, bXor );
            Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i )
                if ( pObj->pData )
                    Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData );
            return NULL;
        }        
        Cudd_Ref( bRes );
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
        Cudd_RecursiveDeref( p->dd, bTemp );
        Cudd_RecursiveDeref( p->dd, bXor );
    }
    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i )
        Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData );
    Cudd_Deref( bRes );
    return bRes;
}

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

  Synopsis    [Derives quantification cube.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
155
DdNode * Llb_ManConstructQuantCubeIntern( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace, int fBackward )
156 157 158 159
{
    Aig_Obj_t * pObj;
    DdNode * bRes, * bTemp, * bVar;
    int i, iGroupFirst, iGroupLast;
160
    abctime TimeStop;
161
    TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
162 163 164
    bRes = Cudd_ReadOne( p->dd );   Cudd_Ref( bRes );
    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
    {
165 166
        if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) )
            continue;
167 168 169 170 171 172 173 174 175 176 177
        iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj));
        iGroupLast  = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj));
        assert( iGroupFirst <= iGroupLast );
        if ( iGroupFirst < iGroupLast )
            continue;
        bVar  = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
        bRes  = Cudd_bddAnd( p->dd, bTemp = bRes, bVar );  Cudd_Ref( bRes );
        Cudd_RecursiveDeref( p->dd, bTemp );
    }
    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
    {
178 179
        if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) )
            continue;
180 181 182 183 184 185 186 187 188 189
        iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj));
        iGroupLast  = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj));
        assert( iGroupFirst <= iGroupLast );
        if ( iGroupFirst < iGroupLast )
            continue;
        bVar  = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
        bRes  = Cudd_bddAnd( p->dd, bTemp = bRes, bVar );  Cudd_Ref( bRes );
        Cudd_RecursiveDeref( p->dd, bTemp );
    }
    Cudd_Deref( bRes );
190
    p->dd->TimeStop = TimeStop;
191 192 193 194 195 196 197 198 199 200 201 202 203 204
    return bRes;
}

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

  Synopsis    [Derives quantification cube.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
205
DdNode * Llb_ManConstructQuantCubeFwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace )
206 207 208
{
    Aig_Obj_t * pObj;
    DdNode * bRes, * bTemp, * bVar;
209
    int i, iGroupLast;
210
    abctime TimeStop;
211
    TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
    bRes = Cudd_ReadOne( p->dd );   Cudd_Ref( bRes );
    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
    {
        iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj));
        assert( iGroupLast >= iGrpPlace );
        if ( iGroupLast > iGrpPlace )
            continue;
        bVar  = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
        bRes  = Cudd_bddAnd( p->dd, bTemp = bRes, bVar );  Cudd_Ref( bRes );
        Cudd_RecursiveDeref( p->dd, bTemp );
    }
    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
    {
        iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj));
        assert( iGroupLast >= iGrpPlace );
        if ( iGroupLast > iGrpPlace )
            continue;
        bVar  = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
        bRes  = Cudd_bddAnd( p->dd, bTemp = bRes, bVar );  Cudd_Ref( bRes );
        Cudd_RecursiveDeref( p->dd, bTemp );
    }
    Cudd_Deref( bRes );
234
    p->dd->TimeStop = TimeStop;
235 236 237 238 239
    return bRes;
}

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

240 241 242 243 244 245 246 247 248 249 250 251 252
  Synopsis    [Derives quantification cube.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
DdNode * Llb_ManConstructQuantCubeBwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace )
{
    Aig_Obj_t * pObj;
    DdNode * bRes, * bTemp, * bVar;
253
    int i, iGroupFirst;
254
    abctime TimeStop;
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 283 284 285 286 287
    TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
    bRes = Cudd_ReadOne( p->dd );   Cudd_Ref( bRes );
    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
    {
        if ( Saig_ObjIsPi(p->pAig, pObj) )
            continue;
        iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj));
        assert( iGroupFirst <= iGrpPlace );
        if ( iGroupFirst < iGrpPlace )
            continue;
        bVar  = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
        bRes  = Cudd_bddAnd( p->dd, bTemp = bRes, bVar );  Cudd_Ref( bRes );
        Cudd_RecursiveDeref( p->dd, bTemp );
    }
    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
    {
        if ( Saig_ObjIsPi(p->pAig, pObj) )
            continue;
        iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj));
        assert( iGroupFirst <= iGrpPlace );
        if ( iGroupFirst < iGrpPlace )
            continue;
        bVar  = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
        bRes  = Cudd_bddAnd( p->dd, bTemp = bRes, bVar );  Cudd_Ref( bRes );
        Cudd_RecursiveDeref( p->dd, bTemp );
    }
    Cudd_Deref( bRes );
    p->dd->TimeStop = TimeStop;
    return bRes;
}

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

288 289 290 291 292 293 294 295 296 297 298 299 300
  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
DdNode * Llb_ManComputeInitState( Llb_Man_t * p, DdManager * dd )
{
    Aig_Obj_t * pObj;
    DdNode * bRes, * bVar, * bTemp;
301
    int i, iVar;
302
    abctime TimeStop;
303
    TimeStop = dd->TimeStop; dd->TimeStop = 0;
304 305 306 307 308 309 310 311 312
    bRes = Cudd_ReadOne( dd );   Cudd_Ref( bRes );
    Saig_ManForEachLo( p->pAig, pObj, i )
    {
        iVar  = (dd == p->ddG) ? i : Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj));
        bVar  = Cudd_bddIthVar( dd, iVar );
        bRes  = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) );  Cudd_Ref( bRes );
        Cudd_RecursiveDeref( dd, bTemp );
    }
    Cudd_Deref( bRes );
313
    dd->TimeStop = TimeStop;
314 315 316 317 318 319 320 321 322 323 324 325 326 327
    return bRes;
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
328
DdNode * Llb_ManComputeImage( Llb_Man_t * p, DdNode * bInit, int fBackward )
329 330 331 332
{
    int fCheckSupport = 0;
    Llb_Grp_t * pGroup;
    DdNode * bImage, * bGroup, * bCube, * bTemp;
333
    int k, Index;
334
    bImage = bInit;  Cudd_Ref( bImage );
335
    for ( k = 1; k < p->pMatrix->nCols-1; k++ )
336
    {
337 338 339 340 341
        if ( fBackward )
            Index = p->pMatrix->nCols - 1 - k;
        else
            Index = k;

342
        // compute group BDD
343
        pGroup = p->pMatrix->pColGrps[Index];
344 345 346 347 348 349 350
        bGroup = Llb_ManConstructGroupBdd( p, pGroup );
        if ( bGroup == NULL )
        {
            Cudd_RecursiveDeref( p->dd, bImage );
            return NULL;
        }
        Cudd_Ref( bGroup );
351
        // quantify variables appearing only in this group
352
        bCube  = Llb_ManConstructQuantCubeIntern( p, pGroup, Index, fBackward );       Cudd_Ref( bCube );
353 354 355 356 357 358 359 360
        bGroup = Cudd_bddExistAbstract( p->dd, bTemp = bGroup, bCube );         
        if ( bGroup == NULL )
        {
            Cudd_RecursiveDeref( p->dd, bTemp );
            Cudd_RecursiveDeref( p->dd, bCube );
            return NULL;
        }
        Cudd_Ref( bGroup );
361 362 363
        Cudd_RecursiveDeref( p->dd, bTemp );
        Cudd_RecursiveDeref( p->dd, bCube );
        // perform partial product
364 365 366 367 368
        if ( fBackward )
            bCube  = Llb_ManConstructQuantCubeBwd( p, pGroup, Index );
        else
            bCube  = Llb_ManConstructQuantCubeFwd( p, pGroup, Index );
        Cudd_Ref( bCube );
369 370
//        bImage = Extra_bddAndAbstractTime( p->dd, bTemp = bImage, bGroup, bCube, p->pPars->TimeTarget );   
        bImage = Cudd_bddAndAbstract( p->dd, bTemp = bImage, bGroup, bCube );   
371
        if ( bImage == NULL )
372
        {
373 374 375
            Cudd_RecursiveDeref( p->dd, bTemp );
            Cudd_RecursiveDeref( p->dd, bGroup );
            Cudd_RecursiveDeref( p->dd, bCube );
376 377
            return NULL;
        }
378 379 380 381
        Cudd_Ref( bImage );
        Cudd_RecursiveDeref( p->dd, bTemp );
        Cudd_RecursiveDeref( p->dd, bGroup );
        Cudd_RecursiveDeref( p->dd, bCube );
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
    }

    // make sure image depends on next state vars
    if ( fCheckSupport )
    {
        bCube = Cudd_Support( p->dd, bImage );    Cudd_Ref( bCube );
        for ( bTemp = bCube; bTemp != p->dd->one; bTemp = cuddT(bTemp) )
        {
            int ObjId = Vec_IntEntry( p->vVar2Obj, bTemp->index );
            Aig_Obj_t * pObj = Aig_ManObj( p->pAig, ObjId );
            if ( !Saig_ObjIsLi(p->pAig, pObj) )
                printf( "Var %d assigned to obj %d that is not LI\n", bTemp->index, ObjId );
        }
        Cudd_RecursiveDeref( p->dd, bCube );
    }
    Cudd_Deref( bImage );
    return bImage;
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
DdNode * Llb_ManCreateConstraints( Llb_Man_t * p, Vec_Int_t * vHints, int fUseNsVars )
{
    DdNode * bConstr, * bFunc, * bTemp;
    Aig_Obj_t * pObj;
416
    int i, Entry;
417
    abctime TimeStop;
418 419
    if ( vHints == NULL )
        return Cudd_ReadOne( p->dd );
420
    TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
421
    assert( Aig_ManCiNum(p->pAig) == Aig_ManCiNum(p->pAigGlo) );
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437
    // assign const and PI nodes to the original AIG
    Aig_ManCleanData( p->pAig );
    Aig_ManConst1( p->pAig )->pData = Cudd_ReadOne( p->dd );
    Saig_ManForEachPi( p->pAig, pObj, i )
        pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var,Aig_ObjId(pObj)) );
    Saig_ManForEachLo( p->pAig, pObj, i )
    {
        if ( fUseNsVars )
            Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(Saig_ObjLoToLi(p->pAig, pObj)) );
        else
            Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(pObj) );
        pObj->pData = Cudd_bddIthVar( p->dd, Entry );
    }
    // transfer them to the global AIG
    Aig_ManCleanData( p->pAigGlo );
    Aig_ManConst1( p->pAigGlo )->pData = Cudd_ReadOne( p->dd );
438
    Aig_ManForEachCi( p->pAigGlo, pObj, i )
439
        pObj->pData = Aig_ManCi(p->pAig, i)->pData;
440 441 442 443 444 445 446 447 448 449 450 451 452 453
    // derive consraints
    bConstr = Cudd_ReadOne( p->dd );   Cudd_Ref( bConstr );
    Vec_IntForEachEntry( vHints, Entry, i )
    {
        if ( Entry != 0 && Entry != 1 )
            continue;
        bFunc = Llb_ManConstructOutBdd( p->pAigGlo, Aig_ManObj(p->pAigGlo, i), p->dd );  Cudd_Ref( bFunc );
        bFunc = Cudd_NotCond( bFunc, Entry ); // restrict to not constraint
        // make the product
        bConstr = Cudd_bddAnd( p->dd, bTemp = bConstr, bFunc );                          Cudd_Ref( bConstr );
        Cudd_RecursiveDeref( p->dd, bTemp );
        Cudd_RecursiveDeref( p->dd, bFunc );
    }
    Cudd_Deref( bConstr );
454
    p->dd->TimeStop = TimeStop;
455 456 457 458 459
    return bConstr;
}

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

460
  Synopsis    [Perform reachability with hints and returns reached states in ppGlo.]
461 462 463 464 465 466 467 468

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
469
Abc_Cex_t * Llb_ManReachDeriveCex( Llb_Man_t * p )
470
{
471 472
    Abc_Cex_t * pCex;
    Aig_Obj_t * pObj;
473
    DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing;
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
    int i, v, RetValue, nPiOffset;
    char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) );
    assert( Vec_PtrSize(p->vRings) > 0 );

    p->dd->TimeStop  = 0;
    p->ddR->TimeStop = 0;

/*
    Saig_ManForEachLo( p->pAig, pObj, i )
        printf( "%d ", pObj->Id );
    printf( "\n" );
    Saig_ManForEachLi( p->pAig, pObj, i )
        printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) );
    printf( "\n" );
*/
    // allocate room for the counter-example
    pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) );
    pCex->iFrame = Vec_PtrSize(p->vRings) - 1;
    pCex->iPo = -1;

    // get the last cube
    bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc );  Cudd_Ref( bOneCube );
    RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
    Cudd_RecursiveDeref( p->ddR, bOneCube );
    assert( RetValue );

    // write PIs of counter-example
    nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1);
    Saig_ManForEachPi( p->pAig, pObj, i )
        if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
504
            Abc_InfoSetBit( pCex->pData, nPiOffset + i );
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546

    // write state in terms of NS variables
    if ( Vec_PtrSize(p->vRings) > 1 )
    {
        bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues );   Cudd_Ref( bState );
    }
    // perform backward analysis
    Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v )
    { 
        if ( v == Vec_PtrSize(p->vRings) - 1 )
            continue;
//Extra_bddPrintSupport( p->dd, bState );  printf( "\n" );
//Extra_bddPrintSupport( p->dd, bRing );   printf( "\n" );
        // compute the next states
        bImage = Llb_ManComputeImage( p, bState, 1 ); 
        assert( bImage != NULL );
        Cudd_Ref( bImage );
        Cudd_RecursiveDeref( p->dd, bState );
//Extra_bddPrintSupport( p->dd, bImage );  printf( "\n" );

        // move reached states into ring manager
        bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) );    Cudd_Ref( bImage );
        Cudd_RecursiveDeref( p->dd, bTemp );
//Extra_bddPrintSupport( p->ddR, bImage );  printf( "\n" );

        // intersect with the previous set
        bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing );                Cudd_Ref( bOneCube );
        Cudd_RecursiveDeref( p->ddR, bImage );

        // find any assignment of the BDD
        RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
        Cudd_RecursiveDeref( p->ddR, bOneCube );
        assert( RetValue );
/*
        for ( i = 0; i < p->ddR->size; i++ )
            printf( "%d ", pValues[i] );
        printf( "\n" );
*/
        // write PIs of counter-example
        nPiOffset -= Saig_ManPiNum(p->pAig);
        Saig_ManForEachPi( p->pAig, pObj, i )
            if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
547
                Abc_InfoSetBit( pCex->pData, nPiOffset + i );
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568

        // check that we get the init state
        if ( v == 0 )
        {
            Saig_ManForEachLo( p->pAig, pObj, i )
                assert( pValues[i] == 0 );
            break;
        }

        // write state in terms of NS variables
        bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues );   Cudd_Ref( bState );
    }
    assert( nPiOffset == Saig_ManRegNum(p->pAig) );
    // update the output number
//Abc_CexPrint( pCex );
    RetValue = Saig_ManFindFailedPoCex( p->pAigGlo, pCex );
    assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pAigGlo) ); // invalid CEX!!!
    pCex->iPo = RetValue;
    // cleanup
    ABC_FREE( pValues );
    return pCex;
569 570 571 572
}

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

573 574 575 576 577 578 579 580 581 582 583 584
  Synopsis    [Perform reachability with hints and returns reached states in ppGlo.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo )
{
    int * pNs2Glo = Vec_IntArray( p->vNs2Glo );
585
    int * pCs2Glo = Vec_IntArray( p->vCs2Glo );
586 587 588
    int * pGlo2Cs = Vec_IntArray( p->vGlo2Cs );
    DdNode * bCurrent, * bReached, * bNext, * bTemp, * bCube;
    DdNode * bConstrCs, * bConstrNs;
589
    abctime clk2, clk = Abc_Clock();
590
    int nIters, nBddSize = 0;
591
//    int nThreshold = 10000;
592 593

    // compute time to stop
594
    p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0;
595 596 597 598 599 600 601

    // define variable limits
    Llb_ManPrepareVarLimits( p );

    // start the managers
    assert( p->dd == NULL );
    assert( p->ddG == NULL );
602
    assert( p->ddR == NULL );
603
    p->dd  = Cudd_Init( Vec_IntSize(p->vVar2Obj), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
604
    p->ddR = Cudd_Init( Aig_ManCiNum(p->pAig),    0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
605 606 607 608 609 610 611 612 613
    if ( pddGlo && *pddGlo )
        p->ddG = *pddGlo, *pddGlo = NULL; 
    else
        p->ddG = Cudd_Init( Aig_ManRegNum(p->pAig),   0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );

    if ( p->pPars->fReorder )
    {
        Cudd_AutodynEnable( p->dd,  CUDD_REORDER_SYMM_SIFT );
        Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT );
614
        Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT );
615 616 617 618 619
    }
    else
    {
        Cudd_AutodynDisable( p->dd );
        Cudd_AutodynDisable( p->ddG );
620
        Cudd_AutodynDisable( p->ddR );
621 622
    }

623 624 625
    // set the stop time parameter
    p->dd->TimeStop  = p->pPars->TimeTarget;
    p->ddG->TimeStop = p->pPars->TimeTarget;
626 627 628 629 630 631 632 633
    p->ddR->TimeStop = p->pPars->TimeTarget;

    // create bad state in the ring manager
    p->ddR->bFunc  = Llb_BddComputeBad( p->pAigGlo, p->ddR, p->pPars->TimeTarget );          
    if ( p->ddR->bFunc == NULL )
    {
        if ( !p->pPars->fSilent )
            printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
634
        p->pPars->iFrame = -1;
635 636 637
        return -1;
    }
    Cudd_Ref( p->ddR->bFunc );
638

639 640 641 642 643 644 645 646
    // derive constraints
    bConstrCs = Llb_ManCreateConstraints( p, vHints, 0 );   Cudd_Ref( bConstrCs );
    bConstrNs = Llb_ManCreateConstraints( p, vHints, 1 );   Cudd_Ref( bConstrNs );
//Extra_bddPrint( p->dd, bConstrCs ); printf( "\n" );
//Extra_bddPrint( p->dd, bConstrNs ); printf( "\n" );

    // perform reachability analysis
    // compute the starting set of states
647
    if ( p->ddG->bFunc )
648
    {
649
        bReached = p->ddG->bFunc; p->ddG->bFunc = NULL;
650 651 652 653 654 655 656 657 658 659 660 661 662
        bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Cs );    Cudd_Ref( bCurrent );
    }
    else
    {
        bReached = Llb_ManComputeInitState( p, p->ddG );                         Cudd_Ref( bReached );
        bCurrent = Llb_ManComputeInitState( p, p->dd  );                         Cudd_Ref( bCurrent );
    }
//Extra_bddPrintSupport( p->ddG, bReached ); printf( "\n" );
//Extra_bddPrintSupport( p->dd,  bCurrent ); printf( "\n" );

//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" );
    for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ )
    { 
663
        clk2 = Abc_Clock();
664
        // check the runtime limit
665
        if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget )
666 667 668 669 670 671 672 673 674 675 676
        {
            if ( !p->pPars->fSilent )
                printf( "Reached timeout during image computation (%d seconds).\n",  p->pPars->TimeLimit );
            p->pPars->iFrame = nIters - 1;
            Cudd_RecursiveDeref( p->dd,  bCurrent );  bCurrent = NULL;
            Cudd_RecursiveDeref( p->dd,  bConstrCs ); bConstrCs = NULL;
            Cudd_RecursiveDeref( p->dd,  bConstrNs ); bConstrNs = NULL;
            Cudd_RecursiveDeref( p->ddG, bReached );  bReached = NULL;
            return -1;
        }

677 678 679
        // save the onion ring
        bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pCs2Glo );
        if ( bTemp == NULL )
680
        {
681 682 683 684 685 686 687 688 689 690 691
            if ( !p->pPars->fSilent )
                printf( "Reached timeout (%d seconds) during ring transfer.\n",  p->pPars->TimeLimit );
            p->pPars->iFrame = nIters - 1;
            Cudd_RecursiveDeref( p->dd,  bCurrent );  bCurrent = NULL;
            Cudd_RecursiveDeref( p->dd,  bConstrCs ); bConstrCs = NULL;
            Cudd_RecursiveDeref( p->dd,  bConstrNs ); bConstrNs = NULL;
            Cudd_RecursiveDeref( p->ddG, bReached );  bReached = NULL;
            return -1;
        }
        Cudd_Ref( bTemp );
        Vec_PtrPush( p->vRings, bTemp );
692

693 694 695 696 697 698 699
        // check it for bad states
        if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) 
        {
            assert( p->pAigGlo->pSeqModel == NULL );
            if ( !p->pPars->fBackward )
                p->pAigGlo->pSeqModel = Llb_ManReachDeriveCex( p ); 
            if ( !p->pPars->fSilent )
700
            {
701
                if ( !p->pPars->fBackward )
702
                    Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d.  ", p->pAigGlo->pSeqModel->iPo, p->pAigGlo->pName, p->pAigGlo->pName, nIters );
703
                else
704
                    Abc_Print( 1, "Output ??? of miter \"%s\" was asserted in frame %d (counter-example is not produced).  ", p->pAigGlo->pName, nIters );
705
                Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
706
            }
707
            p->pPars->iFrame = nIters - 1;
708 709 710 711 712
            Cudd_RecursiveDeref( p->dd,  bCurrent );  bCurrent = NULL;
            Cudd_RecursiveDeref( p->dd,  bConstrCs ); bConstrCs = NULL;
            Cudd_RecursiveDeref( p->dd,  bConstrNs ); bConstrNs = NULL;
            Cudd_RecursiveDeref( p->ddG, bReached );  bReached = NULL;
            return 0; 
713 714 715 716 717
        }

        // restrict reachable states using constraints
        if ( vHints )
        {
718
            bCurrent = Cudd_bddAnd( p->dd, bTemp = bCurrent, bConstrCs );                                Cudd_Ref( bCurrent );
719 720 721 722
            Cudd_RecursiveDeref( p->dd, bTemp );
        }

        // quantify variables appearing only in the init state
723 724
        bCube    = Llb_ManConstructQuantCubeIntern( p, (Llb_Grp_t *)Vec_PtrEntry(p->vGroups,0), 0, 0 );  Cudd_Ref( bCube );
        bCurrent = Cudd_bddExistAbstract( p->dd, bTemp = bCurrent, bCube );                              Cudd_Ref( bCurrent );
725 726 727 728
        Cudd_RecursiveDeref( p->dd, bTemp );
        Cudd_RecursiveDeref( p->dd, bCube );

        // compute the next states
729
        bNext = Llb_ManComputeImage( p, bCurrent, 0 );
730 731 732
        if ( bNext == NULL )
        {
            if ( !p->pPars->fSilent )
733
                printf( "Reached timeout (%d seconds) during image computation.\n",  p->pPars->TimeLimit );
734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752
            p->pPars->iFrame = nIters - 1;
            Cudd_RecursiveDeref( p->dd,  bCurrent );   bCurrent = NULL;
            Cudd_RecursiveDeref( p->dd,  bConstrCs );  bConstrCs = NULL;
            Cudd_RecursiveDeref( p->dd,  bConstrNs );  bConstrNs = NULL;
            Cudd_RecursiveDeref( p->ddG, bReached );   bReached = NULL;
            return -1;
        }
        Cudd_Ref( bNext );
        Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;

        // restrict reachable states using constraints
        if ( vHints )
        {
            bNext = Cudd_bddAnd( p->dd, bTemp = bNext, bConstrNs );                Cudd_Ref( bNext );
            Cudd_RecursiveDeref( p->dd, bTemp );
        }
//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" );

        // remap these states into the current state vars
753 754
//        bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo );    Cudd_Ref( bNext );
//        Cudd_RecursiveDeref( p->dd, bTemp );
755 756
//        bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pNs2Glo, p->pPars->TimeTarget );    
        bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo );    
757 758 759 760 761 762 763 764 765 766 767 768 769 770
        if ( bNext == NULL )
        {
            if ( !p->pPars->fSilent )
                printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n",  p->pPars->TimeLimit );
            p->pPars->iFrame = nIters - 1;
            Cudd_RecursiveDeref( p->dd,  bTemp );  
            Cudd_RecursiveDeref( p->dd,  bConstrCs );  bConstrCs = NULL;
            Cudd_RecursiveDeref( p->dd,  bConstrNs );  bConstrNs = NULL;
            Cudd_RecursiveDeref( p->ddG, bReached );   bReached = NULL;
            return -1;
        }
        Cudd_Ref( bNext );
        Cudd_RecursiveDeref( p->dd, bTemp );  

771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787

        // check if there are any new states
        if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states
        {
            Cudd_RecursiveDeref( p->ddG,  bNext );     bNext = NULL;
            break;
        }

        // check the BDD size
        nBddSize = Cudd_DagSize(bNext);
        if ( nBddSize > p->pPars->nBddMax )
        {
            Cudd_RecursiveDeref( p->ddG,  bNext );     bNext = NULL;
            break;
        }

        // get the new states
788 789 790 791 792 793 794 795
        bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) );
        if ( bCurrent == NULL )
        {
            Cudd_RecursiveDeref( p->ddG,  bNext );        bNext = NULL;
            Cudd_RecursiveDeref( p->ddG,  bReached );     bReached = NULL;
            break;
        }
        Cudd_Ref( bCurrent );
796 797 798 799 800
        // minimize the new states with the reached states
//        bCurrent = Cudd_bddConstrain( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent );
//        bCurrent = Cudd_bddRestrict( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) );  Cudd_Ref( bCurrent );
//        Cudd_RecursiveDeref( p->ddG, bTemp );
//printf( "Initial BDD =%7d. Constrained BDD =%7d.\n", Cudd_DagSize(bTemp), Cudd_DagSize(bCurrent) );
801

802
        // remap these states into the current state vars
803 804
//        bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs );   Cudd_Ref( bCurrent );
//        Cudd_RecursiveDeref( p->ddG, bTemp );
805 806
//        bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs, p->pPars->TimeTarget );    
        bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs );    
807 808 809 810 811 812 813 814 815 816 817 818 819 820
        if ( bCurrent == NULL )
        {
            if ( !p->pPars->fSilent )
                printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n",  p->pPars->TimeLimit );
            p->pPars->iFrame = nIters - 1;
            Cudd_RecursiveDeref( p->ddG, bTemp );  
            Cudd_RecursiveDeref( p->dd,  bConstrCs );  bConstrCs = NULL;
            Cudd_RecursiveDeref( p->dd,  bConstrNs );  bConstrNs = NULL;
            Cudd_RecursiveDeref( p->ddG, bReached );   bReached = NULL;
            return -1;
        }
        Cudd_Ref( bCurrent );
        Cudd_RecursiveDeref( p->ddG, bTemp ); 
        
821 822

        // add to the reached states
823 824 825 826 827 828 829 830
        bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext );                       
        if ( bReached == NULL )
        {
            Cudd_RecursiveDeref( p->ddG,  bTemp );     bTemp = NULL;
            Cudd_RecursiveDeref( p->ddG,  bNext );     bNext = NULL;
            break;
        }
        Cudd_Ref( bReached );
831 832 833 834 835 836
        Cudd_RecursiveDeref( p->ddG, bTemp );
        Cudd_RecursiveDeref( p->ddG, bNext );
        bNext = NULL;

        if ( p->pPars->fVerbose )
        {
837 838 839 840 841
            fprintf( stdout, "F =%5d : ",    nIters );
            fprintf( stdout, "Im =%6d  ",    nBddSize );
            fprintf( stdout, "(%4d %3d)   ", Cudd_ReadReorderings(p->dd),  Cudd_ReadGarbageCollections(p->dd) );
            fprintf( stdout, "Rea =%6d  ",   Cudd_DagSize(bReached) );
            fprintf( stdout, "(%4d%4d)   ",  Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) );
842
            Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 );
843
        }
844 845
/*
        if ( p->pPars->fVerbose )
846
        {
847 848 849 850
            double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) );
//            Extra_bddPrint( p->ddG, bReached );printf( "\n" );
            fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
            fflush( stdout ); 
851
        }
852
*/
853 854 855 856
    }
    Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL;
    Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL;
    if ( bReached == NULL )
857 858
    {
        p->pPars->iFrame = nIters - 1;
859
        return 0; // reachable
860
    }
861
//    assert( bCurrent == NULL );
862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878
    if ( bCurrent )
        Cudd_RecursiveDeref( p->dd, bCurrent );
    // report the stats
    if ( p->pPars->fVerbose )
    {
        double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) );
        if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax )
            fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters );
        else
            fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters );
        fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
        fflush( stdout ); 
    }
    if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax )
    {
        if ( !p->pPars->fSilent )
            printf( "Verified only for states reachable in %d frames.  ", nIters );
879
        p->pPars->iFrame = p->pPars->nIterMax;
880 881 882 883 884
        Cudd_RecursiveDeref( p->ddG, bReached );
        return -1; // undecided
    }
    if ( pddGlo ) 
    {
885 886
        assert( p->ddG->bFunc == NULL );
        p->ddG->bFunc = bReached; bReached = NULL;
887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904
        assert( *pddGlo == NULL );
        *pddGlo = p->ddG;  p->ddG = NULL;
    }
    else
        Cudd_RecursiveDeref( p->ddG, bReached );
    if ( !p->pPars->fSilent )
        printf( "The miter is proved unreachable after %d iterations.  ", nIters );
    p->pPars->iFrame = nIters - 1;
    return 1; // unreachable
}

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


ABC_NAMESPACE_IMPL_END