fraCec.c 17.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
/**CFile****************************************************************

  FileName    [fraCec.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [New FRAIG package.]

  Synopsis    [CEC engined based on fraiging.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

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

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

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

#include "fra.h"
22 23
#include "sat/cnf/cnf.h"
#include "sat/bsat/satSolver2.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 38 39 40 41 42 43 44 45 46
////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

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

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
47
int Fra_FraigSat( Aig_Man_t * pMan, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int nLearnedStart, int nLearnedDelta, int nLearnedPerce, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose )
Alan Mishchenko committed
48
{
49 50 51 52
    if ( fNewSolver )
    {
        extern void * Cnf_DataWriteIntoSolver2( Cnf_Dat_t * p, int nFrames, int fInit );
        extern int    Cnf_DataWriteOrClause2( void * pSat, Cnf_Dat_t * pCnf );
Alan Mishchenko committed
53

54 55
        sat_solver2 * pSat;
        Cnf_Dat_t * pCnf;
56
        int status, RetValue;
57
        abctime clk = Abc_Clock();
58
        Vec_Int_t * vCiIds;
Alan Mishchenko committed
59

60 61
        assert( Aig_ManRegNum(pMan) == 0 );
        pMan->pData = NULL;
Alan Mishchenko committed
62

63
        // derive CNF
64 65
        pCnf = Cnf_Derive( pMan, Aig_ManCoNum(pMan) );
    //    pCnf = Cnf_DeriveSimple( pMan, Aig_ManCoNum(pMan) );
Alan Mishchenko committed
66

67 68 69
        if ( fFlipBits ) 
            Cnf_DataTranformPolarity( pCnf, 0 );

70 71 72 73 74 75
        if ( fVerbose )
        {
            printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals );
            Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
        }

76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
        // convert into SAT solver
        pSat = (sat_solver2 *)Cnf_DataWriteIntoSolver2( pCnf, 1, 0 );
        if ( pSat == NULL )
        {
            Cnf_DataFree( pCnf );
            return 1;
        }

        if ( fAndOuts )
        {
            // assert each output independently
            if ( !Cnf_DataWriteAndClauses( pSat, pCnf ) )
            {
                sat_solver2_delete( pSat );
                Cnf_DataFree( pCnf );
                return 1;
            }
        }
        else
        {
            // add the OR clause for the outputs
            if ( !Cnf_DataWriteOrClause2( pSat, pCnf ) )
            {
                sat_solver2_delete( pSat );
                Cnf_DataFree( pCnf );
                return 1;
            }
        }
        vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan );
Alan Mishchenko committed
105
        Cnf_DataFree( pCnf );
Alan Mishchenko committed
106 107


108
        printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver2_nvars(pSat), sat_solver2_nclauses(pSat) );
109
        ABC_PRT( "Time", Abc_Clock() - clk );
110 111

        // simplify the problem
112
        clk = Abc_Clock();
113
        status = sat_solver2_simplify(pSat);
114
//        printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver2_nvars(pSat), sat_solver2_nclauses(pSat) );
115
//        ABC_PRT( "Time", Abc_Clock() - clk );
116
        if ( status == 0 )
Alan Mishchenko committed
117
        {
118 119 120
            Vec_IntFree( vCiIds );
            sat_solver2_delete( pSat );
    //        printf( "The problem is UNSATISFIABLE after simplification.\n" );
Alan Mishchenko committed
121 122
            return 1;
        }
123 124

        // solve the miter
125
        clk = Abc_Clock();
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
        if ( fVerbose )
            pSat->verbosity = 1;
        status = sat_solver2_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)0 );
        if ( status == l_Undef )
        {
    //        printf( "The problem timed out.\n" );
            RetValue = -1;
        }
        else if ( status == l_True )
        {
    //        printf( "The problem is SATISFIABLE.\n" );
            RetValue = 0;
        }
        else if ( status == l_False )
        {
    //        printf( "The problem is UNSATISFIABLE.\n" );
            RetValue = 1;
        }
        else
            assert( 0 );

    //    Abc_Print( 1, "The number of conflicts = %6d.  ", (int)pSat->stats.conflicts );
148
    //    Abc_PrintTime( 1, "Solving time", Abc_Clock() - clk );
149 150 151 152 153 154 155
 
        // if the problem is SAT, get the counterexample
        if ( status == l_True )
        {
            pMan->pData = Sat_Solver2GetModel( pSat, vCiIds->pArray, vCiIds->nSize );
        }
        // free the sat_solver2
156
        if ( fVerbose )
157 158 159 160 161 162
            Sat_Solver2PrintStats( stdout, pSat );
    //sat_solver2_store_write( pSat, "trace.cnf" );
    //sat_solver2_store_free( pSat );
        sat_solver2_delete( pSat );
        Vec_IntFree( vCiIds );
        return RetValue;
Alan Mishchenko committed
163 164 165
    }
    else
    {
166 167
        sat_solver * pSat;
        Cnf_Dat_t * pCnf;
168
        int status, RetValue;
169
        abctime clk = Abc_Clock();
170 171 172 173 174 175
        Vec_Int_t * vCiIds;

        assert( Aig_ManRegNum(pMan) == 0 );
        pMan->pData = NULL;

        // derive CNF
176 177
        pCnf = Cnf_Derive( pMan, Aig_ManCoNum(pMan) );
    //    pCnf = Cnf_DeriveSimple( pMan, Aig_ManCoNum(pMan) );
178 179 180 181

        if ( fFlipBits ) 
            Cnf_DataTranformPolarity( pCnf, 0 );

182 183 184 185 186 187
        if ( fVerbose )
        {
            printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals );
            Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
        }

188 189 190
        // convert into SAT solver
        pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
        if ( pSat == NULL )
Alan Mishchenko committed
191 192 193 194
        {
            Cnf_DataFree( pCnf );
            return 1;
        }
Alan Mishchenko committed
195

196
        if ( nLearnedStart )
197
            pSat->nLearntStart = pSat->nLearntMax = nLearnedStart;
198 199 200 201
        if ( nLearnedDelta )
            pSat->nLearntDelta = nLearnedDelta;
        if ( nLearnedPerce )
            pSat->nLearntRatio = nLearnedPerce;
202 203
        if ( fVerbose )
            pSat->fVerbose = fVerbose;
Alan Mishchenko committed
204

205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
        if ( fAndOuts )
        {
            // assert each output independently
            if ( !Cnf_DataWriteAndClauses( pSat, pCnf ) )
            {
                sat_solver_delete( pSat );
                Cnf_DataFree( pCnf );
                return 1;
            }
        }
        else
        {
            // add the OR clause for the outputs
            if ( !Cnf_DataWriteOrClause( pSat, pCnf ) )
            {
                sat_solver_delete( pSat );
                Cnf_DataFree( pCnf );
                return 1;
            }
        }
        vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan );
        Cnf_DataFree( pCnf );
Alan Mishchenko committed
227 228


229
    //    printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) );
230
    //    ABC_PRT( "Time", Abc_Clock() - clk );
231

232
        // simplify the problem
233
        clk = Abc_Clock();
234 235
        status = sat_solver_simplify(pSat);
    //    printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) );
236
    //    ABC_PRT( "Time", Abc_Clock() - clk );
237 238 239 240 241 242 243 244 245
        if ( status == 0 )
        {
            Vec_IntFree( vCiIds );
            sat_solver_delete( pSat );
    //        printf( "The problem is UNSATISFIABLE after simplification.\n" );
            return 1;
        }

        // solve the miter
246
        clk = Abc_Clock();
247 248
//        if ( fVerbose )
//            pSat->verbosity = 1;
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
        status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)0 );
        if ( status == l_Undef )
        {
    //        printf( "The problem timed out.\n" );
            RetValue = -1;
        }
        else if ( status == l_True )
        {
    //        printf( "The problem is SATISFIABLE.\n" );
            RetValue = 0;
        }
        else if ( status == l_False )
        {
    //        printf( "The problem is UNSATISFIABLE.\n" );
            RetValue = 1;
        }
        else
            assert( 0 );

    //    Abc_Print( 1, "The number of conflicts = %6d.  ", (int)pSat->stats.conflicts );
269
    //    Abc_PrintTime( 1, "Solving time", Abc_Clock() - clk );
Alan Mishchenko committed
270
 
271 272 273 274 275 276
        // if the problem is SAT, get the counterexample
        if ( status == l_True )
        {
            pMan->pData = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize );
        }
        // free the sat_solver
277
        if ( fVerbose )
278 279 280 281 282 283
            Sat_SolverPrintStats( stdout, pSat );
    //sat_solver_store_write( pSat, "trace.cnf" );
    //sat_solver_store_free( pSat );
        sat_solver_delete( pSat );
        Vec_IntFree( vCiIds );
        return RetValue;
Alan Mishchenko committed
284 285 286 287 288
    }
}

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

289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
  Synopsis    [Recognizes what nodes are inputs of the EXOR.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Aig_ManCountXors( Aig_Man_t * p )
{
    Aig_Obj_t * pObj, * pFan0, * pFan1;
    int i, Counter = 0;
    Aig_ManForEachNode( p, pObj, i )
        if ( Aig_ObjIsMuxType(pObj) && Aig_ObjRecognizeExor(pObj, &pFan0, &pFan1) )
            Counter++;
    return Counter;

}

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

Alan Mishchenko committed
311 312 313 314 315 316 317 318 319
  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
320
int Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose )
Alan Mishchenko committed
321
{
Alan Mishchenko committed
322 323 324
    int nBTLimitStart =        300;   // starting SAT run
    int nBTLimitFirst =          2;   // first fraiging iteration
    int nBTLimitLast  = nConfLimit;   // the last-gasp SAT run
Alan Mishchenko committed
325 326 327

    Fra_Par_t Params, * pParams = &Params;
    Aig_Man_t * pAig = *ppAig, * pTemp;
328
    int i, RetValue;
329
    abctime clk;
Alan Mishchenko committed
330 331 332 333 334 335 336 337

    // report the original miter
    if ( fVerbose )
    {
        printf( "Original miter:   Nodes = %6d.\n", Aig_ManNodeNum(pAig) );
    }
    RetValue = Fra_FraigMiterStatus( pAig );
//    assert( RetValue == -1 );
Alan Mishchenko committed
338
    if ( RetValue == 0 )
Alan Mishchenko committed
339
    {
340 341
        pAig->pData = ABC_ALLOC( int, Aig_ManCiNum(pAig) );
        memset( pAig->pData, 0, sizeof(int) * Aig_ManCiNum(pAig) );
Alan Mishchenko committed
342
        return RetValue;
Alan Mishchenko committed
343
    }
Alan Mishchenko committed
344 345

    // if SAT only, solve without iteration
346
clk = Abc_Clock();
347
    RetValue = Fra_FraigSat( pAig, (ABC_INT64_T)2*nBTLimitStart, (ABC_INT64_T)0, 0, 0, 0, 1, 0, 0, 0 );
Alan Mishchenko committed
348 349 350
    if ( fVerbose )
    {
        printf( "Initial SAT:      Nodes = %6d.  ", Aig_ManNodeNum(pAig) );
351
ABC_PRT( "Time", Abc_Clock() - clk );
Alan Mishchenko committed
352 353 354 355 356
    }
    if ( RetValue >= 0 )
        return RetValue;

    // duplicate the AIG
357
clk = Abc_Clock();
Alan Mishchenko committed
358
    pAig = Dar_ManRwsat( pTemp = pAig, 1, 0 );
Alan Mishchenko committed
359 360 361 362
    Aig_ManStop( pTemp );
    if ( fVerbose )
    {
        printf( "Rewriting:        Nodes = %6d.  ", Aig_ManNodeNum(pAig) );
363
ABC_PRT( "Time", Abc_Clock() - clk );
Alan Mishchenko committed
364 365 366 367 368 369 370 371 372 373 374
    }

    // perform the loop
    Fra_ParamsDefault( pParams );
    pParams->nBTLimitNode = nBTLimitFirst;
    pParams->nBTLimitMiter = nBTLimitStart;
    pParams->fDontShowBar = 1;
    pParams->fProve = 1;
    for ( i = 0; i < 6; i++ )
    {
//printf( "Running fraiging with %d BTnode and %d BTmiter.\n", pParams->nBTLimitNode, pParams->nBTLimitMiter );
375 376 377 378 379 380 381 382 383 384 385 386 387
        // try XOR balancing
        if ( Aig_ManCountXors(pAig) * 30 > Aig_ManNodeNum(pAig) + 300 )
        {
clk = Abc_Clock();
            pAig = Dar_ManBalanceXor( pTemp = pAig, 1, 0, 0 );
            Aig_ManStop( pTemp );
            if ( fVerbose )
            {
                printf( "Balance-X:        Nodes = %6d.  ", Aig_ManNodeNum(pAig) );
ABC_PRT( "Time", Abc_Clock() - clk );
            } 
        }

Alan Mishchenko committed
388
        // run fraiging
389
clk = Abc_Clock();
Alan Mishchenko committed
390 391 392 393 394
        pAig = Fra_FraigPerform( pTemp = pAig, pParams );
        Aig_ManStop( pTemp );
        if ( fVerbose )
        {
            printf( "Fraiging (i=%d):   Nodes = %6d.  ", i+1, Aig_ManNodeNum(pAig) );
395
ABC_PRT( "Time", Abc_Clock() - clk );
Alan Mishchenko committed
396 397 398 399 400 401 402 403
        }

        // check the miter status
        RetValue = Fra_FraigMiterStatus( pAig );
        if ( RetValue >= 0 )
            break;

        // perform rewriting
404
clk = Abc_Clock();
Alan Mishchenko committed
405 406 407 408 409
        pAig = Dar_ManRewriteDefault( pTemp = pAig );
        Aig_ManStop( pTemp );
        if ( fVerbose )
        {
            printf( "Rewriting:        Nodes = %6d.  ", Aig_ManNodeNum(pAig) );
410
ABC_PRT( "Time", Abc_Clock() - clk );
Alan Mishchenko committed
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
        } 

        // check the miter status
        RetValue = Fra_FraigMiterStatus( pAig );
        if ( RetValue >= 0 )
            break;
        // try simulation

        // set the parameters for the next run
        pParams->nBTLimitNode = 8 * pParams->nBTLimitNode;
        pParams->nBTLimitMiter = 2 * pParams->nBTLimitMiter;
    }

    // if still unsolved try last gasp
    if ( RetValue == -1 )
    {
427
clk = Abc_Clock();
428
        RetValue = Fra_FraigSat( pAig, (ABC_INT64_T)nBTLimitLast, (ABC_INT64_T)0, 0, 0, 0, 1, 0, 0, 0 );
Alan Mishchenko committed
429 430
        if ( fVerbose )
        {
431
            printf( "Final SAT:        Nodes = %6d.  ", Aig_ManNodeNum(pAig) );
432
ABC_PRT( "Time", Abc_Clock() - clk );
Alan Mishchenko committed
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
        }
    }

    *ppAig = pAig;
    return RetValue;
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
451
int Fra_FraigCecPartitioned( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int nConfLimit, int nPartSize, int fSmart, int fVerbose )
Alan Mishchenko committed
452 453 454 455 456
{
    Aig_Man_t * pAig;
    Vec_Ptr_t * vParts;
    int i, RetValue = 1, nOutputs;
    // create partitions
Alan Mishchenko committed
457
    vParts = Aig_ManMiterPartitioned( pMan1, pMan2, nPartSize, fSmart );
Alan Mishchenko committed
458 459
    // solve the partitions
    nOutputs = -1;
460
    Vec_PtrForEachEntry( Aig_Man_t *, vParts, pAig, i )
Alan Mishchenko committed
461 462 463
    {
        nOutputs++;
        if ( fVerbose )
Alan Mishchenko committed
464
        {
Alan Mishchenko committed
465
            printf( "Verifying part %4d  (out of %4d)  PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", 
466
                i+1, Vec_PtrSize(vParts), Aig_ManCiNum(pAig), Aig_ManCoNum(pAig), 
Alan Mishchenko committed
467
                Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) );
Alan Mishchenko committed
468 469
            fflush( stdout );
        }
Alan Mishchenko committed
470 471 472 473 474
        RetValue = Fra_FraigMiterStatus( pAig );
        if ( RetValue == 1 )
            continue;
        if ( RetValue == 0 )
            break;
Alan Mishchenko committed
475
        RetValue = Fra_FraigCec( &pAig, nConfLimit, 0 );
Alan Mishchenko committed
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
        Vec_PtrWriteEntry( vParts, i, pAig );
        if ( RetValue == 1 )
            continue;
        if ( RetValue == 0 )
            break;
        break;
    }
    // clear the result
    if ( fVerbose )
    {
        printf( "                                                                                          \r" );
        fflush( stdout );
    }
    // report the timeout
    if ( RetValue == -1 )
    {
        printf( "Timed out after verifying %d partitions (out of %d).\n", nOutputs, Vec_PtrSize(vParts) );
        fflush( stdout );
    }
Alan Mishchenko committed
495
    // free intermediate results
496
    Vec_PtrForEachEntry( Aig_Man_t *, vParts, pAig, i )
Alan Mishchenko committed
497 498 499 500 501
        Aig_ManStop( pAig );
    Vec_PtrFree( vParts );
    return RetValue;
}

Alan Mishchenko committed
502 503 504 505 506 507 508 509 510 511 512
/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
513
int Fra_FraigCecTop( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int nConfLimit, int nPartSize, int fSmart, int fVerbose )
Alan Mishchenko committed
514
{
Alan Mishchenko committed
515
    Aig_Man_t * pTemp;
Alan Mishchenko committed
516
    //Abc_NtkDarCec( pNtk1, pNtk2, fPartition, fVerbose );
517
    int RetValue;
518
    abctime clkTotal = Abc_Clock();
Alan Mishchenko committed
519

520
    if ( Aig_ManCiNum(pMan1) != Aig_ManCiNum(pMan1) )
Alan Mishchenko committed
521 522 523 524
    {
        printf( "Abc_CommandAbc8Cec(): Miters have different number of PIs.\n" );
        return 0;
    }
525
    if ( Aig_ManCoNum(pMan1) != Aig_ManCoNum(pMan1) )
Alan Mishchenko committed
526 527 528 529
    {
        printf( "Abc_CommandAbc8Cec(): Miters have different number of POs.\n" );
        return 0;
    }
530 531
    assert( Aig_ManCiNum(pMan1) == Aig_ManCiNum(pMan1) );
    assert( Aig_ManCoNum(pMan1) == Aig_ManCoNum(pMan1) );
Alan Mishchenko committed
532

Alan Mishchenko committed
533 534 535 536 537 538 539 540 541 542
    // make sure that the first miter has more nodes
    if ( Aig_ManNodeNum(pMan1) < Aig_ManNodeNum(pMan2) )
    {
        pTemp = pMan1;
        pMan1 = pMan2;
        pMan2 = pTemp;
    }
    assert( Aig_ManNodeNum(pMan1) >= Aig_ManNodeNum(pMan2) );

    if ( nPartSize )
Alan Mishchenko committed
543
        RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, nConfLimit, nPartSize, fSmart, fVerbose );
Alan Mishchenko committed
544
    else // no partitioning
545
        RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, nConfLimit, Aig_ManCoNum(pMan1), 0, fVerbose );
Alan Mishchenko committed
546 547 548 549 550

    // report the miter
    if ( RetValue == 1 )
    {
        printf( "Networks are equivalent.   " );
551
ABC_PRT( "Time", Abc_Clock() - clkTotal );
Alan Mishchenko committed
552 553 554 555
    }
    else if ( RetValue == 0 )
    {
        printf( "Networks are NOT EQUIVALENT.   " );
556
ABC_PRT( "Time", Abc_Clock() - clkTotal );
Alan Mishchenko committed
557 558 559 560
    }
    else
    {
        printf( "Networks are UNDECIDED.   " );
561
ABC_PRT( "Time", Abc_Clock() - clkTotal );
Alan Mishchenko committed
562 563 564 565 566
    }
    fflush( stdout );
    return RetValue;
}

Alan Mishchenko committed
567 568 569 570 571 572

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


573 574
ABC_NAMESPACE_IMPL_END