blob: e5556d273f94aff8bc44d32b57277a3f60347a97 [file] [log] [blame]
/**CFile****************************************************************
FileName [giaShrink7.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Scalable AIG package.]
Synopsis [Implementation of DAG-aware unmapping for 6-input cuts.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: giaShrink6.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "gia.h"
#include "misc/vec/vecHash.h"
#include "misc/util/utilTruth.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// operation manager
typedef struct Unm_Man_t_ Unm_Man_t;
struct Unm_Man_t_
{
Gia_Man_t * pGia; // user's AIG
Gia_Man_t * pNew; // constructed AIG
Hash_IntMan_t * pHash; // hash table
int nNewSize; // expected size of new manager
Vec_Int_t * vUsed; // used nodes
Vec_Int_t * vId2Used; // mapping of obj IDs into used node IDs
Vec_Wrd_t * vTruths; // truth tables
Vec_Int_t * vLeaves; // temporary storage for leaves
abctime clkStart; // starting the clock
};
extern word Shr_ManComputeTruth6( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves, Vec_Wrd_t * vTruths );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Unm_Man_t * Unm_ManAlloc( Gia_Man_t * pGia )
{
Unm_Man_t * p;
p = ABC_CALLOC( Unm_Man_t, 1 );
p->clkStart = Abc_Clock();
p->nNewSize = 3 * Gia_ManObjNum(pGia) / 2;
p->pGia = pGia;
p->pNew = Gia_ManStart( p->nNewSize );
p->pNew->pName = Abc_UtilStrsav( pGia->pName );
p->pNew->pSpec = Abc_UtilStrsav( pGia->pSpec );
Gia_ManHashAlloc( p->pNew );
Gia_ManCleanLevels( p->pNew, p->nNewSize );
// allocate traversal IDs
p->pNew->nObjs = p->nNewSize;
Gia_ManIncrementTravId( p->pNew );
p->pNew->nObjs = 1;
// start hashing
p->pHash = Hash_IntManStart( 1000 );
// truth tables
p->vLeaves = Vec_IntStart( 10 );
return p;
}
Gia_Man_t * Unm_ManFree( Unm_Man_t * p )
{
Gia_Man_t * pTemp = p->pNew; p->pNew = NULL;
Gia_ManHashStop( pTemp );
Vec_IntFreeP( &pTemp->vLevels );
Gia_ManSetRegNum( pTemp, Gia_ManRegNum(p->pGia) );
// truth tables
Vec_WrdFreeP( &p->vTruths );
Vec_IntFreeP( &p->vLeaves );
Vec_IntFreeP( &p->vUsed );
Vec_IntFreeP( &p->vId2Used );
// free data structures
Hash_IntManStop( p->pHash );
ABC_FREE( p );
Gia_ManStop( pTemp );
pTemp = NULL;
return pTemp;
}
/**Function*************************************************************
Synopsis [Computes information about node pairs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Unm_ManPrintPairStats( Hash_IntMan_t * pHash, int nTotal0, int nPairs0, int nPairs1, int fUseLit )
{
int i, Num, nRefs, nPairs = 0, nTotal = 0, Counter[21] = {0};
Num = Hash_IntManEntryNum( pHash );
for ( i = 1; i <= Num; i++ )
{
nRefs = Abc_MinInt( 20, Hash_IntObjData2(pHash, i) );
nTotal += nRefs;
Counter[nRefs]++;
nPairs += (nRefs > 1);
/*
if ( fUseLit )
printf( "(%c%c, %c%c) %d\n",
Abc_LitIsCompl(Hash_IntObjData0(pHash, i)-2) ? '!' : ' ',
'a' + Abc_Lit2Var(Hash_IntObjData0(pHash, i)-2),
Abc_LitIsCompl(Hash_IntObjData1(pHash, i)-2) ? '!' : ' ',
'a' + Abc_Lit2Var(Hash_IntObjData1(pHash, i)-2), nRefs );
else
printf( "( %c, %c) %d\n",
'a' + Hash_IntObjData0(pHash, i)-1,
'a' + Hash_IntObjData1(pHash, i)-1, nRefs );
*/
// printf( "(%4d, %4d) %d\n", Hash_IntObjData0(pHash, i), Hash_IntObjData1(pHash, i), nRefs );
}
printf( "Statistics for pairs appearing less than 20 times:\n" );
for ( i = 0; i < 21; i++ )
if ( Counter[i] > 0 )
printf( "%3d : %7d %7.2f %%\n", i, Counter[i], 100.0 * Counter[i] * i / Abc_MaxInt(nTotal, 1) );
printf( "Pairs: Total = %8d Init = %8d %7.2f %% Final = %8d %7.2f %% Real = %8d %7.2f %%\n", nTotal0,
nPairs0, 100.0 * nPairs0 / Abc_MaxInt(nTotal0, 1),
nPairs, 100.0 * nPairs / Abc_MaxInt(nTotal0, 1),
nPairs1, 100.0 * nPairs1 / Abc_MaxInt(nTotal0, 1) );
return nPairs;
}
Vec_Int_t * Unm_ManComputePairs( Unm_Man_t * p, int fVerbose )
{
Gia_Obj_t * pObj;
Vec_Int_t * vPairs = Vec_IntAlloc( 1000 );
Vec_Int_t * vNum2Obj = Vec_IntStart( 1 );
Hash_IntMan_t * pHash = Hash_IntManStart( 1000 );
int nTotal = 0, nPairs0 = 0, nPairs = 0;
int i, k, j, FanK, FanJ, Num, nRefs;
Gia_ManSetRefsMapped( p->pGia );
Gia_ManForEachLut( p->pGia, i )
{
nTotal += Gia_ObjLutSize(p->pGia, i) * (Gia_ObjLutSize(p->pGia, i) - 1) / 2;
pObj = Gia_ManObj( p->pGia, i );
// collect leaves of this gate
Vec_IntClear( p->vLeaves );
Gia_LutForEachFanin( p->pGia, i, Num, k )
if ( Gia_ObjRefNumId(p->pGia, Num) > 1 )
Vec_IntPush( p->vLeaves, Num );
if ( Vec_IntSize(p->vLeaves) < 2 )
continue;
nPairs0 += Vec_IntSize(p->vLeaves) * (Vec_IntSize(p->vLeaves) - 1) / 2;
// enumerate pairs
Vec_IntForEachEntry( p->vLeaves, FanK, k )
Vec_IntForEachEntryStart( p->vLeaves, FanJ, j, k+1 )
{
if ( FanK > FanJ )
ABC_SWAP( int, FanK, FanJ );
Num = Hash_Int2ManInsert( pHash, FanK, FanJ, 0 );
nRefs = Hash_Int2ObjInc(pHash, Num);
if ( nRefs == 0 )
{
assert( Num == Hash_IntManEntryNum(pHash) );
assert( Num == Vec_IntSize(vNum2Obj) );
Vec_IntPush( vNum2Obj, i );
continue;
}
if ( nRefs == 1 )
{
assert( Num < Vec_IntSize(vNum2Obj) );
Vec_IntPush( vPairs, Vec_IntEntry(vNum2Obj, Num) );
Vec_IntPush( vPairs, FanK );
Vec_IntPush( vPairs, FanJ);
}
Vec_IntPush( vPairs, i );
Vec_IntPush( vPairs, FanK );
Vec_IntPush( vPairs, FanJ );
}
}
Vec_IntFree( vNum2Obj );
if ( fVerbose )
nPairs = Unm_ManPrintPairStats( pHash, nTotal, nPairs0, Vec_IntSize(vPairs) / 3, 0 );
Hash_IntManStop( pHash );
return vPairs;
}
// finds used nodes
Vec_Int_t * Unm_ManFindUsedNodes( Vec_Int_t * vPairs, int nObjs )
{
Vec_Int_t * vNodes = Vec_IntAlloc( 1000 );
Vec_Str_t * vMarks = Vec_StrStart( nObjs ); int i;
for ( i = 0; i < Vec_IntSize(vPairs); i += 3 )
Vec_StrWriteEntry( vMarks, Vec_IntEntry(vPairs, i), 1 );
for ( i = 0; i < nObjs; i++ )
if ( Vec_StrEntry( vMarks, i ) )
Vec_IntPush( vNodes, i );
Vec_StrFree( vMarks );
printf( "The number of used nodes = %d\n", Vec_IntSize(vNodes) );
return vNodes;
}
// computes truth table for selected nodes
Vec_Wrd_t * Unm_ManComputeTruths( Unm_Man_t * p )
{
Vec_Wrd_t * vTruthsTemp, * vTruths;
int i, k, iObj, iNode;
word uTruth;
vTruths = Vec_WrdAlloc( Vec_IntSize(p->vUsed) );
vTruthsTemp = Vec_WrdStart( Gia_ManObjNum(p->pGia) );
Vec_IntForEachEntry( p->vUsed, iObj, i )
{
assert( Gia_ObjIsLut(p->pGia, iObj) );
// collect leaves of this gate
Vec_IntClear( p->vLeaves );
Gia_LutForEachFanin( p->pGia, iObj, iNode, k )
Vec_IntPush( p->vLeaves, iNode );
assert( Vec_IntSize(p->vLeaves) <= 6 );
// compute truth table
uTruth = Shr_ManComputeTruth6( p->pGia, Gia_ManObj(p->pGia, iObj), p->vLeaves, vTruthsTemp );
Vec_WrdPush( vTruths, uTruth );
// if ( i % 100 == 0 )
// Kit_DsdPrintFromTruth( (unsigned *)&uTruth, 6 ), printf( "\n" );
}
Vec_WrdFreeP( &vTruthsTemp );
return vTruths;
}
/**Function*************************************************************
Synopsis [Collects decomposable pairs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Unm_ManCollectDecomp( Unm_Man_t * p, Vec_Int_t * vPairs, int fVerbose )
{
word uTruth; int nNonUnique = 0;
int i, k, j, s, iObj, iNode, iUsed, FanK, FanJ, Res, Num, nRefs;
Vec_Int_t * vNum2Obj = Vec_IntStart( 1 );
Vec_Int_t * vPairs2 = Vec_IntAlloc( 1000 );
assert( Hash_IntManEntryNum(p->pHash) == 0 );
for ( i = 0; i < Vec_IntSize(vPairs); i += 3 )
{
iObj = Vec_IntEntry( vPairs, i );
assert( Gia_ObjIsLut(p->pGia, iObj) );
// collect leaves of this gate
Vec_IntClear( p->vLeaves );
Gia_LutForEachFanin( p->pGia, iObj, iNode, s )
Vec_IntPush( p->vLeaves, iNode );
assert( Vec_IntSize(p->vLeaves) <= 6 );
FanK = Vec_IntEntry(vPairs, i+1);
FanJ = Vec_IntEntry(vPairs, i+2);
k = Vec_IntFind( p->vLeaves, FanK );
j = Vec_IntFind( p->vLeaves, FanJ );
assert( FanK < FanJ );
iUsed = Vec_IntEntry( p->vId2Used, iObj );
uTruth = Vec_WrdEntry( p->vTruths, iUsed );
Res = Abc_TtCheckDsdAnd( uTruth, k, j, NULL );
if ( Res == -1 )
continue;
// derive literals
FanK = Abc_Var2Lit( FanK, ((Res >> 0) & 1) );
FanJ = Abc_Var2Lit( FanJ, ((Res >> 1) & 1) );
if ( Res == 4 )
ABC_SWAP( int, FanK, FanJ );
Num = Hash_Int2ManInsert( p->pHash, FanK, FanJ, 0 );
nRefs = Hash_Int2ObjInc(p->pHash, Num);
if ( nRefs == 0 )
{
assert( Num == Hash_IntManEntryNum(p->pHash) );
assert( Num == Vec_IntSize(vNum2Obj) );
Vec_IntPush( vNum2Obj, iObj );
continue;
}
if ( nRefs == 1 )
{
assert( Num < Vec_IntSize(vNum2Obj) );
Vec_IntPush( vPairs2, Vec_IntEntry(vNum2Obj, Num) );
Vec_IntPush( vPairs2, FanK );
Vec_IntPush( vPairs2, FanJ );
nNonUnique++;
}
Vec_IntPush( vPairs2, iObj );
Vec_IntPush( vPairs2, FanK );
Vec_IntPush( vPairs2, FanJ );
}
Vec_IntFree( vNum2Obj );
if ( fVerbose )
Unm_ManPrintPairStats( p->pHash, Vec_IntSize(vPairs)/3, Hash_IntManEntryNum(p->pHash), Vec_IntSize(vPairs2)/3, 1 );
// Hash_IntManStop( pHash );
return vPairs2;
}
/**Function*************************************************************
Synopsis [Compute truth tables for the selected nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Unm_ManWork( Unm_Man_t * p )
{
Vec_Int_t * vPairs, * vPairs2;
// find the duplicated pairs
vPairs = Unm_ManComputePairs( p, 1 );
// find the used nodes
p->vUsed = Unm_ManFindUsedNodes( vPairs, Gia_ManObjNum(p->pGia) );
p->vId2Used = Vec_IntInvert( p->vUsed, -1 );
Vec_IntFillExtra( p->vId2Used, Gia_ManObjNum(p->pGia), -1 );
// compute truth tables for used nodes
p->vTruths = Unm_ManComputeTruths( p );
// derive new pairs
vPairs2 = Unm_ManCollectDecomp( p, vPairs, 1 );
Vec_IntFreeP( &vPairs );
Vec_IntFreeP( &vPairs2 );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Unm_ManTest( Gia_Man_t * pGia )
{
Unm_Man_t * p;
p = Unm_ManAlloc( pGia );
Unm_ManWork( p );
Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
return Unm_ManFree( p );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END