fraClass.c 28.1 KB
Newer Older
Alan Mishchenko committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/**CFile****************************************************************

  FileName    [fraClass.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [New FRAIG package.]

  Synopsis    []

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

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

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

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

#include "fra.h"

23 24 25
ABC_NAMESPACE_IMPL_START


Alan Mishchenko committed
26 27 28 29 30
/*
    The candidate equivalence classes are stored as a vector of pointers 
    to the array of pointers to the nodes in each class.
    The first node of the class is its representative node.
    The representative has the smallest topological order among the class nodes.
Alan Mishchenko committed
31
    The nodes inside each class are ordered according to their topological order.
Alan Mishchenko committed
32 33 34 35 36 37 38 39 40 41
    The classes are ordered according to the topological order of their representatives.
    The array of pointers to the class nodes is terminated with a NULL pointer.
    To enable dynamic addition of new classes (during class refinement),
    each array has at least as many NULLs in the end, as there are nodes in the class.
*/

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

Alan Mishchenko committed
42 43
static inline Aig_Obj_t *  Fra_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj )                       { return ppNexts[pObj->Id];  }
static inline void         Fra_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; }
Alan Mishchenko committed
44

Alan Mishchenko committed
45 46 47 48 49 50
////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

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

Alan Mishchenko committed
51 52 53 54 55 56 57 58 59 60 61 62
  Synopsis    [Starts representation of equivalence classes.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Fra_Cla_t * Fra_ClassesStart( Aig_Man_t * pAig )
{
    Fra_Cla_t * p;
Alan Mishchenko committed
63
    p = ABC_ALLOC( Fra_Cla_t, 1 );
Alan Mishchenko committed
64 65
    memset( p, 0, sizeof(Fra_Cla_t) );
    p->pAig = pAig;
Alan Mishchenko committed
66
    p->pMemRepr  = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
Alan Mishchenko committed
67
    memset( p->pMemRepr, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pAig) );
Alan Mishchenko committed
68 69
    p->vClasses     = Vec_PtrAlloc( 100 );
    p->vClasses1    = Vec_PtrAlloc( 100 );
Alan Mishchenko committed
70
    p->vClassesTemp = Vec_PtrAlloc( 100 );
Alan Mishchenko committed
71 72
    p->vClassOld    = Vec_PtrAlloc( 100 );
    p->vClassNew    = Vec_PtrAlloc( 100 );
Alan Mishchenko committed
73 74 75
    p->pFuncNodeHash      = Fra_SmlNodeHash;
    p->pFuncNodeIsConst   = Fra_SmlNodeIsConst;
    p->pFuncNodesAreEqual = Fra_SmlNodesAreEqual;
Alan Mishchenko committed
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
    return p;
}

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

  Synopsis    [Stop representation of equivalence classes.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Fra_ClassesStop( Fra_Cla_t * p )
{
Alan Mishchenko committed
92 93
    ABC_FREE( p->pMemClasses );
    ABC_FREE( p->pMemRepr );
Alan Mishchenko committed
94 95 96 97 98
    if ( p->vClassesTemp ) Vec_PtrFree( p->vClassesTemp );
    if ( p->vClassNew )    Vec_PtrFree( p->vClassNew );
    if ( p->vClassOld )    Vec_PtrFree( p->vClassOld );
    if ( p->vClasses1 )    Vec_PtrFree( p->vClasses1 );
    if ( p->vClasses )     Vec_PtrFree( p->vClasses );
Alan Mishchenko committed
99
    if ( p->vImps )        Vec_IntFree( p->vImps );
Alan Mishchenko committed
100
    ABC_FREE( p );
Alan Mishchenko committed
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
}

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

  Synopsis    [Starts representation of equivalence classes.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Fra_ClassesCopyReprs( Fra_Cla_t * p, Vec_Ptr_t * vFailed )
{
    Aig_Obj_t * pObj;
    int i;
Alan Mishchenko committed
118 119
    Aig_ManReprStart( p->pAig, Aig_ManObjNumMax(p->pAig) );
    memmove( p->pAig->pReprs, p->pMemRepr, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p->pAig) );
Alan Mishchenko committed
120 121 122 123 124 125 126 127 128
    if ( Vec_PtrSize(p->vClasses1) == 0 && Vec_PtrSize(p->vClasses) == 0 )
    {
        Aig_ManForEachObj( p->pAig, pObj, i )
        {
            if ( p->pAig->pReprs[i] != NULL )
                printf( "Classes are not cleared!\n" );
            assert( p->pAig->pReprs[i] == NULL );
        }
    }
Alan Mishchenko committed
129
    if ( vFailed )
130
        Vec_PtrForEachEntry( Aig_Obj_t *, vFailed, pObj, i )
Alan Mishchenko committed
131
            p->pAig->pReprs[pObj->Id] = NULL;
Alan Mishchenko committed
132 133 134 135
}

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

Alan Mishchenko committed
136 137 138 139 140 141 142 143 144
  Synopsis    [Prints simulation classes.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
145
int Fra_ClassCount( Aig_Obj_t ** pClass )
Alan Mishchenko committed
146
{
Alan Mishchenko committed
147
    Aig_Obj_t * pTemp;
Alan Mishchenko committed
148
    int i;
Alan Mishchenko committed
149
    for ( i = 0; (pTemp = pClass[i]); i++ );
Alan Mishchenko committed
150 151 152 153 154
    return i;
}

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

Alan Mishchenko committed
155
  Synopsis    [Count the number of literals.]
Alan Mishchenko committed
156 157 158 159 160 161 162 163

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
164
int Fra_ClassesCountLits( Fra_Cla_t * p )
Alan Mishchenko committed
165
{
Alan Mishchenko committed
166
    Aig_Obj_t ** pClass;
Alan Mishchenko committed
167 168
    int i, nNodes, nLits = 0;
    nLits = Vec_PtrSize( p->vClasses1 );
169
    Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i )
Alan Mishchenko committed
170
    {
Alan Mishchenko committed
171
        nNodes = Fra_ClassCount( pClass );
Alan Mishchenko committed
172
        assert( nNodes > 1 );
Alan Mishchenko committed
173
        nLits += nNodes - 1;
Alan Mishchenko committed
174
    }
Alan Mishchenko committed
175
    return nLits;
Alan Mishchenko committed
176 177 178 179
}

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

Alan Mishchenko committed
180
  Synopsis    [Count the number of pairs.]
Alan Mishchenko committed
181 182 183 184 185 186 187 188

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
189
int Fra_ClassesCountPairs( Fra_Cla_t * p )
Alan Mishchenko committed
190
{
Alan Mishchenko committed
191
    Aig_Obj_t ** pClass;
Alan Mishchenko committed
192
    int i, nNodes, nPairs = 0;
193
    Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i )
Alan Mishchenko committed
194
    {
Alan Mishchenko committed
195 196
        nNodes = Fra_ClassCount( pClass );
        assert( nNodes > 1 );
Alan Mishchenko committed
197
        nPairs += nNodes * (nNodes - 1) / 2;
Alan Mishchenko committed
198
    }
Alan Mishchenko committed
199
    return nPairs;
Alan Mishchenko committed
200 201 202 203
}

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

Alan Mishchenko committed
204
  Synopsis    [Prints simulation classes.]
Alan Mishchenko committed
205 206 207 208 209 210 211 212

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
213
void Fra_PrintClass( Fra_Cla_t * p, Aig_Obj_t ** pClass )
Alan Mishchenko committed
214 215 216
{
    Aig_Obj_t * pTemp;
    int i;
Alan Mishchenko committed
217
    for ( i = 1; (pTemp = pClass[i]); i++ )
Alan Mishchenko committed
218 219
        assert( Fra_ClassObjRepr(pTemp) == pClass[0] );
    printf( "{ " );
Alan Mishchenko committed
220
    for ( i = 0; (pTemp = pClass[i]); i++ )
Alan Mishchenko committed
221
        printf( "%d(%d,%d) ", pTemp->Id, pTemp->Level, Aig_SupportSize(p->pAig,pTemp) );
Alan Mishchenko committed
222 223 224 225 226 227 228 229 230 231 232 233 234 235
    printf( "}\n" );
}

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

  Synopsis    [Prints simulation classes.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
236
void Fra_ClassesPrint( Fra_Cla_t * p, int fVeryVerbose )
Alan Mishchenko committed
237
{
Alan Mishchenko committed
238
    Aig_Obj_t ** pClass;
Alan Mishchenko committed
239
    Aig_Obj_t * pObj;
Alan Mishchenko committed
240
    int i;
Alan Mishchenko committed
241

Alan Mishchenko committed
242
    printf( "Const = %5d. Class = %5d. Lit = %5d. ", 
Alan Mishchenko committed
243
        Vec_PtrSize(p->vClasses1), Vec_PtrSize(p->vClasses), Fra_ClassesCountLits(p) );
Alan Mishchenko committed
244 245 246
    if ( p->vImps && Vec_IntSize(p->vImps) > 0 )
        printf( "Imp = %5d. ", Vec_IntSize(p->vImps) );
    printf( "\n" );
Alan Mishchenko committed
247 248

    if ( fVeryVerbose )
Alan Mishchenko committed
249
    {
250
        Vec_PtrForEachEntry( Aig_Obj_t *, p->vClasses1, pObj, i )
Alan Mishchenko committed
251
            assert( Fra_ClassObjRepr(pObj) == Aig_ManConst1(p->pAig) );
Alan Mishchenko committed
252
        printf( "Constants { " );
253
        Vec_PtrForEachEntry( Aig_Obj_t *, p->vClasses1, pObj, i )
Alan Mishchenko committed
254
            printf( "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) );
Alan Mishchenko committed
255
        printf( "}\n" );
256
        Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i )
Alan Mishchenko committed
257 258
        {
            printf( "%3d (%3d) : ", i, Fra_ClassCount(pClass) );
Alan Mishchenko committed
259
            Fra_PrintClass( p, pClass );
Alan Mishchenko committed
260 261
        }
        printf( "\n" );
Alan Mishchenko committed
262
    }
Alan Mishchenko committed
263
}
Alan Mishchenko committed
264 265 266 267 268 269 270 271 272 273 274 275

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

  Synopsis    [Creates initial simulation classes.]

  Description [Assumes that simulation info is assigned.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
276
void Fra_ClassesPrepare( Fra_Cla_t * p, int fLatchCorr, int nMaxLevs )
Alan Mishchenko committed
277
{
Alan Mishchenko committed
278 279
    Aig_Obj_t ** ppTable, ** ppNexts;
    Aig_Obj_t * pObj, * pTemp;
Alan Mishchenko committed
280 281 282
    int i, k, nTableSize, nEntries, nNodes, iEntry;

    // allocate the hash table hashing simulation info into nodes
283
    nTableSize = Abc_PrimeCudd( Aig_ManObjNumMax(p->pAig) );
284 285
    ppTable = ABC_FALLOC( Aig_Obj_t *, nTableSize ); 
    ppNexts = ABC_FALLOC( Aig_Obj_t *, nTableSize ); 
Alan Mishchenko committed
286
    memset( ppTable, 0, sizeof(Aig_Obj_t *) * nTableSize );
Alan Mishchenko committed
287 288

    // add all the nodes to the hash table
Alan Mishchenko committed
289
    Vec_PtrClear( p->vClasses1 );
Alan Mishchenko committed
290
    Aig_ManForEachObj( p->pAig, pObj, i )
Alan Mishchenko committed
291
    {
Alan Mishchenko committed
292 293
        if ( fLatchCorr )
        {
294
            if ( !Aig_ObjIsCi(pObj) )
Alan Mishchenko committed
295 296 297 298
                continue;
        }
        else
        {
299
            if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
Alan Mishchenko committed
300
                continue;
Alan Mishchenko committed
301
            // skip the node with more that the given number of levels
Alan Mishchenko committed
302
            if ( nMaxLevs && (int)pObj->Level > nMaxLevs )
Alan Mishchenko committed
303
                continue;
Alan Mishchenko committed
304
        }
Alan Mishchenko committed
305
        // hash the node by its simulation info
Alan Mishchenko committed
306
        iEntry = p->pFuncNodeHash( pObj, nTableSize );
Alan Mishchenko committed
307
        // check if the node belongs to the class of constant 1
Alan Mishchenko committed
308
        if ( p->pFuncNodeIsConst( pObj ) )
Alan Mishchenko committed
309 310
        {
            Vec_PtrPush( p->vClasses1, pObj );
Alan Mishchenko committed
311
            Fra_ClassObjSetRepr( pObj, Aig_ManConst1(p->pAig) );
Alan Mishchenko committed
312 313
            continue;
        }
Alan Mishchenko committed
314 315 316 317 318 319 320 321 322 323 324
        // add the node to the class
        if ( ppTable[iEntry] == NULL )
        {
            ppTable[iEntry] = pObj;
            Fra_ObjSetNext( ppNexts, pObj, pObj );
        }
        else
        {
            Fra_ObjSetNext( ppNexts, pObj, Fra_ObjNext(ppNexts,ppTable[iEntry]) );
            Fra_ObjSetNext( ppNexts, ppTable[iEntry], pObj );
        }
Alan Mishchenko committed
325
    }
Alan Mishchenko committed
326

Alan Mishchenko committed
327
    // count the total number of nodes in the non-trivial classes
Alan Mishchenko committed
328
    // mark the representative nodes of each equivalence class
Alan Mishchenko committed
329 330
    nEntries = 0;
    for ( i = 0; i < nTableSize; i++ )
Alan Mishchenko committed
331
        if ( ppTable[i] && ppTable[i] != Fra_ObjNext(ppNexts, ppTable[i]) )
Alan Mishchenko committed
332
        {
Alan Mishchenko committed
333 334 335 336 337 338 339 340
            for ( pTemp = Fra_ObjNext(ppNexts, ppTable[i]), k = 1; 
                  pTemp != ppTable[i]; 
                  pTemp = Fra_ObjNext(ppNexts, pTemp), k++ );
            assert( k > 1 );
            nEntries += k;
            // mark the node
            assert( ppTable[i]->fMarkA == 0 );
            ppTable[i]->fMarkA = 1;
Alan Mishchenko committed
341
        }
Alan Mishchenko committed
342

Alan Mishchenko committed
343
    // allocate room for classes
Alan Mishchenko committed
344
    p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, 2*(nEntries + Vec_PtrSize(p->vClasses1)) );
Alan Mishchenko committed
345
    p->pMemClassesFree = p->pMemClasses + 2*nEntries;
Alan Mishchenko committed
346
 
Alan Mishchenko committed
347
    // copy the entries into storage in the topological order
Alan Mishchenko committed
348 349
    Vec_PtrClear( p->vClasses );
    nEntries = 0;
Alan Mishchenko committed
350
    Aig_ManForEachObj( p->pAig, pObj, i )
Alan Mishchenko committed
351
    {
352
        if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
Alan Mishchenko committed
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
            continue;
        // skip the nodes that are not representatives of non-trivial classes
        if ( pObj->fMarkA == 0 )
            continue;
        pObj->fMarkA = 0;
        // add the class of nodes
        Vec_PtrPush( p->vClasses, p->pMemClasses + 2*nEntries );
        // count the number of entries in this class
        for ( pTemp = Fra_ObjNext(ppNexts, pObj), k = 1; 
              pTemp != pObj; 
              pTemp = Fra_ObjNext(ppNexts, pTemp), k++ );
        nNodes = k;
        assert( nNodes > 1 );
        // add the nodes to the class in the topological order
        p->pMemClasses[2*nEntries] = pObj;
        for ( pTemp = Fra_ObjNext(ppNexts, pObj), k = 1; 
              pTemp != pObj; 
              pTemp = Fra_ObjNext(ppNexts, pTemp), k++ )
Alan Mishchenko committed
371
        {
Alan Mishchenko committed
372
            p->pMemClasses[2*nEntries+nNodes-k] = pTemp;
Alan Mishchenko committed
373
            Fra_ClassObjSetRepr( pTemp, pObj );
Alan Mishchenko committed
374
        }
Alan Mishchenko committed
375 376 377 378 379
        // add as many empty entries
        p->pMemClasses[2*nEntries + nNodes] = NULL;
        // increment the number of entries
        nEntries += k;
    }
Alan Mishchenko committed
380 381
    ABC_FREE( ppTable );
    ABC_FREE( ppNexts );
Alan Mishchenko committed
382
    // now it is time to refine the classes
Alan Mishchenko committed
383
    Fra_ClassesRefine( p );
Alan Mishchenko committed
384
//    Fra_ClassesPrint( p, 0 );
Alan Mishchenko committed
385 386 387 388 389 390 391 392 393 394 395 396 397
}

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

  Synopsis    [Refines one class using simulation info.]

  Description [Returns the new class if refinement happened.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
398
Aig_Obj_t ** Fra_RefineClassOne( Fra_Cla_t * p, Aig_Obj_t ** ppClass )
Alan Mishchenko committed
399
{
Alan Mishchenko committed
400
    Aig_Obj_t * pObj, ** ppThis;
Alan Mishchenko committed
401
    int i;
Alan Mishchenko committed
402
    assert( ppClass[0] != NULL && ppClass[1] != NULL );
Alan Mishchenko committed
403

Alan Mishchenko committed
404
    // check if the class is going to be refined
Alan Mishchenko committed
405
    for ( ppThis = ppClass + 1; (pObj = *ppThis); ppThis++ )        
Alan Mishchenko committed
406
        if ( !p->pFuncNodesAreEqual(ppClass[0], pObj) )
Alan Mishchenko committed
407 408 409 410 411 412
            break;
    if ( pObj == NULL )
        return NULL;
    // split the class
    Vec_PtrClear( p->vClassOld );
    Vec_PtrClear( p->vClassNew );
Alan Mishchenko committed
413
    Vec_PtrPush( p->vClassOld, ppClass[0] );
Alan Mishchenko committed
414
    for ( ppThis = ppClass + 1; (pObj = *ppThis); ppThis++ )        
Alan Mishchenko committed
415
        if ( p->pFuncNodesAreEqual(ppClass[0], pObj) )
Alan Mishchenko committed
416 417 418
            Vec_PtrPush( p->vClassOld, pObj );
        else
            Vec_PtrPush( p->vClassNew, pObj );
Alan Mishchenko committed
419 420
/*
    printf( "Refining class (" );
421
    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i )
Alan Mishchenko committed
422 423
        printf( "%d,", pObj->Id );
    printf( ") + (" );
424
    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
Alan Mishchenko committed
425 426 427
        printf( "%d,", pObj->Id );
    printf( ")\n" );
*/
Alan Mishchenko committed
428
    // put the nodes back into the class memory
429
    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i )
Alan Mishchenko committed
430
    {
Alan Mishchenko committed
431 432
        ppClass[i] = pObj;
        ppClass[Vec_PtrSize(p->vClassOld)+i] = NULL;
Alan Mishchenko committed
433
        Fra_ClassObjSetRepr( pObj, i? ppClass[0] : NULL );
Alan Mishchenko committed
434
    }
Alan Mishchenko committed
435
    ppClass += 2*Vec_PtrSize(p->vClassOld);
Alan Mishchenko committed
436
    // put the new nodes into the class memory
437
    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
Alan Mishchenko committed
438
    {
Alan Mishchenko committed
439 440
        ppClass[i] = pObj;
        ppClass[Vec_PtrSize(p->vClassNew)+i] = NULL;
Alan Mishchenko committed
441
        Fra_ClassObjSetRepr( pObj, i? ppClass[0] : NULL );
Alan Mishchenko committed
442
    }
Alan Mishchenko committed
443
    return ppClass;
Alan Mishchenko committed
444 445 446 447 448 449 450 451 452 453 454 455 456
}

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

  Synopsis    [Iteratively refines the classes after simulation.]

  Description [Returns the number of refinements performed.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
457
int Fra_RefineClassLastIter( Fra_Cla_t * p, Vec_Ptr_t * vClasses )
Alan Mishchenko committed
458
{
Alan Mishchenko committed
459
    Aig_Obj_t ** pClass, ** pClass2;
Alan Mishchenko committed
460
    int nRefis;
461
    pClass = (Aig_Obj_t **)Vec_PtrEntryLast( vClasses );
Alan Mishchenko committed
462
    for ( nRefis = 0; (pClass2 = Fra_RefineClassOne( p, pClass )); nRefis++ )
Alan Mishchenko committed
463 464 465 466 467 468
    {
        // if the original class is trivial, remove it
        if ( pClass[1] == NULL )
            Vec_PtrPop( vClasses );
        // if the new class is trivial, stop
        if ( pClass2[1] == NULL )
Alan Mishchenko committed
469 470
        {
            nRefis++;
Alan Mishchenko committed
471
            break;
Alan Mishchenko committed
472
        }
Alan Mishchenko committed
473
        // othewise, add the class and continue
Alan Mishchenko committed
474
        assert( pClass2[0] != NULL );
Alan Mishchenko committed
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492
        Vec_PtrPush( vClasses, pClass2 );
        pClass = pClass2;
    }
    return nRefis;
}

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

  Synopsis    [Refines the classes after simulation.]

  Description [Assumes that simulation info is assigned. Returns the
  number of classes refined.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
493
int Fra_ClassesRefine( Fra_Cla_t * p )
Alan Mishchenko committed
494 495
{
    Vec_Ptr_t * vTemp;
Alan Mishchenko committed
496
    Aig_Obj_t ** pClass;
Alan Mishchenko committed
497
    int i, nRefis;
Alan Mishchenko committed
498
    // refine the classes
Alan Mishchenko committed
499
    nRefis = 0;
Alan Mishchenko committed
500
    Vec_PtrClear( p->vClassesTemp );
501
    Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i )
Alan Mishchenko committed
502 503
    {
        // add the class to the new array
Alan Mishchenko committed
504
        assert( pClass[0] != NULL );
Alan Mishchenko committed
505
        Vec_PtrPush( p->vClassesTemp, pClass );
Alan Mishchenko committed
506
        // refine the class iteratively
Alan Mishchenko committed
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
        nRefis += Fra_RefineClassLastIter( p, p->vClassesTemp );
    }
    // exchange the class representation
    vTemp = p->vClassesTemp;
    p->vClassesTemp = p->vClasses;
    p->vClasses = vTemp;
    return nRefis;
}

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

  Synopsis    [Refines constant 1 equivalence class.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
527
int Fra_ClassesRefine1( Fra_Cla_t * p, int fRefineNewClass, int * pSkipped )
Alan Mishchenko committed
528
{
Alan Mishchenko committed
529
    Aig_Obj_t * pObj, ** ppClass;
Alan Mishchenko committed
530
    int i, k, nRefis = 1;
Alan Mishchenko committed
531 532 533 534
    // check if there is anything to refine
    if ( Vec_PtrSize(p->vClasses1) == 0 )
        return 0;
    // make sure constant 1 class contains only non-constant nodes
Alan Mishchenko committed
535
    assert( Vec_PtrEntry(p->vClasses1,0) != Aig_ManConst1(p->pAig) );
Alan Mishchenko committed
536 537
    // collect all the nodes to be refined
    k = 0;
Alan Mishchenko committed
538
    Vec_PtrClear( p->vClassNew );
539
    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClasses1, pObj, i )
Alan Mishchenko committed
540
    {
Alan Mishchenko committed
541
        if ( p->pFuncNodeIsConst( pObj ) )
Alan Mishchenko committed
542 543 544 545 546 547 548
            Vec_PtrWriteEntry( p->vClasses1, k++, pObj );
        else 
            Vec_PtrPush( p->vClassNew, pObj );
    }
    Vec_PtrShrink( p->vClasses1, k );
    if ( Vec_PtrSize(p->vClassNew) == 0 )
        return 0;
Alan Mishchenko committed
549 550
/*
    printf( "Refined const-1 class: {" );
551
    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
Alan Mishchenko committed
552 553 554
        printf( " %d", pObj->Id );
    printf( " }\n" );
*/
Alan Mishchenko committed
555
    if ( Vec_PtrSize(p->vClassNew) == 1 )
Alan Mishchenko committed
556
    {
557
        Fra_ClassObjSetRepr( (Aig_Obj_t *)Vec_PtrEntry(p->vClassNew,0), NULL );
Alan Mishchenko committed
558
        return 1;
Alan Mishchenko committed
559
    }
Alan Mishchenko committed
560
    // create a new class composed of these nodes
Alan Mishchenko committed
561
    ppClass = p->pMemClassesFree;
Alan Mishchenko committed
562
    p->pMemClassesFree += 2 * Vec_PtrSize(p->vClassNew);
563
    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
Alan Mishchenko committed
564
    {
Alan Mishchenko committed
565 566
        ppClass[i] = pObj;
        ppClass[Vec_PtrSize(p->vClassNew)+i] = NULL;
Alan Mishchenko committed
567
        Fra_ClassObjSetRepr( pObj, i? ppClass[0] : NULL );
Alan Mishchenko committed
568
    }
Alan Mishchenko committed
569
    assert( ppClass[0] != NULL );
Alan Mishchenko committed
570
    Vec_PtrPush( p->vClasses, ppClass );
Alan Mishchenko committed
571
    // iteratively refine this class
Alan Mishchenko committed
572 573 574 575
    if ( fRefineNewClass )
        nRefis += Fra_RefineClassLastIter( p, p->vClasses );
    else if ( pSkipped )
        (*pSkipped)++;
Alan Mishchenko committed
576
    return nRefis;
Alan Mishchenko committed
577 578
}

Alan Mishchenko committed
579 580 581 582 583 584 585 586 587 588 589 590 591 592
/**Function*************************************************************

  Synopsis    [Starts representation of equivalence classes with one class.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Fra_ClassesTest( Fra_Cla_t * p, int Id1, int Id2 )
{
    Aig_Obj_t ** pClass;
Alan Mishchenko committed
593
    p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, 4 );
Alan Mishchenko committed
594 595 596 597 598 599 600 601 602 603
    pClass = p->pMemClasses;
    assert( Id1 < Id2 );
    pClass[0] = Aig_ManObj( p->pAig, Id1 );
    pClass[1] = Aig_ManObj( p->pAig, Id2 );
    pClass[2] = NULL;
    pClass[3] = NULL;
    Fra_ClassObjSetRepr( pClass[1], pClass[0] );
    Vec_PtrPush( p->vClasses, pClass );
}

Alan Mishchenko committed
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625
/**Function*************************************************************

  Synopsis    [Creates latch correspondence classes.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Fra_ClassesLatchCorr( Fra_Man_t * p )
{
    Aig_Obj_t * pObj;
    int i, nEntries = 0;
    Vec_PtrClear( p->pCla->vClasses1 );
    Aig_ManForEachLoSeq( p->pManAig, pObj, i )
    {
        Vec_PtrPush( p->pCla->vClasses1, pObj );
        Fra_ClassObjSetRepr( pObj, Aig_ManConst1(p->pManAig) );
    }
    // allocate room for classes
Alan Mishchenko committed
626
    p->pCla->pMemClasses = ABC_ALLOC( Aig_Obj_t *, 2*(nEntries + Vec_PtrSize(p->pCla->vClasses1)) );
Alan Mishchenko committed
627 628 629
    p->pCla->pMemClassesFree = p->pCla->pMemClasses + 2*nEntries;
}

Alan Mishchenko committed
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
/**Function*************************************************************

  Synopsis    [Postprocesses the classes by removing half of the less useful.]

  Description []
               
  SideEffects [] 

  SeeAlso     []

***********************************************************************/
void Fra_ClassesPostprocess( Fra_Cla_t * p )
{
    int Ratio = 2;
    Fra_Sml_t * pComb;
    Aig_Obj_t * pObj, * pRepr, ** ppClass;
    int * pWeights, WeightMax = 0, i, k, c;
    // perform combinational simulation
648
    pComb = Fra_SmlSimulateComb( p->pAig, 32, 0 );
Alan Mishchenko committed
649
    // compute the weight of each node in the classes
Alan Mishchenko committed
650
    pWeights = ABC_ALLOC( int, Aig_ManObjNumMax(p->pAig) );
Alan Mishchenko committed
651
    memset( pWeights, 0, sizeof(int) * Aig_ManObjNumMax(p->pAig) );
Alan Mishchenko committed
652 653 654 655 656 657
    Aig_ManForEachObj( p->pAig, pObj, i )
    { 
        pRepr = Fra_ClassObjRepr( pObj );
        if ( pRepr == NULL )
            continue;
        pWeights[i] = Fra_SmlNodeNotEquWeight( pComb, pRepr->Id, pObj->Id );
658
        WeightMax = Abc_MaxInt( WeightMax, pWeights[i] );
Alan Mishchenko committed
659 660 661 662 663
    }
    Fra_SmlStop( pComb );
    printf( "Before: Const = %6d. Class = %6d.  ", Vec_PtrSize(p->vClasses1), Vec_PtrSize(p->vClasses) );
    // remove nodes from classes whose weight is less than WeightMax/Ratio
    k = 0;
664
    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClasses1, pObj, i )
Alan Mishchenko committed
665 666 667 668 669 670 671 672
    {
        if ( pWeights[pObj->Id] >= WeightMax/Ratio )
            Vec_PtrWriteEntry( p->vClasses1, k++, pObj );
        else
            Fra_ClassObjSetRepr( pObj, NULL );
    }
    Vec_PtrShrink( p->vClasses1, k );
    // in each class, compact the nodes
673
    Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, ppClass, i )
Alan Mishchenko committed
674 675 676 677 678 679 680 681 682 683 684 685 686
    {
        k = 1;
        for ( c = 1; ppClass[c]; c++ )
        {
            if ( pWeights[ppClass[c]->Id] >= WeightMax/Ratio )
                ppClass[k++] = ppClass[c];
            else
                Fra_ClassObjSetRepr( ppClass[c], NULL );
        }
        ppClass[k] = NULL;
    }
    // remove classes with only repr
    k = 0;
687
    Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, ppClass, i )
Alan Mishchenko committed
688 689 690 691
        if ( ppClass[1] != NULL )
            Vec_PtrWriteEntry( p->vClasses, k++, ppClass );
    Vec_PtrShrink( p->vClasses, k );
    printf( "After: Const = %6d. Class = %6d. \n", Vec_PtrSize(p->vClasses1), Vec_PtrSize(p->vClasses) );
Alan Mishchenko committed
692
    ABC_FREE( pWeights );
Alan Mishchenko committed
693 694
}

Alan Mishchenko committed
695 696
/**Function*************************************************************

Alan Mishchenko committed
697 698 699 700 701 702 703 704 705 706 707 708 709 710
  Synopsis    [Postprocesses the classes by selecting representative lowest in top order.]

  Description []
               
  SideEffects [] 

  SeeAlso     []

***********************************************************************/
void Fra_ClassesSelectRepr( Fra_Cla_t * p )
{
    Aig_Obj_t ** pClass, * pNodeMin;
    int i, c, cMinSupp, nSuppSizeMin, nSuppSizeCur;
    // reassign representatives in each class
711
    Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i )
Alan Mishchenko committed
712 713
    {
        // collect support sizes and find the min-support node
Alan Mishchenko committed
714
        cMinSupp = -1;
Alan Mishchenko committed
715
        pNodeMin = NULL;
Alan Mishchenko committed
716
        nSuppSizeMin = ABC_INFINITY;
Alan Mishchenko committed
717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 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
        for ( c = 0; pClass[c]; c++ )
        {
            nSuppSizeCur = Aig_SupportSize( p->pAig, pClass[c] );
//            nSuppSizeCur = 1;
            if ( nSuppSizeMin > nSuppSizeCur || 
                (nSuppSizeMin == nSuppSizeCur && pNodeMin->Level > pClass[c]->Level) )
            {
                nSuppSizeMin = nSuppSizeCur;
                pNodeMin = pClass[c];
                cMinSupp = c; 
            }
        }
        // skip the case when the repr did not change
        if ( cMinSupp == 0 )
            continue;
        // make the new node the representative of the class
        pClass[cMinSupp] = pClass[0];
        pClass[0] = pNodeMin;
        // set the representative
        for ( c = 0; pClass[c]; c++ )
            Fra_ClassObjSetRepr( pClass[c], c? pClass[0] : NULL );
    }
}



static inline Aig_Obj_t * Fra_ObjEqu( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj )                       { return ppEquivs[pObj->Id];  }
static inline void        Fra_ObjSetEqu( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { ppEquivs[pObj->Id] = pNode; }

static inline Aig_Obj_t * Fra_ObjChild0Equ( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj ) { return Aig_NotCond(Fra_ObjEqu(ppEquivs,Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj));  }
static inline Aig_Obj_t * Fra_ObjChild1Equ( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj ) { return Aig_NotCond(Fra_ObjEqu(ppEquivs,Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj));  }

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

  Synopsis    [Add the node and its constraints to the new AIG.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline void Fra_ClassesDeriveNode( Aig_Man_t * pManFraig, Aig_Obj_t * pObj, Aig_Obj_t ** ppEquivs )
{
    Aig_Obj_t * pObjNew, * pObjRepr, * pObjReprNew, * pMiter;//, * pObjNew2;
    // skip nodes without representative
    if ( (pObjRepr = Fra_ClassObjRepr(pObj)) == NULL )
        return;
    assert( pObjRepr->Id < pObj->Id );
    // get the new node 
    pObjNew = Fra_ObjEqu( ppEquivs, pObj );
    // get the new node of the representative
    pObjReprNew = Fra_ObjEqu( ppEquivs, pObjRepr );
    // 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_ObjSetEqu( ppEquivs, pObj, pObjNew2 );
    // add the constraint
    pMiter = Aig_Exor( pManFraig, Aig_Regular(pObjNew), Aig_Regular(pObjReprNew) );
    pMiter = Aig_NotCond( pMiter, Aig_Regular(pMiter)->fPhase ^ Aig_IsComplement(pMiter) );
    pMiter = Aig_Not( pMiter );
782
    Aig_ObjCreateCo( pManFraig, pMiter );
Alan Mishchenko committed
783 784 785 786
}

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

Alan Mishchenko committed
787 788 789 790 791 792 793 794 795 796 797
  Synopsis    [Derives AIG for the partitioned problem.]

  Description []
               
  SideEffects [] 

  SeeAlso     []

***********************************************************************/
Aig_Man_t * Fra_ClassesDeriveAig( Fra_Cla_t * p, int nFramesK )
{
Alan Mishchenko committed
798 799 800 801 802
    Aig_Man_t * pManFraig;
    Aig_Obj_t * pObj, * pObjNew;
    Aig_Obj_t ** pLatches, ** ppEquivs;
    int i, k, f, nFramesAll = nFramesK + 1;
    assert( Aig_ManRegNum(p->pAig) > 0 );
803
    assert( Aig_ManRegNum(p->pAig) < Aig_ManCiNum(p->pAig) );
Alan Mishchenko committed
804 805
    assert( nFramesK > 0 );
    // start the fraig package
Alan Mishchenko committed
806
    pManFraig = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * nFramesAll );
807 808
    pManFraig->pName = Abc_UtilStrsav( p->pAig->pName );
    pManFraig->pSpec = Abc_UtilStrsav( p->pAig->pSpec );
Alan Mishchenko committed
809
    // allocate place for the node mapping
Alan Mishchenko committed
810
    ppEquivs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) );
Alan Mishchenko committed
811 812 813
    Fra_ObjSetEqu( ppEquivs, Aig_ManConst1(p->pAig), Aig_ManConst1(pManFraig) );
    // create latches for the first frame
    Aig_ManForEachLoSeq( p->pAig, pObj, i )
814
        Fra_ObjSetEqu( ppEquivs, pObj, Aig_ObjCreateCi(pManFraig) );
Alan Mishchenko committed
815
    // add timeframes
Alan Mishchenko committed
816
    pLatches = ABC_ALLOC( Aig_Obj_t *, Aig_ManRegNum(p->pAig) );
Alan Mishchenko committed
817 818 819 820
    for ( f = 0; f < nFramesAll; f++ )
    {
        // create PIs for this frame
        Aig_ManForEachPiSeq( p->pAig, pObj, i )
821
            Fra_ObjSetEqu( ppEquivs, pObj, Aig_ObjCreateCi(pManFraig) );
Alan Mishchenko committed
822 823 824 825 826 827 828 829 830 831 832 833 834
        // set the constraints on the latch outputs
        Aig_ManForEachLoSeq( p->pAig, pObj, i )
            Fra_ClassesDeriveNode( pManFraig, pObj, ppEquivs );
        // add internal nodes of this frame
        Aig_ManForEachNode( p->pAig, pObj, i )
        {
            pObjNew = Aig_And( pManFraig, Fra_ObjChild0Equ(ppEquivs, pObj), Fra_ObjChild1Equ(ppEquivs, pObj) );
            Fra_ObjSetEqu( ppEquivs, pObj, pObjNew );
            Fra_ClassesDeriveNode( pManFraig, pObj, ppEquivs );
        }
        if ( f == nFramesAll - 1 )
            break;
        if ( f == nFramesAll - 2 )
835
            pManFraig->nAsserts = Aig_ManCoNum(pManFraig);
Alan Mishchenko committed
836 837 838 839 840 841 842 843 844
        // save the latch input values
        k = 0;
        Aig_ManForEachLiSeq( p->pAig, pObj, i )
            pLatches[k++] = Fra_ObjChild0Equ( ppEquivs, pObj );
        // insert them to the latch output values
        k = 0;
        Aig_ManForEachLoSeq( p->pAig, pObj, i )
            Fra_ObjSetEqu( ppEquivs, pObj, pLatches[k++] );
    }
Alan Mishchenko committed
845 846
    ABC_FREE( pLatches );
    ABC_FREE( ppEquivs );
Alan Mishchenko committed
847
    // mark the asserts
848
    assert( Aig_ManCoNum(pManFraig) % nFramesAll == 0 );
Alan Mishchenko committed
849
printf( "Assert miters = %6d. Output miters = %6d.\n", 
850
       pManFraig->nAsserts, Aig_ManCoNum(pManFraig) - pManFraig->nAsserts );
Alan Mishchenko committed
851 852 853
    // remove dangling nodes
    Aig_ManCleanup( pManFraig );
    return pManFraig;
Alan Mishchenko committed
854 855
}

Alan Mishchenko committed
856 857 858 859 860
////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


861 862
ABC_NAMESPACE_IMPL_END