fraInd.c 25.6 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    [fraInd.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [New FRAIG package.]

  Synopsis    [Inductive prover.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

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

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

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

#include "fra.h"
22 23 24
#include "sat/cnf/cnf.h"
#include "opt/dar/dar.h"
#include "aig/saig/saig.h"
25 26 27

ABC_NAMESPACE_IMPL_START

Alan Mishchenko committed
28 29 30 31 32 33 34 35 36 37 38

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

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

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

Alan Mishchenko committed
39
  Synopsis    [Performs AIG rewriting on the constraint manager.]
Alan Mishchenko committed
40 41 42 43 44 45 46 47 48 49 50 51

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Fra_FraigInductionRewrite( Fra_Man_t * p )
{
    Aig_Man_t * pTemp;
    Aig_Obj_t * pObj, * pObjPo;
52
    int nTruePis, k, i;
53
    abctime clk = Abc_Clock();
Alan Mishchenko committed
54 55
    // perform AIG rewriting on the speculated frames
//    pTemp = Dar_ManRwsat( pTemp, 1, 0 );
Alan Mishchenko committed
56
    pTemp = Dar_ManRewriteDefault( p->pManFraig );
Alan Mishchenko committed
57
//    printf( "Before = %6d.  After = %6d.\n", Aig_ManNodeNum(p->pManFraig), Aig_ManNodeNum(pTemp) ); 
Alan Mishchenko committed
58 59
//Aig_ManDumpBlif( p->pManFraig, "1.blif", NULL, NULL );
//Aig_ManDumpBlif( pTemp, "2.blif", NULL, NULL );
Alan Mishchenko committed
60 61 62 63 64
//    Fra_FramesWriteCone( pTemp );
//    Aig_ManStop( pTemp );
    // transfer PI/register pointers
    assert( p->pManFraig->nRegs == pTemp->nRegs );
    assert( p->pManFraig->nAsserts == pTemp->nAsserts );
65
    nTruePis = Aig_ManCiNum(p->pManAig) - Aig_ManRegNum(p->pManAig);
Alan Mishchenko committed
66 67 68
    memset( p->pMemFraig, 0, sizeof(Aig_Obj_t *) * p->nSizeAlloc * p->nFramesAll );
    Fra_ObjSetFraig( Aig_ManConst1(p->pManAig), p->pPars->nFramesK, Aig_ManConst1(pTemp) );
    Aig_ManForEachPiSeq( p->pManAig, pObj, i )
69
        Fra_ObjSetFraig( pObj, p->pPars->nFramesK, Aig_ManCi(pTemp,nTruePis*p->pPars->nFramesK+i) );
Alan Mishchenko committed
70
    k = 0;
71
    assert( Aig_ManRegNum(p->pManAig) == Aig_ManCoNum(pTemp) - pTemp->nAsserts );
Alan Mishchenko committed
72 73
    Aig_ManForEachLoSeq( p->pManAig, pObj, i )
    {
74
        pObjPo = Aig_ManCo(pTemp, pTemp->nAsserts + k++);
Alan Mishchenko committed
75 76 77 78 79
        Fra_ObjSetFraig( pObj, p->pPars->nFramesK, Aig_ObjChild0(pObjPo) );
    }
    // exchange
    Aig_ManStop( p->pManFraig );
    p->pManFraig = pTemp;
80
p->timeRwr += Abc_Clock() - clk;
Alan Mishchenko committed
81 82 83 84
}

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

Alan Mishchenko committed
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
  Synopsis    [Performs speculative reduction for one node.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline void Fra_FramesConstrainNode( Aig_Man_t * pManFraig, Aig_Obj_t * pObj, int iFrame )
{
    Aig_Obj_t * pObjNew, * pObjNew2, * pObjRepr, * pObjReprNew, * pMiter;
    // skip nodes without representative
    if ( (pObjRepr = Fra_ClassObjRepr(pObj)) == NULL )
        return;
    assert( pObjRepr->Id < pObj->Id );
    // get the new node 
    pObjNew = Fra_ObjFraig( pObj, iFrame );
    // get the new node of the representative
    pObjReprNew = Fra_ObjFraig( pObjRepr, iFrame );
    // if this is the same node, no need to add constraints
    if ( Aig_Regular(pObjNew) == Aig_Regular(pObjReprNew) )
        return;
    // these are different nodes - perform speculative reduction
    pObjNew2 = Aig_NotCond( pObjReprNew, pObj->fPhase ^ pObjRepr->fPhase );
    // set the new node
    Fra_ObjSetFraig( pObj, iFrame, pObjNew2 );
    // add the constraint
Alan Mishchenko committed
113 114 115
    pMiter = Aig_Exor( pManFraig, pObjNew, pObjReprNew );
    pMiter = Aig_NotCond( pMiter, !Aig_ObjPhaseReal(pMiter) );
    assert( Aig_ObjPhaseReal(pMiter) == 1 );
116
    Aig_ObjCreateCo( pManFraig, pMiter );
Alan Mishchenko committed
117 118 119 120
}

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

Alan Mishchenko committed
121 122 123 124 125 126 127 128 129 130 131 132
  Synopsis    [Prepares the inductive case with speculative reduction.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Aig_Man_t * Fra_FramesWithClasses( Fra_Man_t * p )
{
    Aig_Man_t * pManFraig;
Alan Mishchenko committed
133
    Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew;
Alan Mishchenko committed
134 135
    int i, k, f;
    assert( p->pManFraig == NULL );
Alan Mishchenko committed
136
    assert( Aig_ManRegNum(p->pManAig) > 0 );
137
    assert( Aig_ManRegNum(p->pManAig) < Aig_ManCiNum(p->pManAig) );
Alan Mishchenko committed
138 139

    // start the fraig package
Alan Mishchenko committed
140
    pManFraig = Aig_ManStart( Aig_ManObjNumMax(p->pManAig) * p->nFramesAll );
141 142
    pManFraig->pName = Abc_UtilStrsav( p->pManAig->pName );
    pManFraig->pSpec = Abc_UtilStrsav( p->pManAig->pSpec );
Alan Mishchenko committed
143
    pManFraig->nRegs = p->pManAig->nRegs;
Alan Mishchenko committed
144
    // create PI nodes for the frames
Alan Mishchenko committed
145
    for ( f = 0; f < p->nFramesAll; f++ )
Alan Mishchenko committed
146
        Fra_ObjSetFraig( Aig_ManConst1(p->pManAig), f, Aig_ManConst1(pManFraig) );
Alan Mishchenko committed
147
    for ( f = 0; f < p->nFramesAll; f++ )
Alan Mishchenko committed
148
        Aig_ManForEachPiSeq( p->pManAig, pObj, i )
149
            Fra_ObjSetFraig( pObj, f, Aig_ObjCreateCi(pManFraig) );
Alan Mishchenko committed
150 151
    // create latches for the first frame
    Aig_ManForEachLoSeq( p->pManAig, pObj, i )
152
        Fra_ObjSetFraig( pObj, 0, Aig_ObjCreateCi(pManFraig) );
Alan Mishchenko committed
153 154

    // add timeframes
Alan Mishchenko committed
155
//    pManFraig->fAddStrash = 1;
Alan Mishchenko committed
156
    for ( f = 0; f < p->nFramesAll - 1; f++ )
Alan Mishchenko committed
157
    {
Alan Mishchenko committed
158 159 160
        // set the constraints on the latch outputs
        Aig_ManForEachLoSeq( p->pManAig, pObj, i )
            Fra_FramesConstrainNode( pManFraig, pObj, f );
Alan Mishchenko committed
161 162 163 164 165
        // add internal nodes of this frame
        Aig_ManForEachNode( p->pManAig, pObj, i )
        {
            pObjNew = Aig_And( pManFraig, Fra_ObjChild0Fra(pObj,f), Fra_ObjChild1Fra(pObj,f) );
            Fra_ObjSetFraig( pObj, f, pObjNew );
Alan Mishchenko committed
166
            Fra_FramesConstrainNode( pManFraig, pObj, f );
Alan Mishchenko committed
167
        }
Alan Mishchenko committed
168 169 170
        // transfer latch input to the latch outputs 
        Aig_ManForEachLiLoSeq( p->pManAig, pObjLi, pObjLo, k )
            Fra_ObjSetFraig( pObjLo, f+1, Fra_ObjChild0Fra(pObjLi,f) );
Alan Mishchenko committed
171
    }
Alan Mishchenko committed
172
//    pManFraig->fAddStrash = 0;
Alan Mishchenko committed
173
    // mark the asserts
174
    pManFraig->nAsserts = Aig_ManCoNum(pManFraig);
Alan Mishchenko committed
175 176
    // add the POs for the latch outputs of the last frame
    Aig_ManForEachLoSeq( p->pManAig, pObj, i )
177
        Aig_ObjCreateCo( pManFraig, Fra_ObjFraig(pObj,p->nFramesAll-1) );
Alan Mishchenko committed
178

Alan Mishchenko committed
179 180
    // remove dangling nodes
    Aig_ManCleanup( pManFraig );
Alan Mishchenko committed
181 182 183 184 185 186 187
    // make sure the satisfying assignment is node assigned
    assert( pManFraig->pData == NULL );
    return pManFraig;
}

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

Alan Mishchenko committed
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
  Synopsis    [Prepares the inductive case with speculative reduction.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Fra_FramesAddMore( Aig_Man_t * p, int nFrames )
{
    Aig_Obj_t * pObj, ** pLatches;
    int i, k, f, nNodesOld;
    // set copy pointer of each object to point to itself
    Aig_ManForEachObj( p, pObj, i )
        pObj->pData = pObj;
    // iterate and add objects
Alan Mishchenko committed
205
    nNodesOld = Aig_ManObjNumMax(p);
Alan Mishchenko committed
206
    pLatches = ABC_ALLOC( Aig_Obj_t *, Aig_ManRegNum(p) );
Alan Mishchenko committed
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 234 235 236 237
    for ( f = 0; f < nFrames; f++ )
    {
        // clean latch inputs and outputs
        Aig_ManForEachLiSeq( p, pObj, i )
            pObj->pData = NULL;
        Aig_ManForEachLoSeq( p, pObj, i )
            pObj->pData = NULL;
        // save the latch input values
        k = 0;
        Aig_ManForEachLiSeq( p, pObj, i )
        {
            if ( Aig_ObjFanin0(pObj)->pData )
                pLatches[k++] = Aig_ObjChild0Copy(pObj);
            else
                pLatches[k++] = NULL;
        }
        // insert them as the latch output values
        k = 0;
        Aig_ManForEachLoSeq( p, pObj, i )
            pObj->pData = pLatches[k++];
        // create the next time frame of nodes
        Aig_ManForEachNode( p, pObj, i )
        {
            if ( i > nNodesOld )
                break;
            if ( Aig_ObjFanin0(pObj)->pData && Aig_ObjFanin1(pObj)->pData )
                pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
            else
                pObj->pData = NULL;
        }
    }
Alan Mishchenko committed
238
    ABC_FREE( pLatches );
Alan Mishchenko committed
239 240
}

Alan Mishchenko committed
241 242 243

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

Alan Mishchenko committed
244
  Synopsis    [Performs partitioned sequential SAT sweepingG.]
Alan Mishchenko committed
245 246 247 248 249 250 251 252

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
253 254 255 256 257 258 259 260 261 262
Aig_Man_t * Fra_FraigInductionPart( Aig_Man_t * pAig, Fra_Ssw_t * pPars )
{
    int fPrintParts = 0;
    char Buffer[100];
    Aig_Man_t * pTemp, * pNew;
    Vec_Ptr_t * vResult;
    Vec_Int_t * vPart;
    int * pMapBack;
    int i, nCountPis, nCountRegs;
    int nClasses, nPartSize, fVerbose;
263
    abctime clk = Abc_Clock();
Alan Mishchenko committed
264 265 266 267 268

    // save parameters
    nPartSize = pPars->nPartSize; pPars->nPartSize = 0;
    fVerbose  = pPars->fVerbose;  pPars->fVerbose = 0;
    // generate partitions
Alan Mishchenko committed
269 270 271 272
    if ( pAig->vClockDoms )
    {
        // divide large clock domains into separate partitions
        vResult = Vec_PtrAlloc( 100 );
273
        Vec_PtrForEachEntry( Vec_Int_t *, (Vec_Ptr_t *)pAig->vClockDoms, vPart, i )
Alan Mishchenko committed
274 275
        {
            if ( nPartSize && Vec_IntSize(vPart) > nPartSize )
Alan Mishchenko committed
276
                Aig_ManPartDivide( vResult, vPart, nPartSize, pPars->nOverSize );
Alan Mishchenko committed
277 278 279 280 281 282
            else
                Vec_PtrPush( vResult, Vec_IntDup(vPart) );
        }
    }
    else
        vResult = Aig_ManRegPartitionSimple( pAig, nPartSize, pPars->nOverSize );
Alan Mishchenko committed
283 284 285 286 287 288
//    vResult = Aig_ManPartitionSmartRegisters( pAig, nPartSize, 0 ); 
//    vResult = Aig_ManRegPartitionSmart( pAig, nPartSize );
    if ( fPrintParts )
    {
        // print partitions
        printf( "Simple partitioning. %d partitions are saved:\n", Vec_PtrSize(vResult) );
289
        Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i )
Alan Mishchenko committed
290 291 292 293 294
        {
            sprintf( Buffer, "part%03d.aig", i );
            pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, NULL );
            Ioa_WriteAiger( pTemp, Buffer, 0, 0 );
            printf( "part%03d.aig : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d.\n", 
295
                i, Vec_IntSize(vPart), Aig_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp) );
Alan Mishchenko committed
296 297 298 299 300 301
            Aig_ManStop( pTemp );
        }
    }

    // perform SSW with partitions
    Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) );
302
    Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i )
Alan Mishchenko committed
303 304
    {
        pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, &pMapBack );
Alan Mishchenko committed
305 306 307
        // create the projection of 1-hot registers
        if ( pAig->vOnehots )
            pTemp->vOnehots = Aig_ManRegProjectOnehots( pAig, pTemp, pAig->vOnehots, fVerbose );
Alan Mishchenko committed
308 309 310 311 312
        // run SSW
        pNew = Fra_FraigInduction( pTemp, pPars );
        nClasses = Aig_TransferMappedClasses( pAig, pTemp, pMapBack );
        if ( fVerbose )
            printf( "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. It = %3d. Cl = %5d.\n", 
313
                i, Vec_IntSize(vPart), Aig_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp), pPars->nIters, nClasses );
Alan Mishchenko committed
314 315
        Aig_ManStop( pNew );
        Aig_ManStop( pTemp );
Alan Mishchenko committed
316
        ABC_FREE( pMapBack );
Alan Mishchenko committed
317 318 319 320 321 322 323 324 325
    }
    // remap the AIG
    pNew = Aig_ManDupRepr( pAig, 0 );
    Aig_ManSeqCleanup( pNew );
//    Aig_ManPrintStats( pAig );
//    Aig_ManPrintStats( pNew );
    Vec_VecFree( (Vec_Vec_t *)vResult );
    pPars->nPartSize = nPartSize;
    pPars->fVerbose = fVerbose;
Alan Mishchenko committed
326 327
    if ( fVerbose )
    {
328
        ABC_PRT( "Total time", Abc_Clock() - clk );
Alan Mishchenko committed
329
    }
Alan Mishchenko committed
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
    return pNew;
}

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

  Synopsis    [Performs sequential SAT sweeping.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Aig_Man_t * Fra_FraigInduction( Aig_Man_t * pManAig, Fra_Ssw_t * pParams )
Alan Mishchenko committed
345
{
Alan Mishchenko committed
346 347 348 349 350 351 352 353
    int fUseSimpleCnf = 0;
    int fUseOldSimulation = 0;
    // other paramaters affecting performance
    // - presence of FRAIGing in Abc_NtkDarSeqSweep()
    // - using distance-1 patterns in Fra_SmlAssignDist1()
    // - the number of simulation patterns
    // - the number of BMC frames

Alan Mishchenko committed
354 355 356 357
    Fra_Man_t * p;
    Fra_Par_t Pars, * pPars = &Pars; 
    Aig_Obj_t * pObj;
    Cnf_Dat_t * pCnf;
Alan Mishchenko committed
358
    Aig_Man_t * pManAigNew = NULL;
Alan Mishchenko committed
359
    int nNodesBeg, nRegsBeg;
Alan Mishchenko committed
360
    int nIter = -1; // Suppress "might be used uninitialized"
361
    int i;
362 363
    abctime clk = Abc_Clock(), clk2;
    abctime TimeToStop = pParams->TimeLimit ? pParams->TimeLimit * CLOCKS_PER_SEC + Abc_Clock() : 0;
Alan Mishchenko committed
364

Alan Mishchenko committed
365
    if ( Aig_ManNodeNum(pManAig) == 0 )
Alan Mishchenko committed
366
    {
Alan Mishchenko committed
367
        pParams->nIters = 0;
Alan Mishchenko committed
368 369
        // Ntl_ManFinalize() needs the following to satisfy an assertion
        Aig_ManReprStart(pManAig,Aig_ManObjNumMax(pManAig));
Alan Mishchenko committed
370
        return Aig_ManDupOrdered(pManAig);
Alan Mishchenko committed
371
    }
Alan Mishchenko committed
372
    assert( Aig_ManRegNum(pManAig) > 0 );
Alan Mishchenko committed
373
    assert( pParams->nFramesK > 0 );
Alan Mishchenko committed
374
//Aig_ManShow( pManAig, 0, NULL );
Alan Mishchenko committed
375 376 377 378 379 380 381

    if ( pParams->fWriteImps && pParams->nPartSize > 0 )
    {
        pParams->nPartSize = 0;
        printf( "Partitioning was disabled to allow implication writing.\n" );
    }
    // perform partitioning
Alan Mishchenko committed
382
    if ( (pParams->nPartSize > 0 && pParams->nPartSize < Aig_ManRegNum(pManAig))
Alan Mishchenko committed
383
         || (pManAig->vClockDoms && Vec_VecSize(pManAig->vClockDoms) > 0)  )
Alan Mishchenko committed
384
        return Fra_FraigInductionPart( pManAig, pParams );
Alan Mishchenko committed
385 386 387 388 389 390
 
    nNodesBeg = Aig_ManNodeNum(pManAig);
    nRegsBeg  = Aig_ManRegNum(pManAig);

    // enhance the AIG by adding timeframes
//    Fra_FramesAddMore( pManAig, 3 );
Alan Mishchenko committed
391 392 393

    // get parameters
    Fra_ParamsDefaultSeq( pPars );
Alan Mishchenko committed
394 395 396 397 398 399 400 401 402 403
    pPars->nFramesP   = pParams->nFramesP;
    pPars->nFramesK   = pParams->nFramesK;
    pPars->nMaxImps   = pParams->nMaxImps;
    pPars->nMaxLevs   = pParams->nMaxLevs;
    pPars->fVerbose   = pParams->fVerbose;
    pPars->fRewrite   = pParams->fRewrite;
    pPars->fLatchCorr = pParams->fLatchCorr;
    pPars->fUseImps   = pParams->fUseImps;
    pPars->fWriteImps = pParams->fWriteImps;
    pPars->fUse1Hot   = pParams->fUse1Hot;
Alan Mishchenko committed
404 405 406

    assert( !(pPars->nFramesP > 0 && pPars->fUse1Hot) );
    assert( !(pPars->nFramesK > 1 && pPars->fUse1Hot) );
Alan Mishchenko committed
407
 
Alan Mishchenko committed
408 409
    // start the fraig manager for this run
    p = Fra_ManStart( pManAig, pPars );
Alan Mishchenko committed
410
    p->pPars->nBTLimitNode = 0;
Alan Mishchenko committed
411
    // derive and refine e-classes using K initialized frames
Alan Mishchenko committed
412 413 414 415 416 417 418 419 420 421 422 423
    if ( fUseOldSimulation )
    {
        if ( pPars->nFramesP > 0 )
        {
            pPars->nFramesP = 0;
            printf( "Fra_FraigInduction(): Prefix cannot be used.\n" );
        }
        p->pSml = Fra_SmlStart( pManAig, 0, pPars->nFramesK + 1, pPars->nSimWords );
        Fra_SmlSimulate( p, 1 );
    }
    else
    {
Alan Mishchenko committed
424
        // bug:  r iscas/blif/s5378.blif    ; st; ssw -v
Alan Mishchenko committed
425 426
        // bug:  r iscas/blif/s1238.blif    ; st; ssw -v
        // refine the classes with more simulation rounds
Alan Mishchenko committed
427
if ( pPars->fVerbose )
Alan Mishchenko committed
428
printf( "Simulating %d AIG nodes for %d cycles ... ", Aig_ManNodeNum(pManAig), pPars->nFramesP + 32 );
Alan Mishchenko committed
429
        p->pSml = Fra_SmlSimulateSeq( pManAig, pPars->nFramesP, 32, 1, 1  ); //pPars->nFramesK + 1, 1 );  
Alan Mishchenko committed
430
if ( pPars->fVerbose ) 
Alan Mishchenko committed
431
{
432
ABC_PRT( "Time", Abc_Clock() - clk );
Alan Mishchenko committed
433
}
Alan Mishchenko committed
434
        Fra_ClassesPrepare( p->pCla, p->pPars->fLatchCorr, p->pPars->nMaxLevs );
Alan Mishchenko committed
435
//        Fra_ClassesPostprocess( p->pCla );
Alan Mishchenko committed
436 437 438
        // compute one-hotness conditions
        if ( p->pPars->fUse1Hot )
            p->vOneHots = Fra_OneHotCompute( p, p->pSml );
Alan Mishchenko committed
439 440 441 442 443
        // allocate new simulation manager for simulating counter-examples
        Fra_SmlStop( p->pSml );
        p->pSml = Fra_SmlStart( pManAig, 0, pPars->nFramesK + 1, pPars->nSimWords );
    }

Alan Mishchenko committed
444 445
    // select the most expressive implications
    if ( pPars->fUseImps )
Alan Mishchenko committed
446
        p->pCla->vImps = Fra_ImpDerive( p, 5000000, pPars->nMaxImps, pPars->fLatchCorr );
Alan Mishchenko committed
447

448
    if ( pParams->TimeLimit != 0.0 && Abc_Clock() > TimeToStop )
Alan Mishchenko committed
449
    {
Alan Mishchenko committed
450 451
        if ( !pParams->fSilent )
            printf( "Fra_FraigInduction(): Runtime limit exceeded.\n" );
Alan Mishchenko committed
452 453 454
        goto finish;
    }

Alan Mishchenko committed
455 456 457 458 459 460
    // perform BMC (for the min number of frames)
    Fra_BmcPerform( p, pPars->nFramesP, pPars->nFramesK+1 ); // +1 is needed to prevent non-refinement
//Fra_ClassesPrint( p->pCla, 1 );
//    if ( p->vCex == NULL )
//        p->vCex = Vec_IntAlloc( 1000 );

Alan Mishchenko committed
461
    p->nLitsBeg  = Fra_ClassesCountLits( p->pCla );
Alan Mishchenko committed
462 463
    p->nNodesBeg = nNodesBeg; // Aig_ManNodeNum(pManAig);
    p->nRegsBeg  = nRegsBeg; // Aig_ManRegNum(pManAig);
Alan Mishchenko committed
464

Alan Mishchenko committed
465 466
    // dump AIG of the timeframes
//    pManAigNew = Fra_ClassesDeriveAig( p->pCla, pPars->nFramesK );
Alan Mishchenko committed
467
//    Aig_ManDumpBlif( pManAigNew, "frame_aig.blif", NULL, NULL );
Alan Mishchenko committed
468 469
//    Fra_ManPartitionTest2( pManAigNew );
//    Aig_ManStop( pManAigNew );
Alan Mishchenko committed
470
 
Alan Mishchenko committed
471 472 473 474
    // iterate the inductive case
    p->pCla->fRefinement = 1;
    for ( nIter = 0; p->pCla->fRefinement; nIter++ )
    {
Alan Mishchenko committed
475 476
        int nLitsOld = Fra_ClassesCountLits(p->pCla);
        int nImpsOld = p->pCla->vImps? Vec_IntSize(p->pCla->vImps) : 0;
Alan Mishchenko committed
477
        int nHotsOld = p->vOneHots? Fra_OneHotCount(p, p->vOneHots) : 0;
478
        abctime clk3 = Abc_Clock();
Alan Mishchenko committed
479

480
        if ( pParams->TimeLimit != 0.0 && Abc_Clock() > TimeToStop )
Alan Mishchenko committed
481
        {
Alan Mishchenko committed
482 483
            if ( !pParams->fSilent )
                printf( "Fra_FraigInduction(): Runtime limit exceeded.\n" );
Alan Mishchenko committed
484 485 486
            goto finish;
        }

Alan Mishchenko committed
487 488 489
        // mark the classes as non-refined
        p->pCla->fRefinement = 0;
        // derive non-init K-timeframes while implementing e-classes
490
clk2 = Abc_Clock();
Alan Mishchenko committed
491
        p->pManFraig = Fra_FramesWithClasses( p );
492
p->timeTrav += Abc_Clock() - clk2;
Alan Mishchenko committed
493
//Aig_ManDumpBlif( p->pManFraig, "testaig.blif", NULL, NULL );
Alan Mishchenko committed
494

Alan Mishchenko committed
495 496 497
        // perform AIG rewriting
        if ( p->pPars->fRewrite )
            Fra_FraigInductionRewrite( p );
Alan Mishchenko committed
498 499

        // convert the manager to SAT solver (the last nLatches outputs are inputs)
Alan Mishchenko committed
500
        if ( fUseSimpleCnf || pPars->fUseImps )
Alan Mishchenko committed
501 502 503
            pCnf = Cnf_DeriveSimple( p->pManFraig, Aig_ManRegNum(p->pManFraig) );
        else
            pCnf = Cnf_Derive( p->pManFraig, Aig_ManRegNum(p->pManFraig) );
Alan Mishchenko committed
504
//        Cnf_DataTranformPolarity( pCnf, 0 );
Alan Mishchenko committed
505 506
//Cnf_DataWriteIntoFile( pCnf, "temp.cnf", 1 );

507
        p->pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
Alan Mishchenko committed
508
        p->nSatVars = pCnf->nVars;
Alan Mishchenko committed
509 510 511
        assert( p->pSat != NULL );
        if ( p->pSat == NULL )
            printf( "Fra_FraigInduction(): Computed CNF is not valid.\n" );
Alan Mishchenko committed
512 513 514 515 516 517
        if ( pPars->fUseImps )
        {
            Fra_ImpAddToSolver( p, p->pCla->vImps, pCnf->pVarNums );
            if ( p->pSat == NULL )
                printf( "Fra_FraigInduction(): Adding implicationsn to CNF led to a conflict.\n" );
        }
Alan Mishchenko committed
518

Alan Mishchenko committed
519 520 521
        // set the pointers to the manager
        Aig_ManForEachObj( p->pManFraig, pObj, i )
            pObj->pData = p;
Alan Mishchenko committed
522

Alan Mishchenko committed
523 524 525
        // prepare solver for fraiging the last timeframe
        Fra_ManClean( p, Aig_ManObjNumMax(p->pManFraig) + Aig_ManNodeNum(p->pManAig) );

Alan Mishchenko committed
526
        // transfer PI/LO variable numbers
Alan Mishchenko committed
527 528
        Aig_ManForEachObj( p->pManFraig, pObj, i )
        {
Alan Mishchenko committed
529 530
            if ( pCnf->pVarNums[pObj->Id] == -1 )
                continue;
Alan Mishchenko committed
531
            Fra_ObjSetSatNum( pObj, pCnf->pVarNums[pObj->Id] );
532
            Fra_ObjSetFaninVec( pObj, (Vec_Ptr_t *)1 );
Alan Mishchenko committed
533 534
        }
        Cnf_DataFree( pCnf );
Alan Mishchenko committed
535

Alan Mishchenko committed
536 537 538
        // add one-hotness clauses
        if ( p->pPars->fUse1Hot )
            Fra_OneHotAssume( p, p->vOneHots );
Alan Mishchenko committed
539 540
//        if ( p->pManAig->vOnehots )
//            Fra_OneHotAddKnownConstraint( p, p->pManAig->vOnehots );
Alan Mishchenko committed
541
 
Alan Mishchenko committed
542
        // report the intermediate results
Alan Mishchenko committed
543
        if ( pPars->fVerbose )
Alan Mishchenko committed
544
        {
Alan Mishchenko committed
545
            printf( "%3d : C = %6d. Cl = %6d.  L = %6d. LR = %6d.  ", 
Alan Mishchenko committed
546
                nIter, Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), 
Alan Mishchenko committed
547 548 549
                Fra_ClassesCountLits(p->pCla), p->pManFraig->nAsserts );
            if ( p->pCla->vImps )
                printf( "I = %6d. ", Vec_IntSize(p->pCla->vImps) );
Alan Mishchenko committed
550 551
            if ( p->pPars->fUse1Hot )
                printf( "1h = %6d. ", Fra_OneHotCount(p, p->vOneHots) );
Alan Mishchenko committed
552
            printf( "NR = %6d. ", Aig_ManNodeNum(p->pManFraig) );
Alan Mishchenko committed
553
//            printf( "\n" );
Alan Mishchenko committed
554
        } 
Alan Mishchenko committed
555 556

        // perform sweeping
Alan Mishchenko committed
557 558
        p->nSatCallsRecent = 0;
        p->nSatCallsSkipped = 0;
559
clk2 = Abc_Clock();
Alan Mishchenko committed
560 561
        if ( p->pPars->fUse1Hot )
            Fra_OneHotCheck( p, p->vOneHots );
Alan Mishchenko committed
562
        Fra_FraigSweep( p );
Alan Mishchenko committed
563
        if ( pPars->fVerbose )
Alan Mishchenko committed
564
        {
565
            ABC_PRT( "T", Abc_Clock() - clk3 );
Alan Mishchenko committed
566
        } 
Alan Mishchenko committed
567 568

//        Sat_SolverPrintStats( stdout, p->pSat );
Alan Mishchenko committed
569 570
        // remove FRAIG and SAT solver
        Aig_ManStop( p->pManFraig );   p->pManFraig = NULL;
Alan Mishchenko committed
571
//        printf( "Vars = %d. Clauses = %d. Learnts = %d.\n", p->pSat->size, p->pSat->clauses.size, p->pSat->learnts.size );
Alan Mishchenko committed
572 573
        sat_solver_delete( p->pSat );  p->pSat = NULL; 
        memset( p->pMemFraig, 0, sizeof(Aig_Obj_t *) * p->nSizeAlloc * p->nFramesAll );
Alan Mishchenko committed
574
//        printf( "Recent SAT called = %d. Skipped = %d.\n", p->nSatCallsRecent, p->nSatCallsSkipped );
Alan Mishchenko committed
575
        assert( p->vTimeouts == NULL );
Alan Mishchenko committed
576 577
        if ( p->vTimeouts )
           printf( "Fra_FraigInduction(): SAT solver timed out!\n" );
Alan Mishchenko committed
578 579 580 581
        // check if refinement has happened
//        p->pCla->fRefinement = (int)(nLitsOld != Fra_ClassesCountLits(p->pCla));
        if ( p->pCla->fRefinement && 
            nLitsOld == Fra_ClassesCountLits(p->pCla) && 
Alan Mishchenko committed
582 583
            nImpsOld == (p->pCla->vImps? Vec_IntSize(p->pCla->vImps) : 0) && 
            nHotsOld == (p->vOneHots? Fra_OneHotCount(p, p->vOneHots) : 0) )
Alan Mishchenko committed
584 585 586 587
        {
            printf( "Fra_FraigInduction(): Internal error. The result may not verify.\n" );
            break;
        }
Alan Mishchenko committed
588
    }
Alan Mishchenko committed
589
/*
Alan Mishchenko committed
590
    // verify implications using simulation
Alan Mishchenko committed
591 592
    if ( p->pCla->vImps && Vec_IntSize(p->pCla->vImps) )
    {
593
        int Temp;
594
        abctime clk = Abc_Clock();
Alan Mishchenko committed
595 596 597 598
        if ( Temp = Fra_ImpVerifyUsingSimulation( p ) )
            printf( "Implications failing the simulation test = %d (out of %d).  ", Temp, Vec_IntSize(p->pCla->vImps) );
        else
            printf( "All %d implications have passed the simulation test.  ", Vec_IntSize(p->pCla->vImps) );
599
        ABC_PRT( "Time", Abc_Clock() - clk );
Alan Mishchenko committed
600
    }
Alan Mishchenko committed
601
*/
Alan Mishchenko committed
602

Alan Mishchenko committed
603
    // move the classes into representatives and reduce AIG
604
clk2 = Abc_Clock();
Alan Mishchenko committed
605 606
    if ( p->pPars->fWriteImps && p->vOneHots && Fra_OneHotCount(p, p->vOneHots) )
    {
Alan Mishchenko committed
607 608
        extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact );
        Aig_Man_t * pNew;
Alan Mishchenko committed
609 610
        char * pFileName = Ioa_FileNameGenericAppend( p->pManAig->pName, "_care.aig" );
        printf( "Care one-hotness clauses will be written into file \"%s\".\n", pFileName );
Alan Mishchenko committed
611
        pManAigNew = Aig_ManDupOrdered( pManAig );
Alan Mishchenko committed
612
        pNew = Fra_OneHotCreateExdc( p, p->vOneHots );
Alan Mishchenko committed
613
        Ioa_WriteAiger( pNew, pFileName, 0, 1 );
Alan Mishchenko committed
614
        Aig_ManStop( pNew );
Alan Mishchenko committed
615 616 617 618 619 620 621 622
    }
    else 
    {
    //    Fra_ClassesPrint( p->pCla, 1 );
        Fra_ClassesSelectRepr( p->pCla );
        Fra_ClassesCopyReprs( p->pCla, p->vTimeouts );
        pManAigNew = Aig_ManDupRepr( pManAig, 0 );
    }
Alan Mishchenko committed
623
    // add implications to the manager
Alan Mishchenko committed
624 625
//    if ( fWriteImps && p->pCla->vImps && Vec_IntSize(p->pCla->vImps) )
//        Fra_ImpRecordInManager( p, pManAigNew );
Alan Mishchenko committed
626
    // cleanup the new manager
Alan Mishchenko committed
627
    Aig_ManSeqCleanup( pManAigNew );
Alan Mishchenko committed
628 629 630 631
    // remove pointers to the dead nodes
//    Aig_ManForEachObj( pManAig, pObj, i )
//        if ( pObj->pData && Aig_ObjIsNone(pObj->pData) )
//            pObj->pData = NULL;
Alan Mishchenko committed
632
//    Aig_ManCountMergeRegs( pManAigNew );
633 634
p->timeTrav += Abc_Clock() - clk2;
p->timeTotal = Abc_Clock() - clk;
Alan Mishchenko committed
635 636 637 638
    // get the final stats
    p->nLitsEnd  = Fra_ClassesCountLits( p->pCla );
    p->nNodesEnd = Aig_ManNodeNum(pManAigNew);
    p->nRegsEnd  = Aig_ManRegNum(pManAigNew);
Alan Mishchenko committed
639
    // free the manager
Alan Mishchenko committed
640
finish:
Alan Mishchenko committed
641
    Fra_ManStop( p );
Alan Mishchenko committed
642
    // check the output
643 644
//    if ( Aig_ManCoNum(pManAigNew) - Aig_ManRegNum(pManAigNew) == 1 )
//        if ( Aig_ObjChild0( Aig_ManCo(pManAigNew,0) ) == Aig_ManConst0(pManAigNew) )
Alan Mishchenko committed
645
//            printf( "Proved output constant 0.\n" );
Alan Mishchenko committed
646
    pParams->nIters = nIter;
Alan Mishchenko committed
647 648 649
    return pManAigNew;
}

Alan Mishchenko committed
650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
/**Function*************************************************************

  Synopsis    [Outputs a set of pairs of equivalent nodes.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Fra_FraigInductionTest( char * pFileName, Fra_Ssw_t * pParams )
{
    FILE * pFile;
    char * pFilePairs;
    Aig_Man_t * pMan, * pNew;
    Aig_Obj_t * pObj, * pRepr;
    int * pNum2Id;
    int i, Counter = 0;
    pMan = Saig_ManReadBlif( pFileName );
    if ( pMan == NULL )
        return 0;
    // perform seq SAT sweeping
    pNew = Fra_FraigInduction( pMan, pParams );
    if ( pNew == NULL )
    {
        Aig_ManStop( pMan );
        return 0;
    }
    if ( pParams->fVerbose )
    {
        printf( "Original AIG: " );
        Aig_ManPrintStats( pMan );
        printf( "Reduced  AIG: " );
        Aig_ManPrintStats( pNew );
    }
    Aig_ManStop( pNew );
687
    pNum2Id = (int *)pMan->pData;
Alan Mishchenko committed
688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
    // write the output file
    pFilePairs = Aig_FileNameGenericAppend( pFileName, ".pairs" );
    pFile = fopen( pFilePairs, "w" );
    Aig_ManForEachObj( pMan, pObj, i )
        if ( (pRepr = pMan->pReprs[pObj->Id]) )
        {
            fprintf( pFile, "%d %d %c\n", pNum2Id[pObj->Id], pNum2Id[pRepr->Id], (Aig_ObjPhase(pObj) ^ Aig_ObjPhase(pRepr))? '-' : '+' );
            Counter++;
        }
    fclose( pFile );
    if ( pParams->fVerbose )
    {
        printf( "Result: %d pairs of seq equiv nodes are written into file \"%s\".\n", Counter, pFilePairs );
    }
    Aig_ManStop( pMan );
    return 1;
}

Alan Mishchenko committed
706 707 708 709 710
////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


711 712
ABC_NAMESPACE_IMPL_END