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

  FileName    [gia.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Scalable AIG package.]

  Synopsis    [Scalable gate-level abstraction.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

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

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

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

#include "gia.h"
22 23 24 25
#include "giaAbsRef.h"
#include "sat/cnf/cnf.h"
#include "sat/bsat/satSolver2.h"
#include "base/main/main.h"
26 27 28 29 30 31 32

ABC_NAMESPACE_IMPL_START

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

33 34
#define GA2_BIG_NUM 0x3FFFFFFF

35 36 37 38
typedef struct Ga2_Man_t_ Ga2_Man_t; // manager
struct Ga2_Man_t_
{
    // user data
39 40
    Gia_Man_t *    pGia;         // working AIG manager
    Gia_ParVta_t * pPars;        // parameters
41
    // markings 
42
    Vec_Ptr_t *    vCnfs;        // for each object: CNF0, CNF1
43
    // abstraction
44
    Vec_Int_t *    vIds;         // abstraction ID for each GIA object
45
    Vec_Int_t *    vProofIds;    // mapping of GIA objects into their proof IDs
46
    Vec_Int_t *    vAbs;         // array of abstracted objects
47 48
    Vec_Int_t *    vValues;      // array of objects with abstraction ID assigned
    int            nProofIds;    // the counter of proof IDs
49 50
    int            LimAbs;       // limit value for starting abstraction objects
    int            LimPpi;       // limit value for starting PPI objects
51
    int            nMarked;      // total number of marked nodes and flops
52
    // refinement
53
    Rnm_Man_t *    pRnm;         // refinement manager
54
    // SAT solver and variables
55 56 57
    Vec_Ptr_t *    vId2Lit;      // mapping, for each timeframe, of object ID into SAT literal
    sat_solver2 *  pSat;         // incremental SAT solver
    int            nSatVars;     // the number of SAT variables
58 59
    int            nCexes;       // the number of counter-examples
    int            nObjAdded;    // objs added during refinement
60 61 62
    // temporaries
    Vec_Int_t *    vLits;
    Vec_Int_t *    vIsopMem;
63
    char * pSopSizes, ** pSops;  // CNF representation
64 65 66 67 68 69 70 71 72
    // statistics  
    clock_t        timeStart;
    clock_t        timeInit;
    clock_t        timeSat;
    clock_t        timeUnsat;
    clock_t        timeCex;
    clock_t        timeOther;
};

73 74 75 76 77 78
static inline int         Ga2_ObjOffset( Gia_Man_t * p, Gia_Obj_t * pObj )       { return Vec_IntEntry(p->vMapping, Gia_ObjId(p, pObj));                                                    }
static inline int         Ga2_ObjLeaveNum( Gia_Man_t * p, Gia_Obj_t * pObj )     { return Vec_IntEntry(p->vMapping, Ga2_ObjOffset(p, pObj));                                                }
static inline int *       Ga2_ObjLeavePtr( Gia_Man_t * p, Gia_Obj_t * pObj )     { return Vec_IntEntryP(p->vMapping, Ga2_ObjOffset(p, pObj) + 1);                                           }
static inline unsigned    Ga2_ObjTruth( Gia_Man_t * p, Gia_Obj_t * pObj )        { return (unsigned)Vec_IntEntry(p->vMapping, Ga2_ObjOffset(p, pObj) + Ga2_ObjLeaveNum(p, pObj) + 1);       }
static inline int         Ga2_ObjRefNum( Gia_Man_t * p, Gia_Obj_t * pObj )       { return (unsigned)Vec_IntEntry(p->vMapping, Ga2_ObjOffset(p, pObj) + Ga2_ObjLeaveNum(p, pObj) + 2);       }
static inline Vec_Int_t * Ga2_ObjLeaves( Gia_Man_t * p, Gia_Obj_t * pObj )       { static Vec_Int_t v; v.nSize = Ga2_ObjLeaveNum(p, pObj), v.pArray = Ga2_ObjLeavePtr(p, pObj); return &v;  }
79

80 81
static inline int         Ga2_ObjId( Ga2_Man_t * p, Gia_Obj_t * pObj )           { return Vec_IntEntry(p->vIds, Gia_ObjId(p->pGia, pObj));                                                  }
static inline void        Ga2_ObjSetId( Ga2_Man_t * p, Gia_Obj_t * pObj, int i ) { Vec_IntWriteEntry(p->vIds, Gia_ObjId(p->pGia, pObj), i);                                                 }
82

83 84
static inline Vec_Int_t * Ga2_ObjCnf0( Ga2_Man_t * p, Gia_Obj_t * pObj )         { assert(Ga2_ObjId(p,pObj) >= 0); return Vec_PtrEntry( p->vCnfs, 2*Ga2_ObjId(p,pObj)   );                  }
static inline Vec_Int_t * Ga2_ObjCnf1( Ga2_Man_t * p, Gia_Obj_t * pObj )         { assert(Ga2_ObjId(p,pObj) >= 0); return Vec_PtrEntry( p->vCnfs, 2*Ga2_ObjId(p,pObj)+1 );                  }
85

86 87 88 89
static inline int         Ga2_ObjIsAbs0( Ga2_Man_t * p, Gia_Obj_t * pObj )       { assert(Ga2_ObjId(p,pObj) >= 0); return Ga2_ObjId(p,pObj) >= 0         && Ga2_ObjId(p,pObj) < p->LimAbs;  }
static inline int         Ga2_ObjIsLeaf0( Ga2_Man_t * p, Gia_Obj_t * pObj )      { assert(Ga2_ObjId(p,pObj) >= 0); return Ga2_ObjId(p,pObj) >= p->LimAbs && Ga2_ObjId(p,pObj) < p->LimPpi;  }
static inline int         Ga2_ObjIsAbs( Ga2_Man_t * p, Gia_Obj_t * pObj )        { return Ga2_ObjId(p,pObj) >= 0 &&  Ga2_ObjCnf0(p,pObj);                                                   }
static inline int         Ga2_ObjIsLeaf( Ga2_Man_t * p, Gia_Obj_t * pObj )       { return Ga2_ObjId(p,pObj) >= 0 && !Ga2_ObjCnf0(p,pObj);                                                   }
90

91
static inline Vec_Int_t * Ga2_MapFrameMap( Ga2_Man_t * p, int f )                { return (Vec_Int_t *)Vec_PtrEntry( p->vId2Lit, f );                                                       }
92

93
// returns literal of this object, or -1 if SAT variable of the object is not assigned
94 95
static inline int Ga2_ObjFindLit( Ga2_Man_t * p, Gia_Obj_t * pObj, int f )  
{ 
96
    int Id = Ga2_ObjId(p,pObj);
97
    assert( Ga2_ObjId(p,pObj) >= 0 && Ga2_ObjId(p,pObj) < Vec_IntSize(p->vValues) );
98
    return Vec_IntEntry( Ga2_MapFrameMap(p, f), Ga2_ObjId(p,pObj) );
99
}
100
// inserts literal of this object
101 102
static inline void Ga2_ObjAddLit( Ga2_Man_t * p, Gia_Obj_t * pObj, int f, int Lit )  
{ 
103
//    assert( Lit > 1 );
104
    assert( Ga2_ObjFindLit(p, pObj, f) == -1 );
105
    Vec_IntSetEntry( Ga2_MapFrameMap(p, f), Ga2_ObjId(p,pObj), Lit );
106
}
107
// returns or inserts-and-returns literal of this object
108 109 110 111 112 113 114 115
static inline int Ga2_ObjFindOrAddLit( Ga2_Man_t * p, Gia_Obj_t * pObj, int f )  
{ 
    int Lit = Ga2_ObjFindLit( p, pObj, f );
    if ( Lit == -1 )
    {
        Lit = toLitCond( p->nSatVars++, 0 );
        Ga2_ObjAddLit( p, pObj, f, Lit );
    }
116
//    assert( Lit > 1 );
117 118 119 120 121 122 123 124 125
    return Lit;
}

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

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

126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
  Synopsis    [Computes truth table for the marked node.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
unsigned Ga2_ObjComputeTruth_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int fFirst )
{
    unsigned Val0, Val1;
    if ( pObj->fPhase && !fFirst )
        return pObj->Value;
    assert( Gia_ObjIsAnd(pObj) );
    Val0 = Ga2_ObjComputeTruth_rec( p, Gia_ObjFanin0(pObj), 0 );
    Val1 = Ga2_ObjComputeTruth_rec( p, Gia_ObjFanin1(pObj), 0 );
    return (Gia_ObjFaninC0(pObj) ? ~Val0 : Val0) & (Gia_ObjFaninC1(pObj) ? ~Val1 : Val1);
}
unsigned Ga2_ManComputeTruth( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vLeaves )
{
    static unsigned uTruth5[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
    Gia_Obj_t * pObj;
    int i;
    Gia_ManForEachObjVec( vLeaves, p, pObj, i )
        pObj->Value = uTruth5[i];
152
    return Ga2_ObjComputeTruth_rec( p, pRoot, 1 );
153 154 155 156
}

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

157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
  Synopsis    [Returns AIG marked for CNF generation.]

  Description [The marking satisfies the following requirements:
  Each marked node has the number of marked fanins no more than N.]
               
  SideEffects [Uses pObj->fPhase to store the markings.]

  SeeAlso     []

***********************************************************************/
int Ga2_ManBreakTree_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int fFirst, int N )
{   // breaks a tree rooted at the node into N-feasible subtrees
    int Val0, Val1;
    if ( pObj->fPhase && !fFirst )
        return 1;
    Val0 = Ga2_ManBreakTree_rec( p, Gia_ObjFanin0(pObj), 0, N );
    Val1 = Ga2_ManBreakTree_rec( p, Gia_ObjFanin1(pObj), 0, N );
    if ( Val0 + Val1 < N )
        return Val0 + Val1;
    if ( Val0 + Val1 == N )
    {
        pObj->fPhase = 1;
        return 1;
    }
    assert( Val0 + Val1 > N );
    assert( Val0 < N && Val1 < N );
    if ( Val0 >= Val1 )
    {
        Gia_ObjFanin0(pObj)->fPhase = 1;
        Val0 = 1;
    }
    else 
    {
        Gia_ObjFanin1(pObj)->fPhase = 1;
        Val1 = 1;
    }
    if ( Val0 + Val1 < N )
        return Val0 + Val1;
    if ( Val0 + Val1 == N )
    {
        pObj->fPhase = 1;
        return 1;
    }
    assert( 0 );
    return -1;
}
int Ga2_ManCheckNodesAnd( Gia_Man_t * p, Vec_Int_t * vNodes )
{
    Gia_Obj_t * pObj;
    int i;
    Gia_ManForEachObjVec( vNodes, p, pObj, i )
        if ( (!Gia_ObjFanin0(pObj)->fPhase && Gia_ObjFaninC0(pObj)) || 
             (!Gia_ObjFanin1(pObj)->fPhase && Gia_ObjFaninC1(pObj)) )
            return 0;
    return 1;
}
void Ga2_ManCollectNodes_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes, int fFirst )
{
    if ( pObj->fPhase && !fFirst )
        return;
    assert( Gia_ObjIsAnd(pObj) );
    Ga2_ManCollectNodes_rec( p, Gia_ObjFanin0(pObj), vNodes, 0 );
    Ga2_ManCollectNodes_rec( p, Gia_ObjFanin1(pObj), vNodes, 0 );
    Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );

}
void Ga2_ManCollectLeaves_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves, int fFirst )
{
    if ( pObj->fPhase && !fFirst )
    {
        Vec_IntPushUnique( vLeaves, Gia_ObjId(p, pObj) );
        return;
    }
    assert( Gia_ObjIsAnd(pObj) );
    Ga2_ManCollectLeaves_rec( p, Gia_ObjFanin0(pObj), vLeaves, 0 );
    Ga2_ManCollectLeaves_rec( p, Gia_ObjFanin1(pObj), vLeaves, 0 );
}
234
int Ga2_ManMarkup( Gia_Man_t * p, int N )
235
{
236
    int fSimple = 1;
237
    static unsigned uTruth5[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
238 239 240
    clock_t clk = clock();
    Vec_Int_t * vLeaves;
    Gia_Obj_t * pObj;
241
    int i, k, Leaf, CountMarks;
242

243 244
    vLeaves = Vec_IntAlloc( 100 );

245
    if ( fSimple )
246
    {
247 248
        Gia_ManForEachObj( p, pObj, i )
            pObj->fPhase = !Gia_ObjIsCo(pObj);
249
    }
250
    else
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 283 284 285 286
        // label nodes with multiple fanouts and inputs MUXes
        Gia_ManForEachObj( p, pObj, i )
        {
            pObj->Value = 0;
            if ( !Gia_ObjIsAnd(pObj) )
                continue;
            Gia_ObjFanin0(pObj)->Value++;
            Gia_ObjFanin1(pObj)->Value++;
            if ( !Gia_ObjIsMuxType(pObj) )
                continue;
            Gia_ObjFanin0(Gia_ObjFanin0(pObj))->Value++;
            Gia_ObjFanin1(Gia_ObjFanin0(pObj))->Value++;
            Gia_ObjFanin0(Gia_ObjFanin1(pObj))->Value++;
            Gia_ObjFanin1(Gia_ObjFanin1(pObj))->Value++;
        }
        Gia_ManForEachObj( p, pObj, i )
        {
            pObj->fPhase = 0;
            if ( Gia_ObjIsAnd(pObj) )
                pObj->fPhase = (pObj->Value > 1);
            else if ( Gia_ObjIsCo(pObj) )
                Gia_ObjFanin0(pObj)->fPhase = 1;
            else 
                pObj->fPhase = 1;
        } 
        // add marks when needed
        Gia_ManForEachAnd( p, pObj, i )
        {
            if ( !pObj->fPhase )
                continue;
            Vec_IntClear( vLeaves );
            Ga2_ManCollectLeaves_rec( p, pObj, vLeaves, 1 );
            if ( Vec_IntSize(vLeaves) > N )
                Ga2_ManBreakTree_rec( p, pObj, 1, N );
        }
287
    }
288

289
    // verify that the tree is split correctly
290 291
    Vec_IntFreeP( &p->vMapping );
    p->vMapping = Vec_IntStart( Gia_ManObjNum(p) );
292 293 294 295 296 297 298 299 300 301 302 303 304
    Gia_ManForEachRo( p, pObj, i )
    {
        Gia_Obj_t * pObjRi = Gia_ObjRoToRi(p, pObj);
        assert( pObj->fPhase );
        assert( Gia_ObjFanin0(pObjRi)->fPhase );
        // create map
        Vec_IntWriteEntry( p->vMapping, Gia_ObjId(p, pObj), Vec_IntSize(p->vMapping) );
        Vec_IntPush( p->vMapping, 1 );
        Vec_IntPush( p->vMapping, Gia_ObjFaninId0p(p, pObjRi) );
        Vec_IntPush( p->vMapping, Gia_ObjFaninC0(pObjRi) ? 0x55555555 : 0xAAAAAAAA );
        Vec_IntPush( p->vMapping, -1 );  // placeholder for ref counter
    }
    CountMarks = Gia_ManRegNum(p);
305 306 307 308 309 310 311
    Gia_ManForEachAnd( p, pObj, i )
    {
        if ( !pObj->fPhase )
            continue;
        Vec_IntClear( vLeaves );
        Ga2_ManCollectLeaves_rec( p, pObj, vLeaves, 1 );
//        printf( "%d ", Vec_IntSize(vLeaves) );
312 313
        assert( Vec_IntSize(vLeaves) <= N );
        // create map
314 315
        Vec_IntWriteEntry( p->vMapping, i, Vec_IntSize(p->vMapping) );
        Vec_IntPush( p->vMapping, Vec_IntSize(vLeaves) );
316
        Vec_IntForEachEntry( vLeaves, Leaf, k )
317 318
        {            
            Vec_IntPush( p->vMapping, Leaf );
319
            Gia_ManObj(p, Leaf)->Value = uTruth5[k];
320
            assert( Gia_ManObj(p, Leaf)->fPhase );
321
        }
322 323
        Vec_IntPush( p->vMapping,  (int)Ga2_ObjComputeTruth_rec( p, pObj, 1 ) );
        Vec_IntPush( p->vMapping, -1 );  // placeholder for ref counter
324 325 326 327 328 329
        CountMarks++;
    }
    Abc_PrintTime( 1, "Time", clock() - clk );
    Vec_IntFree( vLeaves );
    return CountMarks;
}
330 331 332
void Ga2_ManComputeTest( Gia_Man_t * p )
{
    clock_t clk;
333
//    unsigned uTruth;
334
    Gia_Obj_t * pObj;
335
    int i, Counter = 0;
336
    clk = clock();
337 338
    Ga2_ManMarkup( p, 5 );
    Abc_PrintTime( 1, "Time", clock() - clk );
339 340 341 342
    Gia_ManForEachAnd( p, pObj, i )
    {
        if ( !pObj->fPhase )
            continue;
343 344 345 346 347
//        uTruth = Ga2_ObjTruth( p, pObj );
//        printf( "%6d : ", Counter );
//        Kit_DsdPrintFromTruth( &uTruth, Ga2_ObjLeaveNum(p, pObj) ); 
//        printf( "\n" );
        Counter++;
348
    }
349
    printf( "Marked AND nodes = %6d.  ", Counter );
350 351
    Abc_PrintTime( 1, "Time", clock() - clk );
}
352 353 354 355 356 357 358 359 360 361 362 363

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
364
Ga2_Man_t * Ga2_ManStart( Gia_Man_t * pGia, Gia_ParVta_t * pPars )
365
{
366 367
    Ga2_Man_t * p;
    p = ABC_CALLOC( Ga2_Man_t, 1 );
368 369
    p->timeStart = clock();
    // user data
370 371
    p->pGia      = pGia;
    p->pPars     = pPars;
372
    // markings 
373
    p->nMarked   = Ga2_ManMarkup( pGia, 5 );
374 375 376
    p->vCnfs     = Vec_PtrAlloc( 1000 );
    Vec_PtrPush( p->vCnfs, Vec_IntAlloc(0) );
    Vec_PtrPush( p->vCnfs, Vec_IntAlloc(0) );
377
    // abstraction
378
    p->vIds      = Vec_IntStartFull( Gia_ManObjNum(pGia) );
379
    p->vProofIds = Vec_IntAlloc( 0 );
380 381
    p->vAbs      = Vec_IntAlloc( 1000 );
    p->vValues   = Vec_IntAlloc( 1000 );
382
    // add constant node to abstraction
383 384
    Ga2_ObjSetId( p, Gia_ManConst0(pGia), 0 );
    Vec_IntPush( p->vValues, 0 );
385
    Vec_IntPush( p->vAbs, 0 );
386
    // refinement
387
    p->pRnm      = Rnm_ManStart( pGia );
388
    // SAT solver and variables
389
    p->vId2Lit   = Vec_PtrAlloc( 1000 );
390
    // temporaries
391 392
    p->vLits     = Vec_IntAlloc( 100 );
    p->vIsopMem  = Vec_IntAlloc( 100 );
393
    Cnf_ReadMsops( &p->pSopSizes, &p->pSops );
394 395
    return p;
}
396 397 398 399 400 401 402 403 404 405 406
void Ga2_ManReportMemory( Ga2_Man_t * p )
{
    double memTot = 0;
    double memAig = 1.0 * p->pGia->nObjsAlloc * sizeof(Gia_Obj_t) + Vec_IntMemory(p->pGia->vMapping);
    double memSat = sat_solver2_memory( p->pSat, 1 );
    double memPro = sat_solver2_memory_proof( p->pSat );
    double memMap = Vec_VecMemoryInt( (Vec_Vec_t *)p->vId2Lit );
    double memRef = Rnm_ManMemoryUsage( p->pRnm );
    double memOth = sizeof(Ga2_Man_t);
    memOth += Vec_VecMemoryInt( (Vec_Vec_t *)p->vCnfs );
    memOth += Vec_IntMemory( p->vIds );
407
    memOth += Vec_IntMemory( p->vProofIds );
408 409 410 411 412 413
    memOth += Vec_IntMemory( p->vAbs );
    memOth += Vec_IntMemory( p->vValues );
    memOth += Vec_IntMemory( p->vLits );
    memOth += Vec_IntMemory( p->vIsopMem );
    memOth += 336450 + (sizeof(char) + sizeof(char*)) * 65536;
    memTot = memAig + memSat + memPro + memMap + memRef + memOth;
414 415 416 417 418 419 420
    ABC_PRMP( "Memory: AIG      ", memAig, memTot );
    ABC_PRMP( "Memory: SAT      ", memSat, memTot );
    ABC_PRMP( "Memory: Proof    ", memPro, memTot );
    ABC_PRMP( "Memory: Map      ", memMap, memTot );
    ABC_PRMP( "Memory: Refine   ", memRef, memTot );
    ABC_PRMP( "Memory: Other    ", memOth, memTot );
    ABC_PRMP( "Memory: TOTAL    ", memTot, memTot );
421
}
422
void Ga2_ManStop( Ga2_Man_t * p )
423
{
424 425
    Vec_IntFreeP( &p->pGia->vMapping );
    Gia_ManSetPhase( p->pGia );
426
//    if ( p->pPars->fVerbose )
427 428 429 430
        Abc_Print( 1, "SAT solver:  Var = %d  Cla = %d  Conf = %d  Lrn = %d  Reduce = %d  Cex = %d  ObjsAdded = %d\n", 
            sat_solver2_nvars(p->pSat), sat_solver2_nclauses(p->pSat), 
            sat_solver2_nconflicts(p->pSat), sat_solver2_nlearnts(p->pSat), 
            p->pSat->nDBreduces, p->nCexes, p->nObjAdded );
431 432 433 434
    if( p->pSat ) sat_solver2_delete( p->pSat );
    Vec_VecFree( (Vec_Vec_t *)p->vCnfs );
    Vec_VecFree( (Vec_Vec_t *)p->vId2Lit );
    Vec_IntFree( p->vIds );
435
    Vec_IntFree( p->vProofIds );
436
    Vec_IntFree( p->vAbs );
437
    Vec_IntFree( p->vValues );
438 439
    Vec_IntFree( p->vLits );
    Vec_IntFree( p->vIsopMem );
440 441 442 443
    Rnm_ManStop( p->pRnm, 1 );
    ABC_FREE( p->pSopSizes );
    ABC_FREE( p->pSops[1] );
    ABC_FREE( p->pSops );
444 445 446 447 448 449
    ABC_FREE( p );
}


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

450
  Synopsis    [Computes a minimized truth table.]
451

452 453 454 455
  Description [Input literals can be 0/1 (const 0/1), non-trivial literals 
  (integers that are more than 1) and unassigned literals (large integers).
  This procedure computes the truth table that essentially depends on input
  variables ordered in the increasing order of their positive literals.]
456 457 458 459 460 461 462 463
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline unsigned Ga2_ObjTruthDepends( unsigned t, int v )
{
464
    static unsigned uInvTruth5[5] = { 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF };
465
    assert( v >= 0 && v <= 4 );
466
    return ((t ^ (t >> (1 << v))) & uInvTruth5[v]);
467 468 469
}
unsigned Ga2_ObjComputeTruthSpecial( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vLits )
{
470
    int fVerbose = 0;
471
    static unsigned uTruth5[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
472
    unsigned Res, uLeaves[5];
473
    Gia_Obj_t * pObj;
474 475 476 477 478 479 480
    int i, k, Lit, Entry, pMap[5];
    int Id = Gia_ObjId(p, pRoot);
    assert( Gia_ObjIsAnd(pRoot) );

    if ( fVerbose )
    printf( "Object %d.\n", Gia_ObjId(p, pRoot) );

481 482 483
    // assign elementary truth tables
    Gia_ManForEachObjVec( vLeaves, p, pObj, i )
    {
484
        pMap[i] = i;
485
        Entry = Vec_IntEntry( vLits, i );
486
        assert( Entry >= 0 );
487
        if ( Entry == 0 )
488
            pObj->Value = uLeaves[i] = 0;
489
        else if ( Entry == 1 )
490
            pObj->Value = uLeaves[i] = ~0;
491
        else // non-trivial literal
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
        {
            pObj->Value = uLeaves[i] = uTruth5[i];
            // check if this literal already encountered
            Vec_IntForEachEntryStop( vLits, Lit, k, i )
                if ( Abc_Lit2Var(Lit) == Abc_Lit2Var(Entry) )
                {
                    if ( Lit == Entry )
                        pObj->Value = uLeaves[i] = uLeaves[k];
                    else if ( Lit == Abc_LitNot(Entry) )
                        pObj->Value = uLeaves[i] = ~uLeaves[k];
                    else assert( 0 );
                    pMap[i] = k;
                    break;
                }
        }

        if ( fVerbose )
        printf( "%d ", Entry );
510
    }
511 512 513 514

    if ( fVerbose )
    {
    Res = Ga2_ObjTruth( p, pRoot );
515
//    Kit_DsdPrintFromTruth( &Res, Vec_IntSize(vLeaves) );
516 517 518
    printf( "\n" );
    }

519
    // compute truth table
520 521 522
    Res = Ga2_ObjComputeTruth_rec( p, pRoot, 1 );
    if ( Res != 0 && Res != ~0 )
    {
523 524 525 526 527 528 529 530 531 532
        // find essential variables
        int nUsed = 0, pUsed[5];
        for ( i = 0; i < Vec_IntSize(vLeaves); i++ )
            if ( Ga2_ObjTruthDepends( Res, i ) )
                pUsed[nUsed++] = i;
        assert( nUsed > 0 );
        // order the by literal value
        Vec_IntSelectSortCost( pUsed, nUsed, vLits );
        assert( Vec_IntEntry(vLits, pUsed[0]) <= Vec_IntEntry(vLits, pUsed[nUsed-1]) );
        // assign elementary truth tables to the leaves
533
        Gia_ManForEachObjVec( vLeaves, p, pObj, i )
534 535 536 537 538 539 540 541 542 543
        {
            Entry = Vec_IntEntry( vLits, i );
            assert( Entry >= 0 );
            if ( Entry == 0 )
                pObj->Value = 0;
            else if ( Entry == 1 )
                pObj->Value = ~0;
            else // non-trivial literal
                pObj->Value = 0xDEADCAFE; // not important
        }
544
        for ( i = 0; i < nUsed; i++ )
545
        {
546 547 548 549
            Entry = Vec_IntEntry( vLits, pUsed[i] );
            assert( Entry > 1 );
            pObj = Gia_ManObj( p, Vec_IntEntry(vLeaves, pUsed[i]) );
            pObj->Value = Abc_LitIsCompl(Entry) ? ~uTruth5[i] : uTruth5[i];
550
//            pObj->Value = uTruth5[i];
551 552
            // remember this literal
            pUsed[i] = Abc_LitRegular(Entry);
553
//            pUsed[i] = Entry;
554
        }
555 556 557 558 559
        // update using the map
        Gia_ManForEachObjVec( vLeaves, p, pObj, i )
            if ( pMap[i] != i )
                pObj->Value = Gia_ManObj( p, Vec_IntEntry(vLeaves, pMap[i]) )->Value;

560
        // compute truth table
561
        Res = Ga2_ObjComputeTruth_rec( p, pRoot, 1 );
562 563 564 565 566 567
        // reload the literals
        Vec_IntClear( vLits );
        for ( i = 0; i < nUsed; i++ )
        {
            Vec_IntPush( vLits, pUsed[i] );
            assert( Ga2_ObjTruthDepends(Res, i) );
568 569
            if ( fVerbose )
            printf( "%d ", pUsed[i] );
570
        }
571 572 573 574 575
        for ( ; i < 5; i++ )
            assert( !Ga2_ObjTruthDepends(Res, i) );

if ( fVerbose )
{
576
//    Kit_DsdPrintFromTruth( &Res, nUsed );
577 578 579
    printf( "\n" );
}

580
    }
581
    else
582 583 584 585 586 587 588 589 590
    {

if ( fVerbose )
{
    Vec_IntClear( vLits );
    printf( "Const %d\n", Res > 0 );
}

    }
591 592 593 594 595 596 597 598 599 600 601 602 603 604
    return Res;
}

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

  Synopsis    [Returns CNF of the function.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
605
Vec_Int_t * Ga2_ManCnfCompute( unsigned uTruth, int nVars, Vec_Int_t * vCover )
606 607
{
    extern int Kit_TruthIsop( unsigned * puTruth, int nVars, Vec_Int_t * vMemory, int fTryBoth );
608 609
    int RetValue;
    assert( nVars <= 5 );
610
    // transform truth table into the SOP
611
    RetValue = Kit_TruthIsop( &uTruth, nVars, vCover, 0 );
612 613
    assert( RetValue == 0 );
    // check the case of constant cover
614
    return Vec_IntDup( vCover );
615 616 617 618 619 620 621 622 623 624 625 626 627
}

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

  Synopsis    [Derives CNF for one node.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
628
static inline void Ga2_ManCnfAddDynamic( Ga2_Man_t * p, int uTruth, int Lits[], int iLitOut, int ProofId )
629
{
630
    int i, k, b, Cube, nClaLits, ClaLits[6];
631
//    assert( uTruth > 0 && uTruth < 0xffff );
632 633 634 635 636 637
    for ( i = 0; i < 2; i++ )
    {
        if ( i )
            uTruth = 0xffff & ~uTruth;
//        Extra_PrintBinary( stdout, &uTruth, 16 ); printf( "\n" );
        for ( k = 0; k < p->pSopSizes[uTruth]; k++ )
638 639 640 641 642 643
        {
            nClaLits = 0;
            ClaLits[nClaLits++] = i ? lit_neg(iLitOut) : iLitOut;
            Cube = p->pSops[uTruth][k];
            for ( b = 3; b >= 0; b-- )
            {
644
                if ( Cube % 3 == 0 ) // value 0 --> add positive literal
645 646 647 648
                {
                    assert( Lits[b] > 1 );
                    ClaLits[nClaLits++] = Lits[b];
                }
649
                else if ( Cube % 3 == 1 ) // value 1 --> add negative literal
650 651 652 653 654 655
                {
                    assert( Lits[b] > 1 );
                    ClaLits[nClaLits++] = lit_neg(Lits[b]);
                }
                Cube = Cube / 3;
            }
656
            sat_solver2_addclause( p->pSat, ClaLits, ClaLits+nClaLits, ProofId );
657
        }
658 659
    }
}
660
static inline void Ga2_ManCnfAddStatic( Ga2_Man_t * p, Vec_Int_t * vCnf0, Vec_Int_t * vCnf1, int Lits[], int iLitOut, int ProofId )
661
{
662 663 664 665 666 667 668 669 670 671 672 673
    Vec_Int_t * vCnf;
    int i, k, b, Cube, Literal, nClaLits, ClaLits[6];
    for ( i = 0; i < 2; i++ )
    {
        vCnf = i ? vCnf1 : vCnf0;
        Vec_IntForEachEntry( vCnf, Cube, k )
        {
            nClaLits = 0;
            ClaLits[nClaLits++] = i ? lit_neg(iLitOut) : iLitOut;
            for ( b = 0; b < 5; b++ )
            {
                Literal = 3 & (Cube >> (b << 1));
674
                if ( Literal == 1 ) // value 0 --> add positive literal
675
                {
676
//                    assert( Lits[b] > 1 );
677 678
                    ClaLits[nClaLits++] = Lits[b];
                }
679
                else if ( Literal == 2 ) // value 1 --> add negative literal
680
                {
681
//                    assert( Lits[b] > 1 );
682 683 684 685 686 687 688 689
                    ClaLits[nClaLits++] = lit_neg(Lits[b]);
                }
                else if ( Literal != 0 )
                    assert( 0 );
            }
            sat_solver2_addclause( p->pSat, ClaLits, ClaLits+nClaLits, ProofId );
        }
    }
690 691 692 693 694 695 696 697 698 699 700 701 702 703
}


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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
704
static inline void Ga2_ManSetupNode( Ga2_Man_t * p, Gia_Obj_t * pObj, int fAbs )
705 706
{
    unsigned uTruth;
707
    int nLeaves;
708
    int Id = Gia_ObjId(p->pGia, pObj);
709
    assert( pObj->fPhase );
710 711
    assert( Vec_PtrSize(p->vCnfs) == 2 * Vec_IntSize(p->vValues) );
    // assign abstraction ID to the node
712
    if ( Ga2_ObjId(p,pObj) == -1 )
713
    {
714
        Ga2_ObjSetId( p, pObj, Vec_IntSize(p->vValues) );
715
        Vec_IntPush( p->vValues, Gia_ObjId(p->pGia, pObj) );
716 717
        Vec_PtrPush( p->vCnfs, NULL );
        Vec_PtrPush( p->vCnfs, NULL );
718 719
    }
    assert( Ga2_ObjCnf0(p, pObj) == NULL );
720 721 722
    if ( !fAbs )
        return;
    Vec_IntPush( p->vAbs, Gia_ObjId(p->pGia, pObj) );
723
    assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsRo(p->pGia, pObj) );
724
    // compute parameters
725
    nLeaves = Ga2_ObjLeaveNum(p->pGia, pObj);
726
    uTruth = Ga2_ObjTruth( p->pGia, pObj );
727 728 729
    // create CNF for pos/neg phases
    Vec_PtrWriteEntry( p->vCnfs, 2 * Ga2_ObjId(p,pObj),     Ga2_ManCnfCompute( uTruth, nLeaves, p->vIsopMem) );    
    Vec_PtrWriteEntry( p->vCnfs, 2 * Ga2_ObjId(p,pObj) + 1, Ga2_ManCnfCompute(~uTruth, nLeaves, p->vIsopMem) );
730
}
731

732
static inline void Ga2_ManAddToAbsOneStatic( Ga2_Man_t * p, Gia_Obj_t * pObj, int f )
733 734
{
    Vec_Int_t * vLeaves;
735 736
    Gia_Obj_t * pLeaf;
    int k, Lit, iLitOut = Ga2_ObjFindOrAddLit( p, pObj, f );
737
    assert( iLitOut > 1 );
738 739
    assert( Gia_ObjIsConst0(pObj) || Gia_ObjIsRo(p->pGia, pObj) || Gia_ObjIsAnd(pObj) );
    if ( Gia_ObjIsConst0(pObj) || (f == 0 && Gia_ObjIsRo(p->pGia, pObj)) )
740 741 742 743 744 745
    {
        iLitOut = Abc_LitNot( iLitOut );
        sat_solver2_addclause( p->pSat, &iLitOut, &iLitOut + 1, Gia_ObjId(p->pGia, pObj) );
    }
    else
    {
746 747
        int fUseStatic = 1;
        Vec_IntClear( p->vLits );
748
        vLeaves = Ga2_ObjLeaves( p->pGia, pObj );
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791
        Gia_ManForEachObjVec( vLeaves, p->pGia, pLeaf, k )
        {
            Lit = Ga2_ObjFindOrAddLit( p, pLeaf, f - Gia_ObjIsRo(p->pGia, pObj) );
            Vec_IntPush( p->vLits, Lit );
            if ( Lit < 2 )
                fUseStatic = 0;
        }
        if ( fUseStatic || Gia_ObjIsRo(p->pGia, pObj) )
            Ga2_ManCnfAddStatic( p, Ga2_ObjCnf0(p, pObj), Ga2_ObjCnf1(p, pObj), Vec_IntArray(p->vLits), iLitOut, Gia_ObjId(p->pGia, pObj) );
        else
        {
            unsigned uTruth = Ga2_ObjComputeTruthSpecial( p->pGia, pObj, vLeaves, p->vLits );
            Ga2_ManCnfAddDynamic( p, uTruth & 0xFFFF, Vec_IntArray(p->vLits), iLitOut, Gia_ObjId(p->pGia, pObj) );
        }
    }
}
static inline void Ga2_ManAddToAbsOneDynamic( Ga2_Man_t * p, Gia_Obj_t * pObj, int f )
{
    int Id = Gia_ObjId(p->pGia, pObj);
    Vec_Int_t * vLeaves;
    Gia_Obj_t * pLeaf;
    unsigned uTruth;
    int i, Lit;
    assert( Ga2_ObjIsAbs0(p, pObj) );
    assert( Gia_ObjIsConst0(pObj) || Gia_ObjIsRo(p->pGia, pObj) || Gia_ObjIsAnd(pObj) );
    if ( Gia_ObjIsConst0(pObj) || (f == 0 && Gia_ObjIsRo(p->pGia, pObj)) )
    {
        Ga2_ObjAddLit( p, pObj, f, 0 );
    }
    else if ( Gia_ObjIsRo(p->pGia, pObj) )
    {
        // if flop is included in the abstraction, but its driver is not
        // flop input driver has no variable assigned -- we assign it here
        pLeaf = Gia_ObjRoToRi( p->pGia, pObj );
        Lit = Ga2_ObjFindOrAddLit( p, Gia_ObjFanin0(pLeaf), f-1 );
        assert( Lit >= 0 );
        Lit = Abc_LitNotCond( Lit, Gia_ObjFaninC0(pLeaf) );
        Ga2_ObjAddLit( p, pObj, f, Lit );
    }
    else
    {
        int pLits[5];
        assert( Gia_ObjIsAnd(pObj) );
792
        Vec_IntClear( p->vLits );
793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860
        vLeaves = Ga2_ObjLeaves( p->pGia, pObj );
        Gia_ManForEachObjVec( vLeaves, p->pGia, pLeaf, i )
        {
            if ( Ga2_ObjIsAbs0(p, pLeaf) )      // belongs to original abstraction
            {
                Lit = Ga2_ObjFindLit( p, pLeaf, f );
                assert( Lit >= 0 );
            }
            else if ( Ga2_ObjIsLeaf0(p, pLeaf) ) // belongs to original PPIs
            {
//                Lit = Ga2_ObjFindLit( p, pLeaf, f );
                Lit = Ga2_ObjFindOrAddLit( p, pLeaf, f );
                if ( Lit == -1 )
                {
                    Lit = GA2_BIG_NUM + i;
                    assert( 0 );
                }
            }
            else assert( 0 );
            Vec_IntPush( p->vLits, (pLits[i] = Lit) );
        }

        // minimize truth table
        uTruth = Ga2_ObjComputeTruthSpecial( p->pGia, pObj, vLeaves, p->vLits );
        if ( uTruth == 0 || uTruth == ~0 ) // const 0 / 1
        {
            Lit = (uTruth > 0);
            Ga2_ObjAddLit( p, pObj, f, Lit );
        }
        else if ( uTruth == 0xAAAAAAAA || uTruth == 0x55555555 )  // buffer / inverter
        {
            Lit = Vec_IntEntry( p->vLits, 0 );
            if ( Lit >= GA2_BIG_NUM )
            {
                pLeaf = Gia_ManObj( p->pGia, Vec_IntEntry(vLeaves, Lit-GA2_BIG_NUM) );
                Lit = Ga2_ObjFindLit( p, pLeaf, f );
                assert( Lit == -1 );
                Lit = Ga2_ObjFindOrAddLit( p, pLeaf, f );
            }
            assert( Lit >= 0 );
            Lit = Abc_LitNotCond( Lit, uTruth == 0x55555555 );
            Ga2_ObjAddLit( p, pObj, f, Lit );
        }
        else
        {
            assert( Vec_IntSize(p->vLits) > 1 && Vec_IntSize(p->vLits) < 6 );
            // replace literals
            Vec_IntForEachEntry( p->vLits, Lit, i )
            {
                if ( Lit >= GA2_BIG_NUM )
                {
                    pLeaf = Gia_ManObj( p->pGia, Vec_IntEntry(vLeaves, Lit-GA2_BIG_NUM) );
                    Lit = Ga2_ObjFindLit( p, pLeaf, f );
                    assert( Lit == -1 );
                    Lit = Ga2_ObjFindOrAddLit( p, pLeaf, f );
                    Vec_IntWriteEntry( p->vLits, i, Lit );
                }
            }
            // perform structural hashing here!!!


            // add new nodes
            Lit = Ga2_ObjFindOrAddLit(p, pObj, f);
            if ( Vec_IntSize(p->vLits) == 5 )
                Ga2_ManCnfAddStatic( p, Ga2_ObjCnf0(p, pObj), Ga2_ObjCnf1(p, pObj), pLits, Lit, -1 );
            else
                Ga2_ManCnfAddDynamic( p, uTruth & 0xFFFF, Vec_IntArray(p->vLits), Lit, -1 );
        }
861 862 863 864 865
    }
}

void Ga2_ManAddAbsClauses( Ga2_Man_t * p, int f )
{
866
    int fSimple = 0;
867
    Gia_Obj_t * pObj;
868
    int i;
869 870 871 872 873
    // add variables for the leaves
    Gia_ManForEachObjVec( p->vValues, p->pGia, pObj, i )
    {
        if ( i == p->LimAbs )
            break;
874 875 876 877
        if ( fSimple )
            Ga2_ManAddToAbsOneStatic( p, pObj, f );
        else
            Ga2_ManAddToAbsOneDynamic( p, pObj, f );
878
    }
879 880 881 882 883
    Gia_ManForEachObjVec( p->vAbs, p->pGia, pObj, i )
        if ( i >= p->LimAbs )
            Ga2_ManAddToAbsOneStatic( p, pObj, f );
}

884
void Ga2_ManAddToAbs( Ga2_Man_t * p, Vec_Int_t * vToAdd )
885
{
886
    Vec_Int_t * vLeaves;
887
    Gia_Obj_t * pObj, * pFanin;
888
    int f, i, k;
889
    // add abstraction objects
890 891
    Gia_ManForEachObjVec( vToAdd, p->pGia, pObj, i )
    {
892 893 894
        Ga2_ManSetupNode( p, pObj, 1 );
        if ( p->pSat->pPrf2 )
            Vec_IntWriteEntry( p->vProofIds, Gia_ObjId(p->pGia, pObj), p->nProofIds++ );
895
    }
896 897 898
    // add PPI objects
    Gia_ManForEachObjVec( vToAdd, p->pGia, pObj, i )
    {
899 900
        vLeaves = Ga2_ObjLeaves( p->pGia, pObj );
        Gia_ManForEachObjVec( vLeaves, p->pGia, pFanin, k )
901
            if ( Ga2_ObjId( p, pFanin ) == -1 )
902
                Ga2_ManSetupNode( p, pFanin, 0 );
903
    }
904
    // add new clauses to the timeframes
905
    for ( f = 0; f <= p->pPars->iFrame; f++ )
906 907
    {
        Vec_IntFillExtra( Ga2_MapFrameMap(p, f), Vec_IntSize(p->vValues), -1 );
908 909
        Gia_ManForEachObjVec( vToAdd, p->pGia, pObj, i )
            Ga2_ManAddToAbsOneStatic( p, pObj, f );
910
    }
911 912
}

913
void Ga2_ManShrinkAbs( Ga2_Man_t * p, int nAbs, int nValues, int nSatVars )
914
{
915
    Vec_Int_t * vMap;
916
    Gia_Obj_t * pObj;
917
    int i;
918
    assert( nAbs > 0 );
919
    assert( nValues > 0 );
920
    assert( nSatVars > 0 );
921
    // shrink abstraction
922 923
    Gia_ManForEachObjVec( p->vAbs, p->pGia, pObj, i )
    {
924
        if ( !i ) continue;
925 926 927 928 929 930
        assert( Ga2_ObjCnf0(p, pObj) != NULL );
        assert( Ga2_ObjCnf1(p, pObj) != NULL );
        if ( i < nAbs )
            continue;
        Vec_IntFree( Ga2_ObjCnf0(p, pObj) );
        Vec_IntFree( Ga2_ObjCnf1(p, pObj) );
931 932
        Vec_PtrWriteEntry( p->vCnfs, 2 * Ga2_ObjId(p,pObj),     NULL );    
        Vec_PtrWriteEntry( p->vCnfs, 2 * Ga2_ObjId(p,pObj) + 1, NULL );
933 934 935 936 937
    }
    Vec_IntShrink( p->vAbs, nAbs );
    // shrink values
    Gia_ManForEachObjVec( p->vValues, p->pGia, pObj, i )
    {
938
        assert( Ga2_ObjId(p,pObj) >= 0 );
939
        if ( i < nValues )
940
            continue;
941
        Ga2_ObjSetId( p, pObj, -1 );
942
    }
943
    Vec_IntShrink( p->vValues, nValues );
944
    Vec_PtrShrink( p->vCnfs, 2 * nValues );
945
    // clean mapping for each timeframe
946
    Vec_PtrForEachEntry( Vec_Int_t *, p->vId2Lit, vMap, i )
947 948 949
        Vec_IntClear( vMap );
    // shrink SAT variables
    p->nSatVars = nSatVars;
950 951 952 953 954 955 956 957 958 959 960 961 962
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
963 964 965 966 967 968 969 970 971
void Ga2_ManAbsTranslate_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vClasses, int fFirst )
{
    if ( pObj->fPhase && !fFirst )
        return;
    assert( Gia_ObjIsAnd(pObj) );
    Ga2_ManAbsTranslate_rec( p, Gia_ObjFanin0(pObj), vClasses, 0 );
    Ga2_ManAbsTranslate_rec( p, Gia_ObjFanin1(pObj), vClasses, 0 );
    Vec_IntWriteEntry( vClasses, Gia_ObjId(p, pObj), 1 );
}
972

973 974 975 976 977 978
Vec_Int_t * Ga2_ManAbsTranslate( Ga2_Man_t * p )
{
    Vec_Int_t * vGateClasses;
    Gia_Obj_t * pObj;
    int i;
    vGateClasses = Vec_IntStart( Gia_ManObjNum(p->pGia) );
979
    Vec_IntWriteEntry( vGateClasses, 0, 1 );
980
    Gia_ManForEachObjVec( p->vAbs, p->pGia, pObj, i )
981
    {
982 983 984
        if ( Gia_ObjIsAnd(pObj) )
            Ga2_ManAbsTranslate_rec( p->pGia, pObj, vGateClasses, 1 );
        else if ( Gia_ObjIsRo(p->pGia, pObj) )
985 986 987
            Vec_IntWriteEntry( vGateClasses, Gia_ObjId(p->pGia, pObj), 1 );
        else if ( !Gia_ObjIsConst0(pObj) )
            assert( 0 );
988
//        Gia_ObjPrint( p->pGia, pObj );
989
    }
990 991
    return vGateClasses;
}
992

993
Vec_Int_t * Ga2_ManAbsDerive( Gia_Man_t * p )
994
{
995
    Vec_Int_t * vToAdd;
996
    Gia_Obj_t * pObj;
997 998
    int i;
    vToAdd = Vec_IntAlloc( 1000 );
999
    Gia_ManForEachRo( p, pObj, i )
1000 1001
        if ( pObj->fPhase && Vec_IntEntry(p->vGateClasses, Gia_ObjId(p, pObj)) )
            Vec_IntPush( vToAdd, Gia_ObjId(p, pObj) );
1002
    Gia_ManForEachAnd( p, pObj, i )
1003 1004 1005 1006 1007 1008 1009 1010
        if ( pObj->fPhase && Vec_IntEntry(p->vGateClasses, i) )
            Vec_IntPush( vToAdd, i );
    return vToAdd;
}

void Ga2_ManRestart( Ga2_Man_t * p )
{
    Vec_Int_t * vToAdd;
1011
    int Lit = 1;
1012
    assert( p->pGia != NULL && p->pGia->vGateClasses != NULL );
1013 1014 1015 1016
    assert( Gia_ManPi(p->pGia, 0)->fPhase ); // marks are set
    // clear SAT variable numbers (begin with 1)
    if ( p->pSat ) sat_solver2_delete( p->pSat );
    p->pSat      = sat_solver2_new();
1017
    // add clause x0 = 0  (lit0 = 1; lit1 = 0)
1018
    sat_solver2_addclause( p->pSat, &Lit, &Lit + 1, -1 );
1019 1020 1021
    // remove previous abstraction
    Ga2_ManShrinkAbs( p, 1, 1, 1 );
    // start new abstraction
1022
    vToAdd = Ga2_ManAbsDerive( p->pGia );
1023 1024
    assert( p->pSat->pPrf2 == NULL );
    assert( p->pPars->iFrame < 0 );
1025
    Ga2_ManAddToAbs( p, vToAdd );
1026
    Vec_IntFree( vToAdd );
1027
    p->LimAbs = Vec_IntSize(p->vAbs);
1028
    p->LimPpi = Vec_IntSize(p->vValues);
1029 1030 1031 1032 1033 1034 1035
    // set runtime limit
    if ( p->pPars->nTimeOut )
        sat_solver2_set_runtime_limit( p->pSat, p->pPars->nTimeOut * CLOCKS_PER_SEC + p->timeStart );
}

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

1036
  Synopsis    [Unrolls one timeframe.]`
1037 1038 1039 1040 1041 1042 1043 1044

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
1045
/*
1046
int Ga2_ManUnroll_rec( Ga2_Man_t * p, Gia_Obj_t * pObj, int f )
1047
{
1048
    int fSimple = 1;
1049
    int Id = Gia_ObjId(p->pGia, pObj);
1050
    unsigned uTruth;
1051 1052 1053 1054
    Gia_Obj_t * pLeaf;
    int nLeaves, * pLeaves;
    int i, Lit, pLits[5];
    if ( Gia_ObjIsConst0(pObj) || (f==0 && Gia_ObjIsRo(p->pGia, pObj)) )
1055 1056 1057 1058 1059 1060
    {
        if ( fSimple )
        {
            Lit = Ga2_ObjFindOrAddLit( p, pObj, f );
            Lit = Abc_LitNot(Lit);
            assert( Lit > 1 );
1061 1062
            sat_solver2_addclause( p->pSat, &Lit, &Lit + 1, -1 );
            return Abc_LitNot(Lit);
1063
        }
1064
        return 0;
1065
    }
1066 1067
    if ( Gia_ObjIsCo(pObj) )
        return Abc_LitNotCond( Ga2_ManUnroll_rec(p, Gia_ObjFanin0(pObj), f), Gia_ObjFaninC0(pObj) );
1068
    assert( pObj->fPhase );
1069
    if ( Ga2_ObjIsLeaf0(p, pObj) )
1070
        return Ga2_ObjFindOrAddLit( p, pObj, f );
1071
    assert( !Gia_ObjIsPi(p->pGia, pObj) );
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
    Lit = Ga2_ObjFindLit( p, pObj, f );
    if ( Lit >= 0 )
        return Lit;
    if ( Gia_ObjIsRo(p->pGia, pObj) )
    {
        assert( f > 0 );
        Lit = Ga2_ManUnroll_rec( p, Gia_ObjRoToRi(p->pGia, pObj), f-1 );
        Ga2_ObjAddLit( p, pObj, f, Lit );
        return Lit;
    }
1082
    assert( Gia_ObjIsAnd(pObj) );
1083 1084
    nLeaves = Ga2_ObjLeaveNum( p->pGia, pObj );
    pLeaves = Ga2_ObjLeavePtr( p->pGia, pObj );
1085 1086 1087
    if ( fSimple )
    {
        // collect fanin literals
1088 1089 1090
        for ( i = 0; i < nLeaves; i++ )
        {
            pLeaf = Gia_ManObj(p->pGia, pLeaves[i]);
1091
            pLits[i] = Ga2_ManUnroll_rec( p, pLeaf, f );
1092
        }
1093 1094 1095
        // create fanout literal
        Lit = Ga2_ObjFindOrAddLit( p, pObj, f );
        // create clauses
1096
        Ga2_ManCnfAddStatic( p, Ga2_ObjCnf0(p, pObj), Ga2_ObjCnf1(p, pObj), pLits, Lit, Gia_ObjId(p->pGia, pObj) );
1097 1098
        return Lit;
    }
1099 1100 1101 1102
    // collect fanin literals
    for ( i = 0; i < nLeaves; i++ )
    {
        pLeaf = Gia_ManObj( p->pGia, pLeaves[i] );
1103
        if ( Ga2_ObjIsAbs0(p, pLeaf) )      // belongs to original abstraction
1104
            pLits[i] = Ga2_ManUnroll_rec( p, pLeaf, f );
1105
        else if ( Ga2_ObjIsLeaf0(p, pLeaf) ) // belongs to original PPIs
1106
            pLits[i] = GA2_BIG_NUM + i;
1107
        else assert( 0 );
1108 1109 1110 1111 1112 1113
    }
    // collect literals
    Vec_IntClear( p->vLits );
    for ( i = 0; i < nLeaves; i++ )
        Vec_IntPush( p->vLits, pLits[i] );
    // minimize truth table
1114 1115
    uTruth = Ga2_ObjComputeTruthSpecial( p->pGia, pObj, Ga2_ObjLeaves(p->pGia, pObj), p->vLits );
    if ( uTruth == 0 || uTruth == ~0 ) // const 0 / 1
1116
    {
1117
        Lit = (uTruth > 0);
1118 1119
        Ga2_ObjAddLit( p, pObj, f, Lit );
    }
1120 1121 1122
    else if ( uTruth == 0xAAAAAAAA || uTruth == 0x55555555 )  // buffer / inverter
    {
        Lit = Vec_IntEntry( p->vLits, 0 );
1123
        if ( Lit >= GA2_BIG_NUM )
1124
        {
1125
            pLeaf = Gia_ManObj( p->pGia, pLeaves[Lit-GA2_BIG_NUM] );
1126 1127
            Lit = Ga2_ObjFindOrAddLit( p, pLeaf, f );
        }
1128
        Lit = Abc_LitNotCond( Lit, uTruth == 0x55555555 );
1129
        Ga2_ObjAddLit( p, pObj, f, Lit );
1130
    }
1131
    else
1132
    {
1133 1134 1135 1136
        // perform structural hashing here!!!

        // add new node
        Lit = Ga2_ObjFindOrAddLit(p, pObj, f);
1137
        Ga2_ManCnfAddDynamic( p, uTruth, Vec_IntArray(p->vLits), Lit );
1138
    }
1139
    return Lit;
1140
}
1141
*/
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173
/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Vec_IntCheckUnique( Vec_Int_t * p )
{
    int RetValue;
    Vec_Int_t * pDup = Vec_IntDup( p );
    Vec_IntUniqify( pDup );
    RetValue = Vec_IntSize(p) - Vec_IntSize(pDup);
    Vec_IntFree( pDup );
    return RetValue;
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
1174 1175 1176
static inline int Ga2_ObjSatValue( Ga2_Man_t * p, Gia_Obj_t * pObj, int f )
{
    int Lit = Ga2_ObjFindLit( p, pObj, f );
1177
    assert( !Gia_ObjIsConst0(pObj) );
1178 1179
    if ( Lit == -1 )
        return 0;
1180 1181
    if ( Abc_Lit2Var(Lit) >= p->pSat->size )
        return 0;
1182
    return Abc_LitIsCompl(Lit) ^ sat_solver2_var_value( p->pSat, Abc_Lit2Var(Lit) );
1183 1184 1185 1186 1187 1188
}
void Ga2_GlaPrepareCexAndMap( Ga2_Man_t * p, Abc_Cex_t ** ppCex, Vec_Int_t ** pvMaps )
{
    Abc_Cex_t * pCex;
    Vec_Int_t * vMap;
    Gia_Obj_t * pObj;
1189
    int f, i, k, Id;
1190 1191 1192 1193 1194
/*
    Gia_ManForEachObj( p->pGia, pObj, i )
        if ( Ga2_ObjId(p, pObj) >= 0 )
            assert( Vec_IntEntry(p->vValues, Ga2_ObjId(p, pObj)) == i );
*/
1195 1196
    // find PIs and PPIs
    vMap = Vec_IntAlloc( 1000 );
1197
    Gia_ManForEachObjVec( p->vValues, p->pGia, pObj, i )
1198
    {
1199
        if ( !i ) continue;
1200 1201
        Id = Ga2_ObjId(p, pObj);
        k = Gia_ObjId(p->pGia, pObj);
1202 1203
        if ( Ga2_ObjIsAbs(p, pObj) )
            continue;
1204 1205
        assert( pObj->fPhase );
        assert( Ga2_ObjIsLeaf(p, pObj) );
1206 1207
        assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsCi(pObj) );
        Vec_IntPush( vMap, Gia_ObjId(p->pGia, pObj) );
1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219
    }
    // derive counter-example
    pCex = Abc_CexAlloc( 0, Vec_IntSize(vMap), p->pPars->iFrame+1 );
    pCex->iFrame = p->pPars->iFrame;
    for ( f = 0; f <= p->pPars->iFrame; f++ )
        Gia_ManForEachObjVec( vMap, p->pGia, pObj, k )
            if ( Ga2_ObjSatValue( p, pObj, f ) )
                Abc_InfoSetBit( pCex->pData, f * Vec_IntSize(vMap) + k );
    *pvMaps = vMap;
    *ppCex = pCex;
}
Abc_Cex_t * Ga2_ManDeriveCex( Ga2_Man_t * p, Vec_Int_t * vPis )
1220
{
1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241
    Abc_Cex_t * pCex;
    Gia_Obj_t * pObj;
    int i, f;
    pCex = Abc_CexAlloc( Gia_ManRegNum(p->pGia), Gia_ManPiNum(p->pGia), p->pPars->iFrame+1 );
    pCex->iPo = 0;
    pCex->iFrame = p->pPars->iFrame;
    Gia_ManForEachObjVec( vPis, p->pGia, pObj, i )
    {
        if ( !Gia_ObjIsPi(p->pGia, pObj) )
            continue;
        assert( Gia_ObjIsPi(p->pGia, pObj) );
        for ( f = 0; f <= pCex->iFrame; f++ )
            if ( Ga2_ObjSatValue( p, pObj, f ) )
                Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + Gia_ObjCioId(pObj) );
    }
    return pCex;
}
Vec_Int_t * Ga2_ManRefine( Ga2_Man_t * p )
{
    Abc_Cex_t * pCex;
    Vec_Int_t * vMap, * vVec;
1242 1243
    Gia_Obj_t * pObj;
    int i;
1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255
    Ga2_GlaPrepareCexAndMap( p, &pCex, &vMap );
    vVec = Rnm_ManRefine( p->pRnm, pCex, vMap, p->pPars->fPropFanout, 1 );
    Abc_CexFree( pCex );
    if ( Vec_IntSize(vVec) == 0 )
    {
        Vec_IntFree( vVec );
        Abc_CexFreeP( &p->pGia->pCexSeq );
        p->pGia->pCexSeq = Ga2_ManDeriveCex( p, vMap );
        Vec_IntFree( vMap );
        return NULL;
    }
    Vec_IntFree( vMap );
1256 1257
    // these objects should be PPIs that are not abstracted yet
    Gia_ManForEachObjVec( vVec, p->pGia, pObj, i )
1258
        assert( pObj->fPhase && Ga2_ObjIsLeaf(p, pObj) );
1259 1260
    p->nObjAdded += Vec_IntSize(vVec);
    return vVec;
1261 1262 1263 1264
}

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

1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318
  Synopsis    [Creates a new manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Ga2_GlaAbsCount( Ga2_Man_t * p, int fRo, int fAnd )
{
    Gia_Obj_t * pObj;
    int i, Counter = 0;
    if ( fRo )
        Gia_ManForEachObjVec( p->vAbs, p->pGia, pObj, i )
            Counter += Gia_ObjIsRo(p->pGia, pObj);
    else if ( fAnd )
        Gia_ManForEachObjVec( p->vAbs, p->pGia, pObj, i )
            Counter += Gia_ObjIsAnd(pObj);
    else assert( 0 );
    return Counter;
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Ga2_ManAbsPrintFrame( Ga2_Man_t * p, int nFrames, int nConfls, int nCexes, clock_t Time, int fFinal )
{
    if ( Abc_FrameIsBatchMode() && !fFinal )
        return;
    Abc_Print( 1, "%4d :", nFrames );
    Abc_Print( 1, "%4d", Abc_MinInt(100, 100 * Vec_IntSize(p->vAbs) / p->nMarked) ); 
    Abc_Print( 1, "%6d", Vec_IntSize(p->vAbs) );
    Abc_Print( 1, "%5d", Vec_IntSize(p->vValues)-Vec_IntSize(p->vAbs)-1 );
    Abc_Print( 1, "%5d", Ga2_GlaAbsCount(p, 1, 0) );
    Abc_Print( 1, "%6d", Ga2_GlaAbsCount(p, 0, 1) );
    Abc_Print( 1, "%8d", nConfls );
    if ( nCexes == 0 )
        Abc_Print( 1, "%5c", '-' ); 
    else
        Abc_Print( 1, "%5d", nCexes ); 
    Abc_PrintInt( sat_solver2_nvars(p->pSat) );
    Abc_PrintInt( sat_solver2_nclauses(p->pSat) );
    Abc_PrintInt( sat_solver2_nlearnts(p->pSat) );
    Abc_Print( 1, "%9.2f sec", 1.0*Time/CLOCKS_PER_SEC );
    Abc_Print( 1, "%5.1f GB", (sat_solver2_memory_proof(p->pSat) + sat_solver2_memory(p->pSat, 0)) / (1<<30) );
1319
    Abc_Print( 1, "%s", (fFinal && nCexes) ? "\n" : "\r" );
1320 1321 1322 1323 1324
    fflush( stdout );
}

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

1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335
  Synopsis    [Performs gate-level abstraction.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Ga2_ManPerform( Gia_Man_t * pAig, Gia_ParVta_t * pPars )
{
1336
    Ga2_Man_t * p;
1337
    Vec_Int_t * vCore, * vPPis;
1338
    clock_t clk2, clk = clock();
1339
    int Status, RetValue = -1;
1340
    int i, c, f, Lit;
1341
    // check trivial case 
1342
    assert( Gia_ManPoNum(pAig) == 1 ); 
1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362
    ABC_FREE( pAig->pCexSeq );
    if ( Gia_ObjIsConst0(Gia_ObjFanin0(Gia_ManPo(pAig,0))) )
    {
        if ( !Gia_ObjFaninC0(Gia_ManPo(pAig,0)) )
        {
            printf( "Sequential miter is trivially UNSAT.\n" );
            return 1;
        }
        pAig->pCexSeq = Abc_CexMakeTriv( Gia_ManRegNum(pAig), Gia_ManPiNum(pAig), 1, 0 );
        printf( "Sequential miter is trivially SAT.\n" );
        return 0;
    }
    // create gate classes if not given
    if ( pAig->vGateClasses == NULL )
    {
        pAig->vGateClasses = Vec_IntStart( Gia_ManObjNum(pAig) );
        Vec_IntWriteEntry( pAig->vGateClasses, 0, 1 );
        Vec_IntWriteEntry( pAig->vGateClasses, Gia_ObjFaninId0p(pAig, Gia_ManPo(pAig, 0)), 1 );
    }
    // start the manager
1363
    p = Ga2_ManStart( pAig, pPars );
1364 1365 1366 1367 1368 1369 1370 1371 1372
    p->timeInit = clock() - clk;
    // perform initial abstraction
    if ( p->pPars->fVerbose )
    {
        Abc_Print( 1, "Running gate-level abstraction (GLA) with the following parameters:\n" );
        Abc_Print( 1, "FrameMax = %d  ConfMax = %d  Timeout = %d  RatioMin = %d %%.\n", 
            pPars->nFramesMax, pPars->nConfLimit, pPars->nTimeOut, pPars->nRatioMin );
        Abc_Print( 1, "LearnStart = %d  LearnDelta = %d  LearnRatio = %d %%.\n", 
            pPars->nLearnedStart, pPars->nLearnedDelta, pPars->nLearnedPerce );
1373
        Abc_Print( 1, " Frame   %%   Abs  PPI   FF   LUT   Confl  Cex   Vars   Clas   Lrns     Time      Mem\n" );
1374 1375 1376 1377
    }
    // iterate unrolling
    for ( i = f = 0; !pPars->nFramesMax || f < pPars->nFramesMax; i++ )
    {
1378 1379
        // remember the timeframe
        p->pPars->iFrame = -1;
1380 1381 1382 1383 1384
        // create new SAT solver
        Ga2_ManRestart( p );
        // unroll the circuit
        for ( f = 0; !pPars->nFramesMax || f < pPars->nFramesMax; f++ )
        {
1385
            // remember current limits
1386
            int nConflsBeg = sat_solver2_nconflicts(p->pSat);
1387 1388 1389 1390 1391 1392 1393 1394
            int nAbs       = Vec_IntSize(p->vAbs);
            int nValues    = Vec_IntSize(p->vValues);
            int nVarsOld;
            // extend and clear storage
            if ( f == Vec_PtrSize(p->vId2Lit) )
                Vec_PtrPush( p->vId2Lit, Vec_IntAlloc(0) );
            Vec_IntFillExtra( Ga2_MapFrameMap(p, f), Vec_IntSize(p->vValues), -1 );
            // remember the timeframe
1395
            p->pPars->iFrame = f;
1396
            // add static clauses to this timeframe
1397
            Ga2_ManAddAbsClauses( p, f );
1398
            // get the output literal
1399 1400 1401 1402
//            Lit = Ga2_ManUnroll_rec( p, Gia_ManPo(pAig,0), f );
            Lit = Ga2_ObjFindLit( p, Gia_ObjFanin0(Gia_ManPo(pAig,0)), f );
            assert( Lit >= 0 );
            Lit = Abc_LitNotCond( Lit, Gia_ObjFaninC0(Gia_ManPo(pAig,0)) );
1403 1404 1405
            if ( Lit == 0 )
                continue;
            assert( Lit > 1 );
1406
            // check for counter-examples
1407
            sat_solver2_setnvars( p->pSat, p->nSatVars );
1408
            nVarsOld = p->nSatVars;
1409 1410 1411
            for ( c = 0; ; c++ )
            {
                // perform SAT solving
1412
                clk2 = clock();
1413
                Status = sat_solver2_solve( p->pSat, &Lit, &Lit+1, (ABC_INT64_T)pPars->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
1414 1415
                if ( Status == l_True ) // perform refinement
                {
1416 1417 1418
                    p->timeSat += clock() - clk2;

                    clk2 = clock();
1419
                    vPPis = Ga2_ManRefine( p );
1420
                    p->timeCex += clock() - clk2;
1421
                    if ( vPPis == NULL )
1422 1423 1424
                    {
                        if ( pPars->fVerbose )
                            Ga2_ManAbsPrintFrame( p, f, sat_solver2_nconflicts(p->pSat)-nConflsBeg, c, clock() - clk, 1 );
1425
                        goto finish;
1426
                    }
1427 1428 1429

                    if ( c == 0 )
                    {
1430 1431 1432
                        // create bookmark to be used for rollback
                        assert( nVarsOld == p->pSat->size );
                        sat_solver2_bookmark( p->pSat );
1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450
                        // start incremental proof manager
                        assert( p->pSat->pPrf2 == NULL );
                        p->pSat->pPrf2 = Prf_ManAlloc();
                        if ( p->pSat->pPrf2 )
                        {
                            p->nProofIds = 0;
                            Vec_IntFill( p->vProofIds, Gia_ManObjNum(p->pGia), -1 );
                            Prf_ManRestart( p->pSat->pPrf2, p->vProofIds, sat_solver2_nlearnts(p->pSat), Vec_IntSize(vPPis) );
                        }
                    }
                    else
                    {
                        // resize the proof logger
                        if ( p->pSat->pPrf2 )
                            Prf_ManGrow( p->pSat->pPrf2, p->nProofIds + Vec_IntSize(vPPis) );
                    }

                    Ga2_ManAddToAbs( p, vPPis );
1451
                    Vec_IntFree( vPPis );
1452
                    if ( pPars->fVerbose )
1453
                        Ga2_ManAbsPrintFrame( p, f, sat_solver2_nconflicts(p->pSat)-nConflsBeg, c+1, clock() - clk, 0 );
1454
                    // verify
1455 1456 1457 1458
                    if ( Vec_IntCheckUnique(p->vAbs) )
                        printf( "Vector has %d duplicated entries.\n", Vec_IntCheckUnique(p->vAbs) );
                    continue;
                }
1459
                p->timeUnsat += clock() - clk2;
1460 1461
                if ( Status == l_Undef ) // ran out of resources
                    goto finish;
1462 1463
                if ( p->pSat->nRuntimeLimit && clock() > p->pSat->nRuntimeLimit ) // timeout
                    goto finish;
1464
                assert( RetValue == l_False );
1465 1466
                if ( c == 0 )
                    break;
1467 1468 1469

                // derive the core
                assert( p->pSat->pPrf2 != NULL );
1470
                vCore = (Vec_Int_t *)Sat_ProofCore( p->pSat );
1471
                Prf_ManStopP( &p->pSat->pPrf2 );
1472 1473 1474 1475
                // update the SAT solver
                sat_solver2_rollback( p->pSat );
                // reduce abstraction
                Ga2_ManShrinkAbs( p, nAbs, nValues, nVarsOld );
1476
                Ga2_ManAddToAbs( p, vCore );
1477
                Vec_IntFree( vCore );
1478
                // verify
1479 1480 1481 1482
                if ( Vec_IntCheckUnique(p->vAbs) )
                    printf( "Vector has %d duplicated entries.\n", Vec_IntCheckUnique(p->vAbs) );
                break;
            }
1483 1484
            if ( pPars->fVerbose )
                Ga2_ManAbsPrintFrame( p, f, sat_solver2_nconflicts(p->pSat)-nConflsBeg, c, clock() - clk, 1 );
1485 1486 1487
            if ( c > 0 )
            {
                Vec_IntFreeP( &pAig->vGateClasses );
1488
                pAig->vGateClasses = Ga2_ManAbsTranslate( p );
1489
//                printf( "\n" );
1490
                break;  // temporary
1491 1492 1493
            }
        }
        // check if the number of objects is below limit
1494
        if ( Vec_IntSize(p->vAbs) >= p->nMarked * (100 - pPars->nRatioMin) / 100 )
1495 1496 1497 1498 1499 1500
        {
            Status = l_Undef;
            break;
        }
    }
finish:
1501
    Prf_ManStopP( &p->pSat->pPrf2 );
1502 1503 1504 1505 1506 1507
    // analize the results
    if ( pAig->pCexSeq == NULL )
    {
        if ( pAig->vGateClasses != NULL )
            Abc_Print( 1, "Replacing the old abstraction by a new one.\n" );
        Vec_IntFreeP( &pAig->vGateClasses );
1508
        pAig->vGateClasses = Ga2_ManAbsTranslate( p );
1509 1510 1511 1512 1513 1514
        if ( Status == l_Undef )
        {
            if ( p->pPars->nTimeOut && clock() >= p->pSat->nRuntimeLimit ) 
                Abc_Print( 1, "SAT solver ran out of time at %d sec in frame %d.  ", p->pPars->nTimeOut, f );
            else if ( pPars->nConfLimit && sat_solver2_nconflicts(p->pSat) >= pPars->nConfLimit )
                Abc_Print( 1, "SAT solver ran out of resources at %d conflicts in frame %d.  ", pPars->nConfLimit, f );
1515
            else if ( Vec_IntSize(p->vAbs) >= p->nMarked * (100 - pPars->nRatioMin) / 100 )
1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530
                Abc_Print( 1, "The ratio of abstracted objects is less than %d %% in frame %d.  ", pPars->nRatioMin, f );
            else
                Abc_Print( 1, "Abstraction stopped for unknown reason in frame %d.  ", f );
        }
        else
        {
            p->pPars->iFrame++;
            Abc_Print( 1, "SAT solver completed %d frames and produced an abstraction.  ", f );
        }
    }
    else
    {
        if ( !Gia_ManVerifyCex( pAig, pAig->pCexSeq, 0 ) )
            Abc_Print( 1, "    Gia_GlaPerform(): CEX verification has failed!\n" );
        Abc_Print( 1, "Counter-example detected in frame %d.  ", f );
1531
        p->pPars->iFrame = pAig->pCexSeq->iFrame - 1;
1532
        Vec_IntFreeP( &pAig->vGateClasses );
1533
        RetValue = 0;
1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544
    }
    Abc_PrintTime( 1, "Time", clock() - clk );
    if ( p->pPars->fVerbose )
    {
        p->timeOther = (clock() - clk) - p->timeUnsat - p->timeSat - p->timeCex - p->timeInit;
        ABC_PRTP( "Runtime: Initializing", p->timeInit,   clock() - clk );
        ABC_PRTP( "Runtime: Solver UNSAT", p->timeUnsat,  clock() - clk );
        ABC_PRTP( "Runtime: Solver SAT  ", p->timeSat,    clock() - clk );
        ABC_PRTP( "Runtime: Refinement  ", p->timeCex,    clock() - clk );
        ABC_PRTP( "Runtime: Other       ", p->timeOther,  clock() - clk );
        ABC_PRTP( "Runtime: TOTAL       ", clock() - clk, clock() - clk );
1545
        Ga2_ManReportMemory( p );
1546
    }
1547
    Ga2_ManStop( p );
1548 1549
    fflush( stdout );
    return RetValue;
1550
}
1551 1552 1553 1554 1555 1556 1557 1558

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


ABC_NAMESPACE_IMPL_END