ifTruth.c 15.5 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    [ifTruth.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [FPGA mapping based on priority cuts.]

  Synopsis    [Computation of truth tables of the cuts.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - November 21, 2006.]

  Revision    [$Id: ifTruth.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]

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

#include "if.h"
22
#include "bool/kit/kit.h"
23
#include "misc/extra/extra.h"
Alan Mishchenko committed
24

25 26 27
ABC_NAMESPACE_IMPL_START


Alan Mishchenko committed
28 29 30 31
////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

Alan Mishchenko committed
32
//#define IF_TRY_NEW
Alan Mishchenko committed
33 34 35 36 37 38 39

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

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

40
  Synopsis    [Sorts the pins in the decreasing order of delays.]
Alan Mishchenko committed
41 42 43 44 45 46 47 48

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
49
void If_CutTruthPermute( word * pTruth, int nLeaves, int nVars, int nWords, float * pDelays, int * pVars )
Alan Mishchenko committed
50
{
51
    while ( 1 )
Alan Mishchenko committed
52
    {
53 54
        int i, fChange = 0;
        for ( i = 0; i < nLeaves - 1; i++ )
Alan Mishchenko committed
55 56 57
        {
            if ( pDelays[i] >= pDelays[i+1] )
                continue;
58 59 60 61
            ABC_SWAP( float, pDelays[i], pDelays[i+1] );
            ABC_SWAP( int, pVars[i], pVars[i+1] );
            if ( pTruth )
                Abc_TtSwapAdjacent( pTruth, nWords, i );
Alan Mishchenko committed
62
            fChange = 1;
63
        }
64 65
        if ( !fChange )
            return;
66 67
    }
}
68
void If_CutRotatePins( If_Man_t * p, If_Cut_t * pCut )
69
{
70 71 72
    If_Obj_t * pLeaf;
    float PinDelays[IF_MAX_LUTSIZE];
    int i, truthId;
73
    assert( !p->pPars->fUseTtPerm );
74 75
    If_CutForEachLeaf( p, pCut, pLeaf, i )
        PinDelays[i] = If_ObjCutBest(pLeaf)->Delay;
76
    if ( p->vTtMem[pCut->nLeaves] == NULL )
77
    {
78
        If_CutTruthPermute( NULL, If_CutLeaveNum(pCut), pCut->nLeaves, p->nTruth6Words[pCut->nLeaves], PinDelays, If_CutLeaves(pCut) );
79
        return;
80
    }
81 82 83
    Abc_TtCopy( p->puTempW, If_CutTruthWR(p, pCut), p->nTruth6Words[pCut->nLeaves], 0 );
    If_CutTruthPermute( p->puTempW, If_CutLeaveNum(pCut), pCut->nLeaves, p->nTruth6Words[pCut->nLeaves], PinDelays, If_CutLeaves(pCut) );
    truthId        = Vec_MemHashInsert( p->vTtMem[pCut->nLeaves], p->puTempW );
84 85
    pCut->iCutFunc = Abc_Var2Lit( truthId, If_CutTruthIsCompl(pCut) );
    assert( (p->puTempW[0] & 1) == 0 );
86 87
}

88 89 90 91 92 93 94 95 96 97 98
/**Function*************************************************************

  Synopsis    [Truth table computation.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
99
int If_CutComputeTruth( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 )
100
{
101
    int fCompl, truthId, nLeavesNew, PrevSize, RetValue = 0;
102 103
    word * pTruth0s = Vec_MemReadEntry( p->vTtMem[pCut0->nLeaves], Abc_Lit2Var(pCut0->iCutFunc) );
    word * pTruth1s = Vec_MemReadEntry( p->vTtMem[pCut1->nLeaves], Abc_Lit2Var(pCut1->iCutFunc) );
104 105 106
    word * pTruth0  = (word *)p->puTemp[0];
    word * pTruth1  = (word *)p->puTemp[1];
    word * pTruth   = (word *)p->puTemp[2];
107 108
    Abc_TtCopy( pTruth0, pTruth0s, p->nTruth6Words[pCut0->nLeaves], fCompl0 ^ pCut0->fCompl ^ Abc_LitIsCompl(pCut0->iCutFunc) );
    Abc_TtCopy( pTruth1, pTruth1s, p->nTruth6Words[pCut1->nLeaves], fCompl1 ^ pCut1->fCompl ^ Abc_LitIsCompl(pCut1->iCutFunc) );
109 110
    Abc_TtStretch6( pTruth0, pCut0->nLeaves, pCut->nLeaves );
    Abc_TtStretch6( pTruth1, pCut1->nLeaves, pCut->nLeaves );
111 112
    Abc_TtExpand( pTruth0, pCut->nLeaves, pCut0->pLeaves, pCut0->nLeaves, pCut->pLeaves, pCut->nLeaves );
    Abc_TtExpand( pTruth1, pCut->nLeaves, pCut1->pLeaves, pCut1->nLeaves, pCut->pLeaves, pCut->nLeaves );
113
    fCompl         = (pTruth0[0] & pTruth1[0] & 1);
114
    Abc_TtAnd( pTruth, pTruth0, pTruth1, p->nTruth6Words[pCut->nLeaves], fCompl );
115
    if ( p->pPars->fCutMin && (pCut0->nLeaves + pCut1->nLeaves > pCut->nLeaves || pCut0->nLeaves == 0 || pCut1->nLeaves == 0) )
116
    {
117
        nLeavesNew = Abc_TtMinBase( pTruth, pCut->pLeaves, pCut->nLeaves, pCut->nLeaves );
118 119 120 121
        if ( nLeavesNew < If_CutLeaveNum(pCut) )
        {
            pCut->nLeaves = nLeavesNew;
            pCut->uSign   = If_ObjCutSignCompute( pCut );
122
            RetValue      = 1;
123 124
        }
    }
125
    PrevSize       = Vec_MemEntryNum( p->vTtMem[pCut->nLeaves] );   
126
    truthId        = Vec_MemHashInsert( p->vTtMem[pCut->nLeaves], pTruth );
127
    pCut->iCutFunc = Abc_Var2Lit( truthId, fCompl );
128
    assert( (pTruth[0] & 1) == 0 );
129 130 131 132
#ifdef IF_TRY_NEW
    {
        word pCopy[1024];
        char pCanonPerm[16];
133
        memcpy( pCopy, If_CutTruthW(pCut), sizeof(word) * p->nTruth6Words[pCut->nLeaves] );
134
        Abc_TtCanonicize( pCopy, pCut->nLeaves, pCanonPerm );
135 136
    }
#endif
137 138 139 140 141 142 143 144 145 146 147 148 149
    if ( p->vTtIsops[pCut->nLeaves] && PrevSize != Vec_MemEntryNum(p->vTtMem[pCut->nLeaves]) )
    {
        Vec_Int_t * vLevel = Vec_WecPushLevel( p->vTtIsops[pCut->nLeaves] );
        fCompl = Kit_TruthIsop( (unsigned *)pTruth, pCut->nLeaves, p->vCover, 1 );
        if ( fCompl >= 0 )
        {
            Vec_IntGrow( vLevel, Vec_IntSize(p->vCover) );
            Vec_IntAppend( vLevel, p->vCover );
            if ( fCompl )
                vLevel->nCap ^= (1<<16); // hack to remember complemented attribute
        }
        assert( Vec_WecSize(p->vTtIsops[pCut->nLeaves]) == Vec_MemEntryNum(p->vTtMem[pCut->nLeaves]) );
    }
150
    return RetValue;
151
}
152

153 154 155 156 157 158 159 160 161 162 163
/**Function*************************************************************

  Synopsis    [Truth table computation.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
164
int If_CutComputeTruthPerm_int( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int iCutFunc0, int iCutFunc1 )
165
{
166
    int fVerbose = 0;
167
    abctime clk = 0;
168
    int pPerm[IF_MAX_LUTSIZE];
169
    int v, Place, fCompl, truthId, nLeavesNew, RetValue = 0;
170 171
    word * pTruth0s = Vec_MemReadEntry( p->vTtMem[pCut0->nLeaves], Abc_Lit2Var(iCutFunc0) );
    word * pTruth1s = Vec_MemReadEntry( p->vTtMem[pCut1->nLeaves], Abc_Lit2Var(iCutFunc1) );
172 173 174
    word * pTruth0  = (word *)p->puTemp[0];
    word * pTruth1  = (word *)p->puTemp[1];
    word * pTruth   = (word *)p->puTemp[2];
175 176
    assert( pCut0->uMaskFunc >= 0 );
    assert( pCut1->uMaskFunc >= 0 );
177 178
    Abc_TtCopy( pTruth0, pTruth0s, p->nTruth6Words[pCut0->nLeaves], Abc_LitIsCompl(iCutFunc0) );
    Abc_TtCopy( pTruth1, pTruth1s, p->nTruth6Words[pCut1->nLeaves], Abc_LitIsCompl(iCutFunc1) );
179 180
    Abc_TtStretch6( pTruth0, pCut0->nLeaves, pCut->nLeaves );
    Abc_TtStretch6( pTruth1, pCut1->nLeaves, pCut->nLeaves );
181 182 183

if ( fVerbose )
{
Alan Mishchenko committed
184 185
//Kit_DsdPrintFromTruth( pTruth0, pCut0->nLeaves ); printf( "\n" );
//Kit_DsdPrintFromTruth( pTruth1, pCut1->nLeaves ); printf( "\n" );
186 187 188
}
    // create literals
    for ( v = 0; v < (int)pCut0->nLeaves; v++ )
189
        pCut->pLeaves[v] = Abc_Var2Lit( pCut0->pLeaves[v], If_CutLeafBit(pCut0, v) );
190 191
    for ( v = 0; v < (int)pCut1->nLeaves; v++ )
        if ( p->pPerm[1][v] >= (int)pCut0->nLeaves )
192 193
            pCut->pLeaves[p->pPerm[1][v]] = Abc_Var2Lit( pCut1->pLeaves[v], If_CutLeafBit(pCut1, v) );
        else if ( If_CutLeafBit(pCut0, p->pPerm[1][v]) != If_CutLeafBit(pCut1, v) )
194
            Abc_TtFlip( pTruth1, p->nTruth6Words[pCut1->nLeaves], v );  
195 196 197 198 199 200 201 202
    // permute variables
    for ( v = (int)pCut1->nLeaves; v < (int)pCut->nLeaves; v++ )
        p->pPerm[1][v] = -1;
    for ( v = 0; v < (int)pCut1->nLeaves; v++ )
    {
        Place = p->pPerm[1][v];
        if ( Place == v || Place == -1 )
            continue;
203
        Abc_TtSwapVars( pTruth1, pCut->nLeaves, v, Place );
204 205 206 207 208 209 210
        p->pPerm[1][v] = p->pPerm[1][Place];
        p->pPerm[1][Place] = Place;
        v--;
    }

if ( fVerbose )
{
Alan Mishchenko committed
211 212
//Kit_DsdPrintFromTruth( pTruth0, pCut0->nLeaves ); printf( "\n" );
//Kit_DsdPrintFromTruth( pTruth1, pCut->nLeaves ); printf( "\n" );
213 214 215
}

    // perform operation
216
    Abc_TtAnd( pTruth, pTruth0, pTruth1, p->nTruth6Words[pCut->nLeaves], 0 );
217
    // minimize support
218
    if ( p->pPars->fCutMin && (pCut0->nLeaves + pCut1->nLeaves > pCut->nLeaves || pCut0->nLeaves == 0 || pCut1->nLeaves == 0) )
219
    {
220
        nLeavesNew = Abc_TtMinBase( pTruth, pCut->pLeaves, pCut->nLeaves, pCut->nLeaves );
221 222 223 224 225 226 227
        if ( nLeavesNew < If_CutLeaveNum(pCut) )
        {
            pCut->nLeaves = nLeavesNew;
            RetValue      = 1;
        }
    }
    // compute canonical form
228
if ( p->pPars->fVerbose )
229 230
clk = Abc_Clock();
    p->uCanonPhase = Abc_TtCanonicize( pTruth, pCut->nLeaves, p->pCanonPerm );
231
if ( p->pPars->fVerbose )
232
p->timeCache[3] += Abc_Clock() - clk;
233
    for ( v = 0; v < (int)pCut->nLeaves; v++ )
234
        pPerm[v] = Abc_LitNotCond( pCut->pLeaves[(int)p->pCanonPerm[v]], ((p->uCanonPhase>>v)&1) );
235
    pCut->uMaskFunc = 0;
236 237 238 239
    for ( v = 0; v < (int)pCut->nLeaves; v++ )
    {
        pCut->pLeaves[v] = Abc_Lit2Var(pPerm[v]);
        if ( Abc_LitIsCompl(pPerm[v]) )
240
            pCut->uMaskFunc |= (1 << v);
241 242 243 244 245 246 247
    }
    // create signature after lowering literals
    if ( RetValue )
        pCut->uSign = If_ObjCutSignCompute( pCut );
    else
        assert( pCut->uSign == If_ObjCutSignCompute( pCut ) );

248
    assert( Vec_IntSize(p->vTtOccurs[pCut->nLeaves]) == Vec_MemEntryNum(p->vTtMem[pCut->nLeaves]) );
249
    // hash function
250
    fCompl         = ((p->uCanonPhase >> pCut->nLeaves) & 1);
251
    truthId        = Vec_MemHashInsert( p->vTtMem[pCut->nLeaves], pTruth );
252
    pCut->iCutFunc = Abc_Var2Lit( truthId, fCompl );
253 254 255 256
    // count how many time this truth table is used
    if ( Vec_IntSize(p->vTtOccurs[pCut->nLeaves]) < Vec_MemEntryNum(p->vTtMem[pCut->nLeaves]) )
        Vec_IntPush( p->vTtOccurs[pCut->nLeaves], 0 );
    Vec_IntAddToEntry( p->vTtOccurs[pCut->nLeaves], truthId, 1 );
257 258 259

if ( fVerbose )
{
Alan Mishchenko committed
260 261 262 263 264
//Kit_DsdPrintFromTruth( pTruth, pCut->nLeaves ); printf( "\n" );
//If_CutPrint( pCut0 );
//If_CutPrint( pCut1 );
//If_CutPrint( pCut );
//printf( "%d\n\n", pCut->iCutFunc );
265 266 267
}

    return RetValue;
268
}
269 270
int If_CutComputeTruthPerm( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int iCutFunc0, int iCutFunc1 )
{
271
    abctime clk = 0;
272 273 274
    int i, Num, nEntriesOld, RetValue;
    if ( pCut0->nLeaves + pCut1->nLeaves > pCut->nLeaves || iCutFunc0 < 2 || iCutFunc1 < 2 )
    {
275 276
if ( p->pPars->fVerbose )
clk = Abc_Clock();
277
        RetValue = If_CutComputeTruthPerm_int( p, pCut, pCut0, pCut1, iCutFunc0, iCutFunc1 );
278
if ( p->pPars->fVerbose )
279 280 281
p->timeCache[0] += Abc_Clock() - clk;
        return RetValue;
    }
282 283 284 285 286 287
    assert( pCut0->nLeaves + pCut1->nLeaves == pCut->nLeaves );
    nEntriesOld = Hash_IntManEntryNum(p->vPairHash);
    Num = Hash_Int2ManInsert( p->vPairHash, (iCutFunc0 << 5)|pCut0->nLeaves, (iCutFunc1 << 5)|pCut1->nLeaves, -1 );
    assert( Num > 0 );
    if ( nEntriesOld == Hash_IntManEntryNum(p->vPairHash) )
    {
288
        char * pCanonPerm;
289 290 291 292 293 294 295 296 297
        int v, pPerm[IF_MAX_LUTSIZE];
        pCut->iCutFunc = Vec_IntEntry( p->vPairRes, Num );
        // move complements from the fanin cuts
        for ( v = 0; v < (int)pCut->nLeaves; v++ )
            if ( v < (int)pCut0->nLeaves )
                pCut->pLeaves[v] = Abc_Var2Lit( pCut->pLeaves[v], If_CutLeafBit(pCut0, v) );
            else
                pCut->pLeaves[v] = Abc_Var2Lit( pCut->pLeaves[v], If_CutLeafBit(pCut1, v-(int)pCut0->nLeaves) );
        // reorder the cut
298
        pCanonPerm = Vec_StrEntryP( p->vPairPerms, Num * pCut->nLimit );
299 300 301
        for ( v = 0; v < (int)pCut->nLeaves; v++ )
            pPerm[v] = Abc_LitNotCond( pCut->pLeaves[Abc_Lit2Var((int)pCanonPerm[v])], Abc_LitIsCompl((int)pCanonPerm[v]) );
        // generate the result
302
        pCut->uMaskFunc = 0;
303 304 305 306
        for ( v = 0; v < (int)pCut->nLeaves; v++ )
        {
            pCut->pLeaves[v] = Abc_Lit2Var(pPerm[v]);
            if ( Abc_LitIsCompl(pPerm[v]) )
307
                pCut->uMaskFunc |= (1 << v);
308 309
        }
//        printf( "Found: %d(%d) %d(%d) -> %d(%d)\n", iCutFunc0, pCut0->nLeaves, iCutFunc1, pCut0->nLeaves, pCut->iCutFunc, pCut->nLeaves );
310
        p->nCacheHits++;
311
//p->timeCache[1] += Abc_Clock() - clk;
312 313
        return 0;
    }
314 315
if ( p->pPars->fVerbose )
clk = Abc_Clock();
316
    p->nCacheMisses++;
317 318 319 320 321 322 323 324
    RetValue = If_CutComputeTruthPerm_int( p, pCut, pCut0, pCut1, iCutFunc0, iCutFunc1 );
    assert( RetValue == 0 );
//    printf( "Added: %d(%d) %d(%d) -> %d(%d)\n", iCutFunc0, pCut0->nLeaves, iCutFunc1, pCut0->nLeaves, pCut->iCutFunc, pCut->nLeaves );
    // save the result
    assert( Num == Vec_IntSize(p->vPairRes) );
    Vec_IntPush( p->vPairRes, pCut->iCutFunc );
    // save the permutation
    assert( Num * (int)pCut->nLimit == Vec_StrSize(p->vPairPerms) );
325 326
    for ( i = 0; i < (int)pCut->nLeaves; i++ )
        Vec_StrPush( p->vPairPerms, (char)Abc_Var2Lit((int)p->pCanonPerm[i], ((p->uCanonPhase>>i)&1)) );
327 328
    for ( i = (int)pCut0->nLeaves + (int)pCut1->nLeaves; i < (int)pCut->nLimit; i++ )
        Vec_StrPush( p->vPairPerms, (char)-1 );
329
if ( p->pPars->fVerbose )
330
p->timeCache[2] += Abc_Clock() - clk;
331 332
    return 0;
}
333

334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
/**Function*************************************************************

  Synopsis    [Check the function of 6-input LUT.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Vec_Mem_t * If_DeriveHashTable6( int nVars, word uTruth )
{
    int fVerbose = 0;
    int nMints   = (1 << nVars);
    int nPerms   = Extra_Factorial( nVars );
    int * pComp  = Extra_GreyCodeSchedule( nVars );
    int * pPerm  = Extra_PermSchedule( nVars );
    word Canon   = ABC_CONST(0xFFFFFFFFFFFFFFFF);
    word tCur, tTemp1, tTemp2;
    Vec_Mem_t * vTtMem6 = Vec_MemAllocForTTSimple( nVars );
    int i, p, c;
    for ( i = 0; i < 2; i++ )
    {
        tCur = i ? ~uTruth : uTruth;
        tTemp1 = tCur;
        for ( p = 0; p < nPerms; p++ )
        {
            tTemp2 = tCur;
            for ( c = 0; c < nMints; c++ )
            {
                if ( Canon > tCur )
                    Canon = tCur;
                Vec_MemHashInsert( vTtMem6, &tCur );
                tCur = Abc_Tt6Flip( tCur, pComp[c] );
            }
            assert( tTemp2 == tCur );
            tCur = Abc_Tt6SwapAdjacent( tCur, pPerm[p] );
        }
        assert( tTemp1 == tCur );
    }
    ABC_FREE( pComp );
    ABC_FREE( pPerm );
    if ( fVerbose )
    {
/*
        word * pEntry;
        Vec_MemForEachEntry( vTtMem6, pEntry, i )
        {
            Extra_PrintHex( stdout, (unsigned*)pEntry, nVars );  
            printf( ", " );
            if ( i % 4 == 3 )
                printf( "\n" );
        }
*/
        Extra_PrintHex( stdout, (unsigned*)&uTruth, nVars );  printf( "\n" );
        Extra_PrintHex( stdout, (unsigned*)&Canon,  nVars );  printf( "\n" );
        printf( "Members = %d.\n", Vec_MemEntryNum(vTtMem6) );
    }
    return vTtMem6;
}

int If_CutCheckTruth6( If_Man_t * p, If_Cut_t * pCut )
{
    if ( pCut->nLeaves != 6 )
        return 0;
    if ( p->vTtMem6 == NULL )
        p->vTtMem6 = If_DeriveHashTable6( 6, ABC_CONST(0xfedcba9876543210) );
    if ( *Vec_MemHashLookup( p->vTtMem6, If_CutTruthWR(p, pCut) ) == -1 )
        return 0;
    return 1;
}

Alan Mishchenko committed
407 408 409 410 411
////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


412 413
ABC_NAMESPACE_IMPL_END