diff options
| -rw-r--r-- | abclib.dsp | 4 | ||||
| -rw-r--r-- | src/map/mio/mioUtils.c | 5 | ||||
| -rw-r--r-- | src/opt/sfm/module.make | 3 | ||||
| -rw-r--r-- | src/opt/sfm/sfmArea.c | 380 | ||||
| -rw-r--r-- | src/opt/sfm/sfmDec.c | 5 | 
5 files changed, 396 insertions, 1 deletions
| @@ -2555,6 +2555,10 @@ SOURCE=.\src\opt\sfm\sfm.h  # End Source File  # Begin Source File +SOURCE=.\src\opt\sfm\sfmArea.c +# End Source File +# Begin Source File +  SOURCE=.\src\opt\sfm\sfmCnf.c  # End Source File  # Begin Source File diff --git a/src/map/mio/mioUtils.c b/src/map/mio/mioUtils.c index 5b1185eb..7572b27c 100644 --- a/src/map/mio/mioUtils.c +++ b/src/map/mio/mioUtils.c @@ -733,8 +733,13 @@ Mio_Cell2_t * Mio_CollectRootsNew2( Mio_Library_t * pLib, int nInputs, int * pnG          assert( Mio_AreaCompare2( ppCells + 4, ppCells + iCell - 1 ) <= 0 );      }      // assign IDs +    Mio_LibraryForEachGate( pLib, pGate0 ) +        Mio_GateSetCell( pGate0, -1 );      for ( i = 0; i < iCell; i++ ) +    {          ppCells[i].Id = ppCells[i].pName ? i : -1; +        Mio_GateSetCell( (Mio_Gate_t *)ppCells[i].pMioGate, i ); +    }      // report      if ( fVerbose ) diff --git a/src/opt/sfm/module.make b/src/opt/sfm/module.make index fbdaa2ec..66518e4e 100644 --- a/src/opt/sfm/module.make +++ b/src/opt/sfm/module.make @@ -1,4 +1,5 @@ -SRC +=    src/opt/sfm/sfmCnf.c \ +SRC +=    src/opt/sfm/sfmArea.c \ +    src/opt/sfm/sfmCnf.c \      src/opt/sfm/sfmCore.c \      src/opt/sfm/sfmDec.c \      src/opt/sfm/sfmLib.c \ diff --git a/src/opt/sfm/sfmArea.c b/src/opt/sfm/sfmArea.c new file mode 100644 index 00000000..87f3b511 --- /dev/null +++ b/src/opt/sfm/sfmArea.c @@ -0,0 +1,380 @@ +/**CFile**************************************************************** + +  FileName    [sfmArea.c] + +  SystemName  [ABC: Logic synthesis and verification system.] + +  PackageName [SAT-based optimization using internal don't-cares.] + +  Synopsis    [Area optimization.] + +  Author      [Alan Mishchenko] +   +  Affiliation [UC Berkeley] + +  Date        [Ver. 1.0. Started - June 20, 2005.] + +  Revision    [$Id: sfmArea.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sfmInt.h" +#include "map/mio/mio.h" +#include "misc/util/utilTruth.h" +#include "misc/util/utilNam.h" +#include "map/scl/sclLib.h" +#include "map/scl/sclCon.h" +#include "opt/dau/dau.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +///                        DECLARATIONS                              /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +///                     FUNCTION DEFINITIONS                         /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + +  Synopsis    [Precompute cell parameters.] + +  Description [] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkPrecomputeCellPairs( Mio_Cell2_t * pCells, int nCells ) +{ +    Vec_Int_t * vInfo = Vec_IntAlloc( 1000 ); +    word iBestArea, tCur, iThis; +    int * pPerm[7], nPerms[7], Perm[7], * Perm1, * Perm2; +    int iBestCell, iBestPerm, iBestDiff; +    int i, k, n, v, p, Count = 0; +    int iGate1 = -1, iGate2 = -1; + +    for ( i = 1; i <= 6; i++ ) +        pPerm[i] = Extra_PermSchedule( i ); +    for ( i = 1; i <= 6; i++ ) +        nPerms[i] = Extra_Factorial( i ); + +    for ( i = 2; i < nCells; i++ ) +    { +        int nFanins = pCells[i].nFanins; +        for ( n = 0; n <= nFanins; n++ ) +        { +            // get the truth table +            iThis = (n == nFanins) ? ~pCells[i].uTruth : Abc_Tt6Flip(pCells[i].uTruth, n); +            // init the comparison +            iBestArea = ~((word)0); +            iBestCell = iBestPerm = iBestDiff = -1; +            // iterate through cells +            for ( k = 2; k < nCells; k++ ) +            { +                if ( nFanins != (int)pCells[k].nFanins ) +                    continue; +                if ( i != k && pCells[i].uTruth == pCells[k].uTruth ) +                { +                    iGate1 = i; +                    iGate2 = k; +                    Count++; +                    continue; +                } +                // set unit permutation +                for ( v = 0; v < nFanins; v++ ) +                    Perm[v] = v; +                // go through all permutation of Cell[k] +                tCur = pCells[k].uTruth; +                for ( p = 0; p < nPerms[nFanins]; p++ ) +                { +                    if ( iThis == tCur && iBestArea > pCells[k].AreaW )  +                    { +                        iBestArea = pCells[k].AreaW; +                        iBestCell = k; +                        iBestPerm = 0; +                        for ( v = 0; v < nFanins; v++ ) +                            iBestPerm |= (v << (Perm[v] << 2)); +                        iBestDiff = (pCells[i].AreaW >= pCells[k].AreaW) ? (int)(pCells[i].AreaW - pCells[k].AreaW) : -(int)(pCells[k].AreaW - pCells[i].AreaW); +                    } +                    if ( nPerms[nFanins] == 1 ) +                        continue; +                    // update +                    tCur  = Abc_Tt6SwapAdjacent( tCur, pPerm[nFanins][p] ); +                    Perm1 = Perm + pPerm[nFanins][p]; +                    Perm2 = Perm1 + 1; +                    ABC_SWAP( int, *Perm1, *Perm2 ); +                } +                assert( tCur == pCells[k].uTruth ); +            } +            Vec_IntPushThree( vInfo, iBestCell, iBestPerm, iBestDiff ); +        } +    } + +    for ( i = 1; i <= 6; i++ ) +        ABC_FREE( pPerm[i] ); +    if ( Count ) +        printf( "In this library, %d cell pairs have equal functions (for example, %s and %s).\n", Count/2, pCells[iGate1].pName, pCells[iGate2].pName ); +    return vInfo; +} +Vec_Int_t * Abc_NtkPrecomputeFirsts( Mio_Cell2_t * pCells, int nCells ) +{ +    int i, Index = 0; +    Vec_Int_t * vFirst = Vec_IntStartFull( 2 );  +    for ( i = 2; i < nCells; i++ ) +    { +        Vec_IntPush( vFirst, Index ); +        Index += 3 * (pCells[i].nFanins + 1); +    } +    assert( nCells == Vec_IntSize(vFirst) ); +    return vFirst; +} +int Abc_NtkPrecomputePrint( Mio_Cell2_t * pCells, int nCells, Vec_Int_t * vInfo ) +{ +    int i, n, v, Index = 0, nRecUsed = 0; +    for ( i = 2; i < nCells; i++ ) +    { +        int nFanins = pCells[i].nFanins; +        printf( "%3d : %8s   Fanins = %d   ", i, pCells[i].pName, nFanins ); +        Dau_DsdPrintFromTruth( &pCells[i].uTruth, nFanins ); +        for ( n = 0; n <= nFanins; n++, Index += 3 ) +        { +            int iCellA = Vec_IntEntry( vInfo, Index+0 ); +            int iPerm  = Vec_IntEntry( vInfo, Index+1 ); +            int Diff   = Vec_IntEntry( vInfo, Index+2 ); +            if ( iCellA == -1 ) +                continue; +            printf( "%d : {", n ); +            for ( v = 0; v < nFanins; v++ ) +                printf( " %d ", (iPerm >> (v << 2)) & 15 ); +            printf( "}  Index = %d  ", Index ); + +            printf( "Gain = %6.2f  ", Scl_Int2Flt(Diff) ); +            Dau_DsdPrintFromTruth( &pCells[iCellA].uTruth, pCells[iCellA].nFanins ); +            nRecUsed++; +        } +    } +    return nRecUsed; +} + +void Abc_NtkPrecomputeCellPairsTest() +{ +    int nCells; +    Mio_Cell2_t * pCells = Mio_CollectRootsNewDefault2( 6, &nCells, 0 ); +    Vec_Int_t * vInfo = Abc_NtkPrecomputeCellPairs( pCells, nCells ); +    int nRecUsed = Abc_NtkPrecomputePrint( pCells, nCells, vInfo ); +    // iterate through the cells +    Vec_Int_t * vFirst = Abc_NtkPrecomputeFirsts( pCells, nCells ); +    printf( "Used records = %d.  All records = %d.\n", nRecUsed, Vec_IntSize(vInfo)/3 - nRecUsed ); +    assert( nCells == Vec_IntSize(vFirst) ); +    Vec_IntFree( vFirst ); +    Vec_IntFree( vInfo ); +    ABC_FREE( pCells ); +} + +int Abc_NodeCheckFanoutHasFanin( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ) +{ +    Abc_Obj_t * pThis; +    int i; +    Abc_ObjForEachFanout( pNode, pThis, i ) +        if ( Abc_NodeFindFanin(pThis, pFanin) >= 0 ) +            return i; +    return -1; +} + +/**Function************************************************************* + +  Synopsis    [Evaluate changes.] + +  Description [] +                +  SideEffects [] + +  SeeAlso     [] + +***********************************************************************/ +int Abc_ObjHasDupFanins( Abc_Obj_t * pObj ) +{ +    int * pArray = pObj->vFanins.pArray; +    int i, k, Limit = Abc_ObjFaninNum(pObj); +    for ( i = 0; i < Limit; i++ ) +        for ( k = i+1; k < Limit; k++ ) +            if ( pArray[i] == pArray[k] ) +                return 1; +    return 0; +} +int Abc_ObjHasDupFanouts( Abc_Obj_t * pObj ) +{ +    int * pArray = pObj->vFanouts.pArray; +    int i, k, Limit = Abc_ObjFanoutNum(pObj); +    for ( i = 0; i < Limit; i++ ) +        for ( k = i+1; k < Limit; k++ ) +            if ( pArray[i] == pArray[k] ) +                return 1; +    return 0; +} +int Abc_ObjChangeEval( Abc_Obj_t * pObj, Vec_Int_t * vInfo, Vec_Int_t * vFirst, int InvArea, int * pfUseInv ) +{ +    Abc_Obj_t * pNext; +    Mio_Gate_t * pGate = (Mio_Gate_t *)pObj->pData; +    int iFanCell, iNodeCell = Mio_GateReadCell( (Mio_Gate_t *)pObj->pData ); +    int * pFanInfo, * pNodeInfo = Vec_IntEntryP( vInfo, Vec_IntEntry(vFirst, iNodeCell) ); +    int i, fNeedInv = 0, Gain = 0, iFanin = Abc_ObjFaninNum(pObj), fUseInv = Abc_NodeIsInv(pObj); +    assert( iFanin > 0 ); +    *pfUseInv = 0; +    if ( pNodeInfo[3*iFanin] == -1 ) +        return 0; +    if ( fUseInv ) +        Gain = InvArea; +    else +        Gain = pNodeInfo[3*iFanin+2]; +    Abc_ObjForEachFanout( pObj, pNext, i ) +    { +        if ( fUseInv && Abc_NodeFindFanin(pNext, Abc_ObjFanin0(pObj)) >= 0 ) +            return 0; +        if ( Abc_ObjHasDupFanins(pNext) ) +            return 0; +        if ( !Abc_ObjIsNode(pNext) || Abc_NodeIsBuf(pNext) ) +        { +            fNeedInv = 1; +            continue; +        } +        if ( Abc_NodeIsInv(pNext) ) +        { +            if ( Abc_NodeCheckFanoutHasFanin(pNext, pObj) >= 0 ) +                return 0; +            Gain += InvArea; +            continue; +        } +        iFanCell = Mio_GateReadCell( (Mio_Gate_t *)pNext->pData ); +        pFanInfo = Vec_IntEntryP( vInfo, Vec_IntEntry(vFirst, iFanCell) ); +        iFanin   = Abc_NodeFindFanin( pNext, pObj ); +        if ( pFanInfo[3*iFanin] == -1 ) +        { +            fNeedInv = 1; +            continue; +        } +        Gain += pFanInfo[3*iFanin+2]; +    } +    if ( fNeedInv ) +        Gain -= InvArea; +    *pfUseInv = fNeedInv; +    return Gain; +} +void Abc_ObjChangeUpdate( Abc_Obj_t * pObj, int iFanin, Mio_Cell2_t * pCells, int * pNodeInfo, Vec_Int_t * vTemp ) +{ +    int v, Perm, iNodeCell = pNodeInfo[3*iFanin]; +    Mio_Gate_t * pGate = (Mio_Gate_t *)pObj->pData; +    //Abc_ObjPrint( stdout, pObj ); +    //printf( "Replacing fanout %d with %s by %s with fanin %d.\n", Abc_ObjId(pObj), Mio_GateReadName(pGate), Mio_GateReadName((Mio_Gate_t *)pCells[iNodeCell].pMioGate), iFanin ); +    pObj->pData = (Mio_Gate_t *)pCells[iNodeCell].pMioGate; +    Perm = pNodeInfo[3*iFanin+1]; +    Vec_IntClear( vTemp ); +    for ( v = 0; v < Abc_ObjFaninNum(pObj); v++ ) +        Vec_IntPush( vTemp, Abc_ObjFaninId(pObj, (Perm >> (v << 2)) & 15) ); +    Vec_IntClear( &pObj->vFanins ); +    Vec_IntAppend( &pObj->vFanins, vTemp ); +} +void Abc_ObjChangePerform( Abc_Obj_t * pObj, Vec_Int_t * vInfo, Vec_Int_t * vFirst, int fUseInv, Vec_Int_t * vTemp, Vec_Ptr_t * vFanout, Vec_Ptr_t * vFanout2, Mio_Cell2_t * pCells ) +{ +    Abc_Obj_t * pNext, * pNext2, * pNodeInv = NULL; +    int iFanCell, iNodeCell = Mio_GateReadCell( (Mio_Gate_t *)pObj->pData ); +    int * pFanInfo, * pNodeInfo = Vec_IntEntryP( vInfo, Vec_IntEntry(vFirst, iNodeCell) ); +    int i, k, iFanin = Abc_ObjFaninNum(pObj); +    assert( iFanin > 0 && pNodeInfo[3*iFanin] != -1 ); +    // update the node +    Abc_NodeCollectFanouts( pObj, vFanout ); +    if ( Abc_NodeIsInv(pObj) ) +    { +        Abc_Obj_t * pFanin = Abc_ObjFanin0(pObj); +        Vec_PtrForEachEntry( Abc_Obj_t *, vFanout, pNext, k ) +            Abc_ObjPatchFanin( pNext, pObj, pFanin ); +        assert( Abc_ObjFanoutNum(pObj) == 0 ); +        Abc_NtkDeleteObj(pObj); +        pObj = pFanin; +        assert( fUseInv == 0 ); +    } +    else +        Abc_ObjChangeUpdate( pObj, iFanin, pCells, pNodeInfo, vTemp ); +    // add inverter if needed +    if ( fUseInv ) +        pNodeInv = Abc_NtkCreateNodeInv(pObj->pNtk, pObj); +    // update the fanouts +    Vec_PtrForEachEntry( Abc_Obj_t *, vFanout, pNext, i ) +    { +        if ( !Abc_ObjIsNode(pNext) || Abc_NodeIsBuf(pNext) ) +        { +            Abc_ObjPatchFanin( pNext, pObj, pNodeInv ); +            continue; +        } +        if ( Abc_NodeIsInv(pNext) ) +        { +            Abc_NodeCollectFanouts( pNext, vFanout2 ); +            Vec_PtrForEachEntry( Abc_Obj_t *, vFanout2, pNext2, k ) +                Abc_ObjPatchFanin( pNext2, pNext, pObj ); +            assert( Abc_ObjFanoutNum(pNext) == 0 ); +            Abc_NtkDeleteObj(pNext); +            continue; +        } +        iFanin   = Abc_NodeFindFanin( pNext, pObj ); +        iFanCell = Mio_GateReadCell( (Mio_Gate_t *)pNext->pData ); +        pFanInfo = Vec_IntEntryP( vInfo, Vec_IntEntry(vFirst, iFanCell) ); +        if ( pFanInfo[3*iFanin] == -1 ) +        { +            Abc_ObjPatchFanin( pNext, pObj, pNodeInv ); +            continue; +        } +        Abc_ObjChangeUpdate( pNext, iFanin, pCells, pFanInfo, vTemp ); +    } +} +void Abc_NtkChangePerform( Abc_Ntk_t * pNtk, int fVerbose ) +{ +    abctime clk = Abc_Clock(); +    int i, fNeedInv, nCells, Gain, GainAll = 0, Count = 0, CountInv = 0; +    Mio_Cell2_t * pCells = Mio_CollectRootsNewDefault2( 6, &nCells, 0 ); +    Vec_Int_t * vInfo = Abc_NtkPrecomputeCellPairs( pCells, nCells ); +    Vec_Int_t * vFirst = Abc_NtkPrecomputeFirsts( pCells, nCells ); + +    Vec_Ptr_t * vFanout = Vec_PtrAlloc( 100 ); +    Vec_Ptr_t * vFanout2 = Vec_PtrAlloc( 100 ); +    Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); +    Abc_Obj_t * pObj; +    Abc_NtkForEachNode( pNtk, pObj, i ) +    { +        if ( Abc_ObjFaninNum(pObj) < 2 && !Abc_NodeIsInv(pObj) ) +            continue; +        if ( Abc_ObjHasDupFanouts(pObj) ) +            continue; +        Gain = Abc_ObjChangeEval( pObj, vInfo, vFirst, (int)pCells[3].AreaW, &fNeedInv ); +        if ( Gain <= 0 ) +            continue; +        //printf( "Obj %d\n", Abc_ObjId(pObj) ); +        Count++; +        CountInv += Abc_NodeIsInv(pObj); +        GainAll += Gain; +        Abc_ObjChangePerform( pObj, vInfo, vFirst, fNeedInv, vTemp, vFanout, vFanout2, pCells ); +    } +    Vec_PtrFree( vFanout2 ); +    Vec_PtrFree( vFanout ); +    Vec_IntFree( vTemp ); + +    Vec_IntFree( vFirst ); +    Vec_IntFree( vInfo ); +    ABC_FREE( pCells ); + +    if ( fVerbose ) +        printf( "Total gain in area = %6.2f after %d changes (including %d inverters). ", Scl_Int2Flt(GainAll), Count, CountInv ); +    if ( fVerbose ) +        Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +//////////////////////////////////////////////////////////////////////// +///                       END OF FILE                                /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/sfm/sfmDec.c b/src/opt/sfm/sfmDec.c index bce20624..c5af0ac0 100644 --- a/src/opt/sfm/sfmDec.c +++ b/src/opt/sfm/sfmDec.c @@ -2152,6 +2152,11 @@ void Abc_NtkPerformMfs3( Abc_Ntk_t * pNtk, Sfm_Par_t * pPars )      if ( pPars->fLibVerbose )          Sfm_LibPrint( p->pLib );      Sfm_DecStop( p ); +    if ( pPars->fArea ) +    { +        extern void Abc_NtkChangePerform( Abc_Ntk_t * pNtk, int fVerbose ); +        Abc_NtkChangePerform( pNtk, pPars->fVerbose ); +    }  }  //////////////////////////////////////////////////////////////////////// | 
