fraImp.c 23 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 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
/**CFile****************************************************************

  FileName    [fraImp.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [New FRAIG package.]

  Synopsis    [Detecting and proving implications.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - June 30, 2007.]

  Revision    [$Id: fraImp.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]

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

#include "fra.h"

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

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

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

  Synopsis    [Counts the number of 1s in each siminfo of each node.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
static inline int Fra_SmlCountOnesOne( Fra_Sml_t * p, int Node )
{
    unsigned * pSim;
    int k, Counter = 0;
    pSim = Fra_ObjSim( p, Node );
    for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
        Counter += Aig_WordCountOnes( pSim[k] );
    return Counter;
}

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

  Synopsis    [Counts the number of 1s in each siminfo of each node.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
63
static inline int * Fra_SmlCountOnes( Fra_Sml_t * p )
Alan Mishchenko committed
64 65
{
    Aig_Obj_t * pObj;
Alan Mishchenko committed
66
    int i, * pnBits; 
Alan Mishchenko committed
67 68
    pnBits = ALLOC( int, Aig_ManObjNumMax(p->pAig) );  
    memset( pnBits, 0, sizeof(int) * Aig_ManObjNumMax(p->pAig) );
Alan Mishchenko committed
69
    Aig_ManForEachObj( p->pAig, pObj, i )
Alan Mishchenko committed
70
        pnBits[i] = Fra_SmlCountOnesOne( p, i );
Alan Mishchenko committed
71 72 73 74 75
    return pnBits;
}

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

Alan Mishchenko committed
76
  Synopsis    [Returns 1 if implications holds.]
Alan Mishchenko committed
77 78 79 80 81 82 83 84

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
85
static inline int Sml_NodeCheckImp( Fra_Sml_t * p, int Left, int Right )
Alan Mishchenko committed
86 87
{
    unsigned * pSimL, * pSimR;
Alan Mishchenko committed
88
    int k;
Alan Mishchenko committed
89 90
    pSimL = Fra_ObjSim( p, Left );
    pSimR = Fra_ObjSim( p, Right );
Alan Mishchenko committed
91 92 93 94
    for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
        if ( pSimL[k] & ~pSimR[k] )
            return 0;
    return 1;
Alan Mishchenko committed
95 96 97 98
}

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

Alan Mishchenko committed
99
  Synopsis    [Counts the number of 1s in the complement of the implication.]
Alan Mishchenko committed
100 101 102 103 104 105 106 107

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
108
static inline int Sml_NodeNotImpWeight( Fra_Sml_t * p, int Left, int Right )
Alan Mishchenko committed
109 110
{
    unsigned * pSimL, * pSimR;
Alan Mishchenko committed
111
    int k, Counter = 0;
Alan Mishchenko committed
112 113
    pSimL = Fra_ObjSim( p, Left );
    pSimR = Fra_ObjSim( p, Right );
Alan Mishchenko committed
114 115 116
    for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
        Counter += Aig_WordCountOnes( pSimL[k] & ~pSimR[k] );
    return Counter;
Alan Mishchenko committed
117 118 119 120
}

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

Alan Mishchenko committed
121
  Synopsis    [Computes the complement of the implication.]
Alan Mishchenko committed
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline void Sml_NodeSaveNotImpPatterns( Fra_Sml_t * p, int Left, int Right, unsigned * pResult )
{
    unsigned * pSimL, * pSimR;
    int k;
    pSimL = Fra_ObjSim( p, Left );
    pSimR = Fra_ObjSim( p, Right );
    for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
        pResult[k] |= pSimL[k] & ~pSimR[k];
}

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

Alan Mishchenko committed
142 143 144 145 146 147 148 149 150
  Synopsis    [Returns the array of nodes sorted by the number of 1s.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
151
Vec_Ptr_t * Fra_SmlSortUsingOnes( Fra_Sml_t * p, int fLatchCorr )
Alan Mishchenko committed
152 153 154 155
{
    Aig_Obj_t * pObj;
    Vec_Ptr_t * vNodes;
    int i, nNodes, nTotal, nBits, * pnNodes, * pnBits, * pMemory;
Alan Mishchenko committed
156
    assert( p->nWordsTotal > 0 );
Alan Mishchenko committed
157
    // count 1s in each node's siminfo
Alan Mishchenko committed
158
    pnBits = Fra_SmlCountOnes( p );
Alan Mishchenko committed
159 160
    // count number of nodes having that many 1s
    nNodes = 0;
Alan Mishchenko committed
161 162 163
    nBits = p->nWordsTotal * 32;
    pnNodes = ALLOC( int, nBits + 1 );
    memset( pnNodes, 0, sizeof(int) * (nBits + 1) );
Alan Mishchenko committed
164 165 166
    Aig_ManForEachObj( p->pAig, pObj, i )
    {
        if ( i == 0 ) continue;
Alan Mishchenko committed
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
        // skip non-PI and non-internal nodes
        if ( fLatchCorr )
        {
            if ( !Aig_ObjIsPi(pObj) )
                continue;
        }
        else
        {
            if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) )
                continue;
        }
        // skip nodes participating in the classes
//        if ( Fra_ClassObjRepr(pObj) )
//            continue;
        assert( pnBits[i] <= nBits ); // "<" because of normalized info
Alan Mishchenko committed
182 183 184 185
        pnNodes[pnBits[i]]++;
        nNodes++;
    }
    // allocate memory for all the nodes
Alan Mishchenko committed
186
    pMemory = ALLOC( int, nNodes + nBits + 1 );  
Alan Mishchenko committed
187
    // markup the memory for each node
Alan Mishchenko committed
188
    vNodes = Vec_PtrAlloc( nBits + 1 );
Alan Mishchenko committed
189
    Vec_PtrPush( vNodes, pMemory );
Alan Mishchenko committed
190
    for ( i = 1; i <= nBits; i++ )
Alan Mishchenko committed
191
    {
Alan Mishchenko committed
192
        pMemory += pnNodes[i-1] + 1;
Alan Mishchenko committed
193 194 195
        Vec_PtrPush( vNodes, pMemory );
    }
    // add the nodes
Alan Mishchenko committed
196
    memset( pnNodes, 0, sizeof(int) * (nBits + 1) );
Alan Mishchenko committed
197 198 199
    Aig_ManForEachObj( p->pAig, pObj, i )
    {
        if ( i == 0 ) continue;
Alan Mishchenko committed
200 201 202 203 204 205 206 207 208 209 210 211 212 213
        // skip non-PI and non-internal nodes
        if ( fLatchCorr )
        {
            if ( !Aig_ObjIsPi(pObj) )
                continue;
        }
        else
        {
            if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) )
                continue;
        }
        // skip nodes participating in the classes
//        if ( Fra_ClassObjRepr(pObj) )
//            continue;
Alan Mishchenko committed
214 215 216 217 218 219 220 221 222 223
        pMemory = Vec_PtrEntry( vNodes, pnBits[i] );
        pMemory[ pnNodes[pnBits[i]]++ ] = i;
    }
    // add 0s in the end
    nTotal = 0;
    Vec_PtrForEachEntry( vNodes, pMemory, i )
    {
        pMemory[ pnNodes[i]++ ] = 0;
        nTotal += pnNodes[i];
    }
Alan Mishchenko committed
224 225 226
    assert( nTotal == nNodes + nBits + 1 );
    free( pnNodes );
    free( pnBits );
Alan Mishchenko committed
227 228 229 230 231
    return vNodes;
}

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

Alan Mishchenko committed
232
  Synopsis    [Returns the array of implications with the highest cost.]
Alan Mishchenko committed
233 234 235 236 237 238 239 240

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
241
Vec_Int_t * Fra_SmlSelectMaxCost( Vec_Int_t * vImps, int * pCosts, int nCostMax, int nImpLimit, int * pCostRange )
Alan Mishchenko committed
242
{
Alan Mishchenko committed
243 244 245 246 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
    Vec_Int_t * vImpsNew;
    int * pCostCount, nImpCount, Imp, i, c;
    assert( Vec_IntSize(vImps) >= nImpLimit );
    // count how many implications have each cost
    pCostCount = ALLOC( int, nCostMax + 1 );
    memset( pCostCount, 0, sizeof(int) * (nCostMax + 1) );
    for ( i = 0; i < Vec_IntSize(vImps); i++ )
    {
        assert( pCosts[i] <= nCostMax );
        pCostCount[ pCosts[i] ]++;
    }
    assert( pCostCount[0] == 0 );
    // select the bound on the cost (above this bound, implication will be included)
    nImpCount = 0;
    for ( c = nCostMax; c > 0; c-- )
    {
        nImpCount += pCostCount[c];
        if ( nImpCount >= nImpLimit )
            break;
    }
//    printf( "Cost range >= %d.\n", c );
    // collect implications with the given costs
    vImpsNew = Vec_IntAlloc( nImpLimit );
    Vec_IntForEachEntry( vImps, Imp, i )
    {
        if ( pCosts[i] < c )
            continue;
        Vec_IntPush( vImpsNew, Imp );
        if ( Vec_IntSize( vImpsNew ) == nImpLimit )
            break;
    }
    free( pCostCount );
Alan Mishchenko committed
275 276
    if ( pCostRange )
        *pCostRange = c;
Alan Mishchenko committed
277
    return vImpsNew;
Alan Mishchenko committed
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
}

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

  Synopsis    [Compares two implications using their largest ID.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Sml_CompareMaxId( unsigned short * pImp1, unsigned short * pImp2 )
{
    int Max1 = AIG_MAX( pImp1[0], pImp1[1] );
    int Max2 = AIG_MAX( pImp2[0], pImp2[1] );
    if ( Max1 < Max2 )
        return -1;
    if ( Max1 > Max2  )
        return 1;
    return 0; 
}

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

  Synopsis    [Derives implication candidates.]

  Description [Implication candidates have the property that 
  (1) they hold using sequential simulation information
  (2) they do not hold using combinational simulation information
  (3) they have as high expressive power as possible (heuristically)
Alan Mishchenko committed
310 311
      that is, they are easy to disprove combinationally
      meaning they cover relatively larger sequential subspace.]
Alan Mishchenko committed
312
               
Alan Mishchenko committed
313
  SideEffects []
Alan Mishchenko committed
314 315 316 317

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
318
Vec_Int_t * Fra_ImpDerive( Fra_Man_t * p, int nImpMaxLimit, int nImpUseLimit, int fLatchCorr )
Alan Mishchenko committed
319
{
Alan Mishchenko committed
320 321
    int nSimWords = 64;
    Fra_Sml_t * pSeq, * pComb;
Alan Mishchenko committed
322 323
    Vec_Int_t * vImps, * vTemp;
    Vec_Ptr_t * vNodes;
Alan Mishchenko committed
324 325 326
    int * pImpCosts, * pNodesI, * pNodesK;
    int nImpsTotal = 0, nImpsTried = 0, nImpsNonSeq = 0, nImpsComb = 0, nImpsCollected = 0;
    int CostMin = AIG_INFINITY, CostMax = 0;
Alan Mishchenko committed
327
    int i, k, Imp, CostRange, clk = clock();
Alan Mishchenko committed
328
    assert( Aig_ManObjNumMax(p->pManAig) < (1 << 15) );
Alan Mishchenko committed
329 330
    assert( nImpMaxLimit > 0 && nImpUseLimit > 0 && nImpUseLimit <= nImpMaxLimit );
    // normalize both managers
Alan Mishchenko committed
331
    pComb = Fra_SmlSimulateComb( p->pManAig, nSimWords );
Alan Mishchenko committed
332
    pSeq = Fra_SmlSimulateSeq( p->pManAig, p->pPars->nFramesP, nSimWords, 1 );
Alan Mishchenko committed
333
    // get the nodes sorted by the number of 1s
Alan Mishchenko committed
334 335 336 337 338 339 340 341
    vNodes = Fra_SmlSortUsingOnes( pSeq, fLatchCorr );
    // count the total number of implications
    for ( k = nSimWords * 32; k > 0; k-- )
    for ( i = k - 1; i > 0; i-- )
    for ( pNodesI = Vec_PtrEntry( vNodes, i ); *pNodesI; pNodesI++ )
    for ( pNodesK = Vec_PtrEntry( vNodes, k ); *pNodesK; pNodesK++ )
        nImpsTotal++;

Alan Mishchenko committed
342
    // compute implications and their costs
Alan Mishchenko committed
343
    pImpCosts = ALLOC( int, nImpMaxLimit );
Alan Mishchenko committed
344
    vImps = Vec_IntAlloc( nImpMaxLimit );
Alan Mishchenko committed
345 346
    for ( k = pSeq->nWordsTotal * 32; k > 0; k-- )
        for ( i = k - 1; i > 0; i-- )
Alan Mishchenko committed
347
        {
Alan Mishchenko committed
348 349
            // HERE WE ARE MISSING SOME POTENTIAL IMPLICATIONS (with complement!)

Alan Mishchenko committed
350 351 352
            for ( pNodesI = Vec_PtrEntry( vNodes, i ); *pNodesI; pNodesI++ )
            for ( pNodesK = Vec_PtrEntry( vNodes, k ); *pNodesK; pNodesK++ )
            {
Alan Mishchenko committed
353 354
                nImpsTried++;
                if ( !Sml_NodeCheckImp(pSeq, *pNodesI, *pNodesK) )
Alan Mishchenko committed
355
                {
Alan Mishchenko committed
356 357
                    nImpsNonSeq++;
                    continue;
Alan Mishchenko committed
358
                }
Alan Mishchenko committed
359 360 361 362 363 364
                if ( Sml_NodeCheckImp(pComb, *pNodesI, *pNodesK) )
                {
                    nImpsComb++;
                    continue;
                }
                nImpsCollected++;
Alan Mishchenko committed
365
                Imp = Fra_ImpCreate( *pNodesI, *pNodesK );
Alan Mishchenko committed
366 367 368 369
                pImpCosts[ Vec_IntSize(vImps) ] = Sml_NodeNotImpWeight(pComb, *pNodesI, *pNodesK);
                CostMin = AIG_MIN( CostMin, pImpCosts[ Vec_IntSize(vImps) ] );
                CostMax = AIG_MAX( CostMax, pImpCosts[ Vec_IntSize(vImps) ] );
                Vec_IntPush( vImps, Imp );
Alan Mishchenko committed
370 371
                if ( Vec_IntSize(vImps) == nImpMaxLimit )
                    goto finish;
Alan Mishchenko committed
372
            } 
Alan Mishchenko committed
373 374
        }
finish:
Alan Mishchenko committed
375 376 377 378
    Fra_SmlStop( pComb );
    Fra_SmlStop( pSeq );

    // select implications with the highest cost
Alan Mishchenko committed
379
    CostRange = CostMin;
Alan Mishchenko committed
380 381
    if ( Vec_IntSize(vImps) > nImpUseLimit )
    {
Alan Mishchenko committed
382
        vImps = Fra_SmlSelectMaxCost( vTemp = vImps, pImpCosts, nSimWords * 32, nImpUseLimit, &CostRange );
Alan Mishchenko committed
383 384
        Vec_IntFree( vTemp );  
    }
Alan Mishchenko committed
385 386

    // dealloc
Alan Mishchenko committed
387
    free( pImpCosts ); 
Alan Mishchenko committed
388 389
    free( Vec_PtrEntry(vNodes, 0) );
    Vec_PtrFree( vNodes );
Alan Mishchenko committed
390
    // reorder implications topologically
Alan Mishchenko committed
391 392
    qsort( (void *)Vec_IntArray(vImps), Vec_IntSize(vImps), sizeof(int), 
            (int (*)(const void *, const void *)) Sml_CompareMaxId );
Alan Mishchenko committed
393 394
if ( p->pPars->fVerbose )
{
Alan Mishchenko committed
395 396 397 398
printf( "Implications: All = %d. Try = %d. NonSeq = %d. Comb = %d. Res = %d.\n", 
    nImpsTotal, nImpsTried, nImpsNonSeq, nImpsComb, nImpsCollected );
printf( "Implication weight: Min = %d. Pivot = %d. Max = %d.   ", 
       CostMin, CostRange, CostMax );
Alan Mishchenko committed
399 400
PRT( "Time", clock() - clk );
}
Alan Mishchenko committed
401 402 403
    return vImps;
}

Alan Mishchenko committed
404

Alan Mishchenko committed
405 406 407 408 409 410 411
// the following three procedures are called to 
// - add implications to the SAT solver
// - check implications using the SAT solver
// - refine implications using after a cex is generated

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

Alan Mishchenko committed
412
  Synopsis    [Add implication clauses to the SAT solver.]
Alan Mishchenko committed
413

Alan Mishchenko committed
414
  Description [Note that implications should be checked in the first frame!]
Alan Mishchenko committed
415 416 417 418 419 420
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
421
void Fra_ImpAddToSolver( Fra_Man_t * p, Vec_Int_t * vImps, int * pSatVarNums )
Alan Mishchenko committed
422 423 424 425 426
{
    sat_solver * pSat = p->pSat;
    Aig_Obj_t * pLeft, * pRight;
    Aig_Obj_t * pLeftF, * pRightF;
    int pLits[2], Imp, Left, Right, i, f, status;
Alan Mishchenko committed
427
    int fComplL, fComplR;
Alan Mishchenko committed
428 429 430
    Vec_IntForEachEntry( vImps, Imp, i )
    {
        // get the corresponding nodes
Alan Mishchenko committed
431 432
        pLeft = Aig_ManObj( p->pManAig, Fra_ImpLeft(Imp) );
        pRight = Aig_ManObj( p->pManAig, Fra_ImpRight(Imp) );
Alan Mishchenko committed
433 434 435 436 437 438 439 440 441 442 443 444 445 446
        // check if all the nodes are present
        for ( f = 0; f < p->pPars->nFramesK; f++ )
        {
            // map these info fraig
            pLeftF = Fra_ObjFraig( pLeft, f );
            pRightF = Fra_ObjFraig( pRight, f );
            if ( Aig_ObjIsNone(Aig_Regular(pLeftF)) || Aig_ObjIsNone(Aig_Regular(pRightF)) )
            {
                Vec_IntWriteEntry( vImps, i, 0 );
                break;
            }
        }
        if ( f < p->pPars->nFramesK )
            continue;
Alan Mishchenko committed
447 448 449 450 451 452 453
        // add constraints in each timeframe
        for ( f = 0; f < p->pPars->nFramesK; f++ )
        {
            // map these info fraig
            pLeftF = Fra_ObjFraig( pLeft, f );
            pRightF = Fra_ObjFraig( pRight, f );
            // get the corresponding SAT numbers
Alan Mishchenko committed
454 455
            Left = pSatVarNums[ Aig_Regular(pLeftF)->Id ];
            Right = pSatVarNums[ Aig_Regular(pRightF)->Id ];
Alan Mishchenko committed
456 457
            assert( Left > 0  && Left < p->nSatVars );
            assert( Right > 0 && Right < p->nSatVars );
Alan Mishchenko committed
458 459 460
            // get the complemented attributes
            fComplL = pLeft->fPhase ^ Aig_IsComplement(pLeftF);
            fComplR = pRight->fPhase ^ Aig_IsComplement(pRightF);
Alan Mishchenko committed
461
            // get the constraint
Alan Mishchenko committed
462 463 464
            // L => R      L' v R     (complement = L & R')
            pLits[0] = 2 * Left  + !fComplL;
            pLits[1] = 2 * Right +  fComplR;
Alan Mishchenko committed
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
            // add contraint to solver
            if ( !sat_solver_addclause( pSat, pLits, pLits + 2 ) )
            {
                sat_solver_delete( pSat );
                p->pSat = NULL;
                return;
            }
        }
    }
    status = sat_solver_simplify(pSat);
    if ( status == 0 )
    {
        sat_solver_delete( pSat );
        p->pSat = NULL;
    }
Alan Mishchenko committed
480 481 482
//    printf( "Total imps = %d. ", Vec_IntSize(vImps) );
    Fra_ImpCompactArray( vImps );
//    printf( "Valid imps = %d. \n", Vec_IntSize(vImps) );
Alan Mishchenko committed
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
}

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

  Synopsis    [Check implications for the node (if they are present).]

  Description [Returns the new position in the array.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Fra_ImpCheckForNode( Fra_Man_t * p, Vec_Int_t * vImps, Aig_Obj_t * pNode, int Pos )
{
    Aig_Obj_t * pLeft, * pRight;
Alan Mishchenko committed
499
    Aig_Obj_t * pLeftF, * pRightF;
Alan Mishchenko committed
500
    int i, Imp, Left, Right, Max, RetValue;
Alan Mishchenko committed
501
    int fComplL, fComplR;
Alan Mishchenko committed
502 503
    Vec_IntForEachEntryStart( vImps, Imp, i, Pos )
    {
Alan Mishchenko committed
504 505
        if ( Imp == 0 )
            continue;
Alan Mishchenko committed
506 507
        Left = Fra_ImpLeft(Imp);
        Right = Fra_ImpRight(Imp);
Alan Mishchenko committed
508 509 510 511 512
        Max = AIG_MAX( Left, Right );
        assert( Max >= pNode->Id );
        if ( Max > pNode->Id )
            return i;
        // get the corresponding nodes
Alan Mishchenko committed
513
        pLeft  = Aig_ManObj( p->pManAig, Left );
Alan Mishchenko committed
514
        pRight = Aig_ManObj( p->pManAig, Right );
Alan Mishchenko committed
515 516 517 518 519 520 521 522 523
        // get the corresponding FRAIG nodes
        pLeftF  = Fra_ObjFraig( pLeft, p->pPars->nFramesK );
        pRightF = Fra_ObjFraig( pRight, p->pPars->nFramesK );
        // get the complemented attributes
        fComplL = pLeft->fPhase ^ Aig_IsComplement(pLeftF);
        fComplR = pRight->fPhase ^ Aig_IsComplement(pRightF);
        // check equality
        if ( Aig_Regular(pLeftF) == Aig_Regular(pRightF) )
        {
Alan Mishchenko committed
524 525 526 527 528 529 530 531 532 533 534 535 536
            if ( fComplL == fComplR ) // x => x  - always true
                continue;
            assert( fComplL != fComplR );
            // consider 4 possibilities:
            // NOT(1) => 1    or   0 => 1  - always true
            // 1 => NOT(1)    or   1 => 0  - never true
            // NOT(x) => x    or   x       - not always true
            // x => NOT(x)    or   NOT(x)  - not always true
            if ( Aig_ObjIsConst1(Aig_Regular(pLeftF)) && fComplL ) // proved implication
                continue;
            // disproved implication
            p->pCla->fRefinement = 1;
            Vec_IntWriteEntry( vImps, i, 0 );
Alan Mishchenko committed
537 538
            continue;
        }
Alan Mishchenko committed
539 540 541 542
        // check the implication 
        // - if true, a clause is added
        // - if false, a cex is simulated
        // make sure the implication is refined
Alan Mishchenko committed
543 544
        RetValue = Fra_NodesAreImp( p, Aig_Regular(pLeftF), Aig_Regular(pRightF), fComplL, fComplR );
        if ( RetValue != 1 )
Alan Mishchenko committed
545
        {
Alan Mishchenko committed
546
            p->pCla->fRefinement = 1;
Alan Mishchenko committed
547 548
            if ( RetValue == 0 )
                Fra_SmlResimulate( p );
Alan Mishchenko committed
549 550 551 552
            if ( Vec_IntEntry(vImps, i) != 0 )
                printf( "Fra_ImpCheckForNode(): Implication is not refined!\n" );
            assert( Vec_IntEntry(vImps, i) == 0 );
        }
Alan Mishchenko committed
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576
    }
    return i;
}

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

  Synopsis    [Removes those implications that no longer hold.]

  Description [Returns 1 if refinement has happened.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Fra_ImpRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vImps )
{
    Aig_Obj_t * pLeft, * pRight;
    int Imp, i, RetValue = 0;
    Vec_IntForEachEntry( vImps, Imp, i )
    {
        if ( Imp == 0 )
            continue;
        // get the corresponding nodes
Alan Mishchenko committed
577 578
        pLeft = Aig_ManObj( p->pManAig, Fra_ImpLeft(Imp) );
        pRight = Aig_ManObj( p->pManAig, Fra_ImpRight(Imp) );
Alan Mishchenko committed
579
        // check if implication holds using this simulation info
Alan Mishchenko committed
580
        if ( !Sml_NodeCheckImp(p->pSml, pLeft->Id, pRight->Id) )
Alan Mishchenko committed
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
        {
            Vec_IntWriteEntry( vImps, i, 0 );
            RetValue = 1;
        }
    }
    return RetValue;
}

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

  Synopsis    [Removes empty implications.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Fra_ImpCompactArray( Vec_Int_t * vImps )
{
    int i, k, Imp;
    k = 0;
    Vec_IntForEachEntry( vImps, Imp, i )
        if ( Imp )
            Vec_IntWriteEntry( vImps, k++, Imp );
    Vec_IntShrink( vImps, k );
}

Alan Mishchenko committed
610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
/**Function*************************************************************

  Synopsis    [Determines the ratio of the state space by computed implications.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
double Fra_ImpComputeStateSpaceRatio( Fra_Man_t * p )
{
    int nSimWords = 64;
    Fra_Sml_t * pComb;
    unsigned * pResult;
    double Ratio = 0.0;
    int Left, Right, Imp, i;
    if ( p->pCla->vImps == NULL || Vec_IntSize(p->pCla->vImps) == 0 )
        return Ratio;
    // simulate the AIG manager with combinational patterns
    pComb = Fra_SmlSimulateComb( p->pManAig, nSimWords );
    // go through the implications and collect where they do not hold
    pResult = Fra_ObjSim( pComb, 0 );
    assert( pResult[0] == 0 );
    Vec_IntForEachEntry( p->pCla->vImps, Imp, i )
    {
        Left = Fra_ImpLeft(Imp);
        Right = Fra_ImpRight(Imp);
        Sml_NodeSaveNotImpPatterns( pComb, Left, Right, pResult );
    }
    // count the number of ones in this area
    Ratio = 100.0 * Fra_SmlCountOnesOne( pComb, 0 ) / (32*(pComb->nWordsTotal-pComb->nWordsPref));
    Fra_SmlStop( pComb );
    return Ratio;
}

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

  Synopsis    [Returns the number of failed implications.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Fra_ImpVerifyUsingSimulation( Fra_Man_t * p )
{
Alan Mishchenko committed
660 661
    int nFrames = 2000;
    int nSimWords = 8;
Alan Mishchenko committed
662 663 664 665 666 667
    Fra_Sml_t * pSeq;
    char * pfFails;
    int Left, Right, Imp, i, Counter;
    if ( p->pCla->vImps == NULL || Vec_IntSize(p->pCla->vImps) == 0 )
        return 0;
    // simulate the AIG manager with combinational patterns
Alan Mishchenko committed
668
    pSeq = Fra_SmlSimulateSeq( p->pManAig, p->pPars->nFramesP, nFrames, nSimWords );
Alan Mishchenko committed
669 670 671 672 673 674 675 676 677 678 679 680 681 682
    // go through the implications and check how many of them do not hold
    pfFails = ALLOC( char, Vec_IntSize(p->pCla->vImps) );
    memset( pfFails, 0, sizeof(char) * Vec_IntSize(p->pCla->vImps) );
    Vec_IntForEachEntry( p->pCla->vImps, Imp, i )
    {
        Left = Fra_ImpLeft(Imp);
        Right = Fra_ImpRight(Imp);
        pfFails[i] = !Sml_NodeCheckImp( pSeq, Left, Right );
    }
    // count how many has failed
    Counter = 0;
    for ( i = 0; i < Vec_IntSize(p->pCla->vImps); i++ )
        Counter += pfFails[i];
    free( pfFails );
Alan Mishchenko committed
683
    Fra_SmlStop( pSeq );
Alan Mishchenko committed
684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718
    return Counter;
}

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

  Synopsis    [Record proven implications in the AIG manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Fra_ImpRecordInManager( Fra_Man_t * p, Aig_Man_t * pNew )
{
    Aig_Obj_t * pLeft, * pRight, * pMiter;
    int nPosOld, Imp, i;
    if ( p->pCla->vImps == NULL || Vec_IntSize(p->pCla->vImps) == 0 )
        return;
    // go through the implication
    nPosOld = Aig_ManPoNum(pNew);
    Vec_IntForEachEntry( p->pCla->vImps, Imp, i )
    {
        pLeft = Aig_ManObj( p->pManAig, Fra_ImpLeft(Imp) );
        pRight = Aig_ManObj( p->pManAig, Fra_ImpRight(Imp) );
        // record the implication: L' + R
        pMiter = Aig_Or( pNew, 
            Aig_NotCond(pLeft->pData, !pLeft->fPhase), 
            Aig_NotCond(pRight->pData, pRight->fPhase) ); 
        Aig_ObjCreatePo( pNew, pMiter );
    }
    pNew->nAsserts = Aig_ManPoNum(pNew) - nPosOld;
}

Alan Mishchenko committed
719 720 721 722 723
////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////