giaIff.c 15.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/**CFile****************************************************************

  FileName    [giaIff.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Scalable AIG package.]

  Synopsis    [Hierarchical mapping of AIG with white boxes.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

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

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

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

#include "gia.h"
#include "map/if/if.h"

ABC_NAMESPACE_IMPL_START

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

typedef struct Iff_Man_t_ Iff_Man_t;
struct Iff_Man_t_
{
33 34 35 36 37 38
    Gia_Man_t *     pGia;       // mapped GIA
    If_LibLut_t *   pLib;       // LUT library
    int             nLutSize;   // LUT size
    int             nDegree;    // degree 
    Vec_Flt_t *     vTimes;     // arrival times
    Vec_Int_t *     vMatch[4];  // matches
39 40
};

41 42 43 44
static inline float Iff_ObjTimeId( Iff_Man_t * p, int iObj )                                { return Vec_FltEntry( p->vTimes, iObj );                       }
static inline float Iff_ObjTime( Iff_Man_t * p, Gia_Obj_t * pObj )                          { return Iff_ObjTimeId( p, Gia_ObjId(p->pGia, pObj) );          }
static inline void  Iff_ObjSetTimeId( Iff_Man_t * p, int iObj, float Time )                 { Vec_FltWriteEntry( p->vTimes, iObj, Time );                   }
static inline void  Iff_ObjSetTime( Iff_Man_t * p, Gia_Obj_t * pObj, float Time )           { Iff_ObjSetTimeId( p, Gia_ObjId(p->pGia, pObj), Time );        }
45

46 47 48 49
static inline int   Iff_ObjMatchId( Iff_Man_t * p, int iObj, int Type )                     { return Vec_IntEntry( p->vMatch[Type], iObj );                 }
static inline int   Iff_ObjMatch( Iff_Man_t * p, Gia_Obj_t * pObj, int Type )               { return Iff_ObjMatchId( p, Gia_ObjId(p->pGia, pObj), Type );   }
static inline void  Iff_ObjSetMatchId( Iff_Man_t * p, int iObj, int Type, int Match )       { Vec_IntWriteEntry( p->vMatch[Type], iObj, Match );            }
static inline void  Iff_ObjSetMatch( Iff_Man_t * p, Gia_Obj_t * pObj, int Type, int Match ) { Iff_ObjSetMatchId( p, Gia_ObjId(p->pGia, pObj), Type, Match );}
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92

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

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Iff_Man_t * Gia_ManIffStart( Gia_Man_t * pGia )
{
    Iff_Man_t * p = ABC_CALLOC( Iff_Man_t, 1 );
    p->vTimes    = Vec_FltStartFull( Gia_ManObjNum(pGia) );
    p->vMatch[2] = Vec_IntStartFull( Gia_ManObjNum(pGia) );
    p->vMatch[3] = Vec_IntStartFull( Gia_ManObjNum(pGia) );
    return p;
}
void Gia_ManIffStop( Iff_Man_t * p )
{
    Vec_FltFree( p->vTimes );
    Vec_IntFree( p->vMatch[2] );
    Vec_IntFree( p->vMatch[3] );
    ABC_FREE( p );
}

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

  Synopsis    [Count the number of unique fanins.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
93
int Gia_IffObjCount( Gia_Man_t * pGia, int iObj, int iFaninSkip2, int iFaninSkip3 )
94 95 96 97 98
{
    int i, iFanin, Count = 0;
    Gia_ManIncrementTravId( pGia );
    Gia_LutForEachFanin( pGia, iObj, iFanin, i )
    {
99
        if ( iFanin == iFaninSkip2 || iFanin == iFaninSkip3 )
100 101 102 103 104 105
            continue;
        if ( Gia_ObjIsTravIdCurrentId( pGia, iFanin ) )
            continue;
        Gia_ObjSetTravIdCurrentId( pGia, iFanin );
        Count++;
    }
106
    if ( iFaninSkip2 >= 0 )
107
    {
108
        Gia_LutForEachFanin( pGia, iFaninSkip2, iFanin, i )
109
        {
110
            if ( iFanin == iFaninSkip3 )
111 112 113 114 115 116 117
                continue;
            if ( Gia_ObjIsTravIdCurrentId( pGia, iFanin ) )
                continue;
            Gia_ObjSetTravIdCurrentId( pGia, iFanin );
            Count++;
        }
    }
118
    if ( iFaninSkip3 >= 0 )
119
    {
120
        Gia_LutForEachFanin( pGia, iFaninSkip3, iFanin, i )
121
        {
122
            if ( iFanin == iFaninSkip2 )
123
                continue;
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
            if ( Gia_ObjIsTravIdCurrentId( pGia, iFanin ) )
                continue;
            Gia_ObjSetTravIdCurrentId( pGia, iFanin );
            Count++;
        }
    }
    return Count;
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
144
float Gia_IffObjTimeOne( Iff_Man_t * p, int iObj, int iFaninSkip2, int iFaninSkip3 )
145 146
{
    int i, iFanin;
147
    float DelayMax = -ABC_INFINITY;
148
    Gia_LutForEachFanin( p->pGia, iObj, iFanin, i )
149
        if ( iFanin != iFaninSkip2 && iFanin != iFaninSkip3 && DelayMax < Iff_ObjTimeId(p, iFanin) )
150
            DelayMax = Iff_ObjTimeId(p, iFanin);
151 152
    assert( i == Gia_ObjLutSize(p->pGia, iObj) );
    if ( iFaninSkip2 == -1 )
153
        return DelayMax;
154
    Gia_LutForEachFanin( p->pGia, iFaninSkip2, iFanin, i )
155 156 157 158 159 160
        if ( iFanin != iFaninSkip3 && DelayMax < Iff_ObjTimeId(p, iFanin) )
            DelayMax = Iff_ObjTimeId(p, iFanin);
    if ( iFaninSkip3 == -1 )
        return DelayMax;
    Gia_LutForEachFanin( p->pGia, iFaninSkip3, iFanin, i )
        if ( iFanin != iFaninSkip2 && DelayMax < Iff_ObjTimeId(p, iFanin) )
161 162 163
            DelayMax = Iff_ObjTimeId(p, iFanin);
    assert( DelayMax >= 0 );
    return DelayMax;
164
}
165
float Gia_IffObjTimeTwo( Iff_Man_t * p, int iObj, int * piFanin, float DelayMin )
166 167
{
    int i, iFanin, nSize;
168
    float This;
169 170 171
    *piFanin = -1;
    Gia_LutForEachFanin( p->pGia, iObj, iFanin, i )
    {
172 173
        if ( Gia_ObjIsCi(Gia_ManObj(p->pGia, iFanin)) )
            continue;
174
        This = Gia_IffObjTimeOne( p, iObj, iFanin, -1 );
175 176
        nSize = Gia_IffObjCount( p->pGia, iObj, iFanin, -1 );
        assert( nSize <= p->pLib->LutMax );
177
        This += p->pLib->pLutDelays[nSize][0];
178
        if ( DelayMin > This )
179
        {
180
            DelayMin = This;
181 182 183
            *piFanin = iFanin;
        }
    }
184 185 186 187 188 189 190 191 192 193 194 195 196
    return DelayMin;
}
float Gia_IffObjTimeThree( Iff_Man_t * p, int iObj, int * piFanin, int * piFanin2, float DelayMin )
{
    int i, k, iFanin, iFanin2, nSize;
    float This;
    *piFanin = -1;
    *piFanin2 = -1;
    Gia_LutForEachFanin( p->pGia, iObj, iFanin, i )
    Gia_LutForEachFanin( p->pGia, iObj, iFanin2, k )
    {
        if ( iFanin == iFanin2 )
            continue;
197 198 199 200
        if ( Gia_ObjIsCi(Gia_ManObj(p->pGia, iFanin)) )
            continue;
        if ( Gia_ObjIsCi(Gia_ManObj(p->pGia, iFanin2)) )
            continue;
201 202 203 204 205 206 207 208 209 210 211 212
        This  = Gia_IffObjTimeOne( p, iObj, iFanin, iFanin2 );
        nSize = Gia_IffObjCount( p->pGia, iObj, iFanin, iFanin2 );
        assert( nSize <= p->pLib->LutMax );
        This += p->pLib->pLutDelays[nSize][0];
        if ( DelayMin > This )
        {
            DelayMin  = This;
            *piFanin  = iFanin;
            *piFanin2 = iFanin2;
        }
    }
    return DelayMin;
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Iff_Man_t * Gia_ManIffPerform( Gia_Man_t * pGia, If_LibLut_t * pLib, Tim_Man_t * pTime, int nLutSize, int nDegree )
{
    Iff_Man_t * p;
    Gia_Obj_t * pObj;
230 231
    int iObj, iFanin, iFanin1, iFanin2;
    int CountAll = 0, Count2 = 0, Count3 = 0;
232
    float arrTime1, arrTime2, arrTime3, arrMax = -ABC_INFINITY; 
233
    assert( nDegree == 2 || nDegree == 3 );
234 235 236 237 238 239 240
    // start the mapping manager and set its parameters
    p = Gia_ManIffStart( pGia );
    p->pGia     = pGia;
    p->pLib     = pLib;
    p->nLutSize = nLutSize;
    p->nDegree  = nDegree;
    // compute arrival times of each node
241
    Iff_ObjSetTimeId( p, 0, 0 );
242 243 244 245 246 247 248
    Tim_ManIncrementTravId( pTime );
    Gia_ManForEachObj1( pGia, pObj, iObj )
    {
        if ( Gia_ObjIsAnd(pObj) )
        {
            if ( !Gia_ObjIsLut(pGia, iObj) )
                continue;
249
            CountAll++;
250 251
            // compute arrival times of LUT inputs
            arrTime1 = Gia_IffObjTimeOne( p, iObj, -1, -1 );
252
            arrTime1 += p->pLib->pLutDelays[Gia_ObjLutSize(pGia, iObj)][0];
253
            // compute arrival times of LUT pairs
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
            arrTime2 = Gia_IffObjTimeTwo( p, iObj, &iFanin, arrTime1 );
            if ( nDegree == 2 )
            {
                // set arrival times
                Iff_ObjSetTimeId( p, iObj, arrTime2 );
                if ( arrTime2 < arrTime1 )
                    Iff_ObjSetMatchId( p, iObj, 2, iFanin ), Count2++;                
            }
            else if ( nDegree == 3 )
            {                
                // compute arrival times of LUT triples
                arrTime3 = Gia_IffObjTimeThree( p, iObj, &iFanin1, &iFanin2, arrTime2 );
                // set arrival times
                Iff_ObjSetTimeId( p, iObj, arrTime3 );
                if ( arrTime3 == arrTime1 )
                    continue;
                if ( arrTime3 == arrTime2 )
                    Iff_ObjSetMatchId( p, iObj, 2, iFanin ), Count2++;
                else
                {
274
                    assert( arrTime3 < arrTime2 );
275 276 277 278 279
                    Iff_ObjSetMatchId( p, iObj, 2, iFanin1 );
                    Iff_ObjSetMatchId( p, iObj, 3, iFanin2 ), Count3++;
                }
            }
            else assert( 0 );
280 281 282 283
        }
        else if ( Gia_ObjIsCi(pObj) )
        {
            arrTime1 = Tim_ManGetCiArrival( pTime, Gia_ObjCioId(pObj) );
284
            Iff_ObjSetTime( p, pObj, arrTime1 );
285 286 287
        }
        else if ( Gia_ObjIsCo(pObj) )
        {
288
            arrTime1 = Iff_ObjTimeId( p, Gia_ObjFaninId0p(pGia, pObj) );
289
            Tim_ManSetCoArrival( pTime, Gia_ObjCioId(pObj), arrTime1 );
290
            Iff_ObjSetTime( p, pObj, arrTime1 );
291
            arrMax = Abc_MaxFloat( arrMax, arrTime1 );
292 293 294
        }
        else assert( 0 );
    }
295
    printf( "Max delay = %.2f.  Count1 = %d.  Count2 = %d.  Count3 = %d.\n", 
296
        arrMax, CountAll - Count2 - Count3, Count2, Count3 );
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
    return p;
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     [] 

***********************************************************************/
void Gia_ManIffSelect_rec( Iff_Man_t * p, int iObj, Vec_Int_t * vPacking )
{
313
    int i, iFanin, iFaninSkip2, iFaninSkip3;
314 315 316 317
    if ( Gia_ObjIsTravIdCurrentId( p->pGia, iObj ) )
        return;
    Gia_ObjSetTravIdCurrentId( p->pGia, iObj );
    assert( Gia_ObjIsLut(p->pGia, iObj) );
318 319 320
    iFaninSkip2 = Iff_ObjMatchId(p, iObj, 2);
    iFaninSkip3 = Iff_ObjMatchId(p, iObj, 3);
    if ( iFaninSkip2 == -1 )
321
    {
322
        assert( iFaninSkip3 == -1 );
323 324 325 326 327
        Gia_LutForEachFanin( p->pGia, iObj, iFanin, i )
            Gia_ManIffSelect_rec( p, iFanin, vPacking );
        Vec_IntPush( vPacking, 1 );
        Vec_IntPush( vPacking, iObj );
    }
328
    else if ( iFaninSkip3 == -1 )
329
    {
330
        assert( iFaninSkip2 > 0 );
331
        Gia_LutForEachFanin( p->pGia, iObj, iFanin, i )
332
            if ( iFanin != iFaninSkip2 )
333
                Gia_ManIffSelect_rec( p, iFanin, vPacking );
334
        Gia_LutForEachFanin( p->pGia, iFaninSkip2, iFanin, i )
335 336
            Gia_ManIffSelect_rec( p, iFanin, vPacking );
        Vec_IntPush( vPacking, 2 );
337
        Vec_IntPush( vPacking, iFaninSkip2 );
338 339
        Vec_IntPush( vPacking, iObj );
    }
340 341
    else
    {
342
        assert( iFaninSkip2 > 0 && iFaninSkip3 > 0 );
343
        Gia_LutForEachFanin( p->pGia, iObj, iFanin, i )
344
            if ( iFanin != iFaninSkip2 && iFanin != iFaninSkip3 )
345
                Gia_ManIffSelect_rec( p, iFanin, vPacking );
346
        Gia_LutForEachFanin( p->pGia, iFaninSkip2, iFanin, i )
347 348 349 350
            if ( iFanin != iFaninSkip3 )
                Gia_ManIffSelect_rec( p, iFanin, vPacking );
        Gia_LutForEachFanin( p->pGia, iFaninSkip3, iFanin, i )
            if ( iFanin != iFaninSkip2 )
351
                Gia_ManIffSelect_rec( p, iFanin, vPacking );
352 353
        Vec_IntPush( vPacking, 3 );
        Vec_IntPush( vPacking, iFaninSkip2 );
354
        Vec_IntPush( vPacking, iFaninSkip3 );
355 356 357 358 359 360 361 362 363 364 365 366
        Vec_IntPush( vPacking, iObj );
    }
    Vec_IntAddToEntry( vPacking, 0, 1 );
}
Vec_Int_t * Gia_ManIffSelect( Iff_Man_t * p )
{
    Vec_Int_t * vPacking;
    Gia_Obj_t * pObj; int i;
    vPacking = Vec_IntAlloc( Gia_ManObjNum(p->pGia) );
    Vec_IntPush( vPacking, 0 );
    // mark const0 and PIs
    Gia_ManIncrementTravId( p->pGia );
367
    Gia_ObjSetTravIdCurrentId( p->pGia, 0 );
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
    Gia_ManForEachCi( p->pGia, pObj, i )
        Gia_ObjSetTravIdCurrent( p->pGia, pObj );
    // recursively collect internal nodes
    Gia_ManForEachCo( p->pGia, pObj, i )
        Gia_ManIffSelect_rec( p, Gia_ObjFaninId0p(p->pGia, pObj), vPacking );
    return vPacking;
}

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

  Synopsis    [This command performs hierarhical mapping.]

  Description []
               
  SideEffects []

  SeeAlso     [] 

***********************************************************************/
void Gia_ManIffTest( Gia_Man_t * pGia, If_LibLut_t * pLib, int fVerbose )
{
    Iff_Man_t * p;
390
    Tim_Man_t * pTemp = NULL;
391 392 393 394 395
    int nDegree = -1;
    int nLutSize = Gia_ManLutSizeMax( pGia );
    if ( nLutSize <= 4 )
    {
        nLutSize = 4;
396
        if ( pLib->LutMax == 7 )
397
            nDegree = 2;
398
        else if ( pLib->LutMax == 10 )
399 400
            nDegree = 3;
        else
401
            { printf( "LUT library for packing 4-LUTs should have 7 or 10 inputs.\n" ); return; }
402 403 404 405
    }
    else if ( nLutSize <= 6 )
    {
        nLutSize = 6;
406
        if ( pLib->LutMax == 11 )
407
            nDegree = 2;
408
        else if ( pLib->LutMax == 16 )
409 410
            nDegree = 3;
        else
411
            { printf( "LUT library for packing 6-LUTs should have 11 or 16 inputs.\n" ); return; }
412 413 414 415 416 417 418 419 420 421
    }
    else
    {
        printf( "The LUT size is more than 6.\n" );
        return;
    }
    if ( fVerbose )
        printf( "Performing %d-clustering with %d-LUTs:\n", nDegree, nLutSize );
    // create timing manager
    if ( pGia->pManTime == NULL )
422
        pGia->pManTime = pTemp = Tim_ManStart( Gia_ManCiNum(pGia), Gia_ManCoNum(pGia) );
423
    // perform timing computation
Alan Mishchenko committed
424
    p = Gia_ManIffPerform( pGia, pLib, (Tim_Man_t *)pGia->pManTime, nLutSize, nDegree );
425 426 427 428
    // remove timing manager
    if ( pGia->pManTime == pTemp )
        pGia->pManTime = NULL;
    Tim_ManStopP( (Tim_Man_t **)&pTemp );
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
    // derive clustering
    Vec_IntFreeP( &pGia->vPacking );
    pGia->vPacking = Gia_ManIffSelect( p );
    Gia_ManIffStop( p );
    // print statistics
    if ( fVerbose )
        Gia_ManPrintPackingStats( pGia );
}

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


ABC_NAMESPACE_IMPL_END