blob: 70bc9fe8629e6326eecf4a3144fa51968e98bf55 [file] [log] [blame]
/**CFile****************************************************************
FileName [giaScl.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Scalable AIG package.]
Synopsis [Sequential cleanup.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: giaScl.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "gia.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Marks unreachable internal nodes and returns their number.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManCombMarkUsed_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
{
if ( pObj == NULL )
return 0;
if ( !pObj->fMark0 )
return 0;
pObj->fMark0 = 0;
assert( Gia_ObjIsAnd(pObj) );
assert( !Gia_ObjIsBuf(pObj) );
return 1 + Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin0(pObj) )
+ Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin1(pObj) )
+ (p->pNexts ? Gia_ManCombMarkUsed_rec( p, Gia_ObjNextObj(p, Gia_ObjId(p, pObj)) ) : 0)
+ (p->pSibls ? Gia_ManCombMarkUsed_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)) ) : 0)
+ (p->pMuxes ? Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin2(p, pObj) ) : 0);
}
int Gia_ManCombMarkUsed( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i, nNodes = 0;
Gia_ManForEachObj( p, pObj, i )
pObj->fMark0 = Gia_ObjIsAnd(pObj) && !Gia_ObjIsBuf(pObj);
Gia_ManForEachBuf( p, pObj, i )
nNodes += Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin0(pObj) );
Gia_ManForEachCo( p, pObj, i )
nNodes += Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin0(pObj) );
return nNodes;
}
/**Function*************************************************************
Synopsis [Performs combinational cleanup.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManCleanup( Gia_Man_t * p )
{
Gia_ManCombMarkUsed( p );
return Gia_ManDupMarked( p );
}
/**Function*************************************************************
Synopsis [Skip the first outputs during cleanup.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManCleanupOutputs( Gia_Man_t * p, int nOutputs )
{
Gia_Obj_t * pObj;
int i;
assert( Gia_ManRegNum(p) == 0 );
assert( nOutputs < Gia_ManCoNum(p) );
Gia_ManCombMarkUsed( p );
Gia_ManForEachCo( p, pObj, i )
if ( i < nOutputs )
pObj->fMark0 = 1;
else
break;
return Gia_ManDupMarked( p );
}
/**Function*************************************************************
Synopsis [Marks CIs/COs/ANDs unreachable from POs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManSeqMarkUsed_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vRoots )
{
if ( !pObj->fMark0 )
return 0;
pObj->fMark0 = 0;
if ( Gia_ObjIsCo(pObj) )
return Gia_ManSeqMarkUsed_rec( p, Gia_ObjFanin0(pObj), vRoots );
if ( Gia_ObjIsRo(p, pObj) )
{
Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) );
return 0;
}
assert( Gia_ObjIsAnd(pObj) );
return 1 + Gia_ManSeqMarkUsed_rec( p, Gia_ObjFanin0(pObj), vRoots )
+ Gia_ManSeqMarkUsed_rec( p, Gia_ObjFanin1(pObj), vRoots );
}
/**Function*************************************************************
Synopsis [Marks CIs/COs/ANDs unreachable from POs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManSeqMarkUsed( Gia_Man_t * p )
{
Vec_Int_t * vRoots;
Gia_Obj_t * pObj;
int i, nNodes = 0;
Gia_ManSetMark0( p );
Gia_ManConst0(p)->fMark0 = 0;
Gia_ManForEachPi( p, pObj, i )
pObj->fMark0 = 0;
vRoots = Gia_ManCollectPoIds( p );
Gia_ManForEachObjVec( vRoots, p, pObj, i )
nNodes += Gia_ManSeqMarkUsed_rec( p, pObj, vRoots );
Vec_IntFree( vRoots );
return nNodes;
}
/**Function*************************************************************
Synopsis [Performs sequential cleanup.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManSeqCleanup( Gia_Man_t * p )
{
Gia_ManSeqMarkUsed( p );
return Gia_ManDupMarked( p );
}
/**Function*************************************************************
Synopsis [Find representatives due to identical fanins.]
Description [Returns the old manager if there is no changes.]
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManReduceEquiv( Gia_Man_t * p, int fVerbose )
{
Gia_Man_t * pNew;
Gia_Obj_t * pObjRi, * pObjRo;
unsigned * pCi2Lit, * pMaps;
int i, iLit, nFanins = 1, Counter0 = 0, Counter = 0;
Gia_ManForEachRi( p, pObjRi, i )
Gia_ObjFanin0(pObjRi)->Value = 0;
Gia_ManForEachRi( p, pObjRi, i )
if ( Gia_ObjFanin0(pObjRi)->Value == 0 )
Gia_ObjFanin0(pObjRi)->Value = 2*nFanins++;
pCi2Lit = ABC_FALLOC( unsigned, Gia_ManCiNum(p) );
pMaps = ABC_FALLOC( unsigned, 2 * nFanins );
Gia_ManForEachRiRo( p, pObjRi, pObjRo, i )
{
iLit = Gia_ObjFanin0Copy( pObjRi );
if ( Gia_ObjFaninId0p(p, pObjRi) == 0 && Gia_ObjFaninC0(pObjRi) == 0 ) // const 0
pCi2Lit[Gia_ManPiNum(p)+i] = 0, Counter0++;
else if ( ~pMaps[iLit] ) // in this case, ID(pObj) > ID(pRepr)
pCi2Lit[Gia_ManPiNum(p)+i] = pMaps[iLit], Counter++;
else
pMaps[iLit] = Abc_Var2Lit( Gia_ObjId(p, pObjRo), 0 );
}
/*
Gia_ManForEachCi( p, pObjRo, i )
{
if ( ~pCi2Lit[i] )
{
Gia_Obj_t * pObj0 = Gia_ObjRoToRi(p, pObjRo);
Gia_Obj_t * pObj1 = Gia_ObjRoToRi(p, Gia_ManObj(p, pCi2Lit[i]));
Gia_Obj_t * pFan0 = Gia_ObjChild0( p, Gia_ObjRoToRi(p, pObjRo) );
Gia_Obj_t * pFan1 = Gia_ObjChild0( p, Gia_ObjRoToRi(p, Gia_ManObj(p, pCi2Lit[i])) );
assert( pFan0 == pFan1 );
}
}
*/
// if ( fVerbose )
// printf( "ReduceEquiv detected %d constant regs and %d equivalent regs.\n", Counter0, Counter );
ABC_FREE( pMaps );
if ( Counter0 || Counter )
pNew = Gia_ManDupDfsCiMap( p, (int *)pCi2Lit, NULL );
else
pNew = p;
ABC_FREE( pCi2Lit );
return pNew;
}
/**Function*************************************************************
Synopsis [Performs sequential cleanup.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManSeqStructSweep( Gia_Man_t * p, int fConst, int fEquiv, int fVerbose )
{
Gia_Man_t * pTemp;
if ( Gia_ManRegNum(p) == 0 )
return Gia_ManCleanup( p );
if ( fVerbose )
printf( "Performing sequential cleanup.\n" );
p = Gia_ManSeqCleanup( pTemp = p );
if ( fVerbose )
Gia_ManReportImprovement( pTemp, p );
if ( fConst && Gia_ManRegNum(p) )
{
p = Gia_ManReduceConst( pTemp = p, fVerbose );
if ( fVerbose )
Gia_ManReportImprovement( pTemp, p );
Gia_ManStop( pTemp );
}
if ( fVerbose && fEquiv )
printf( "Merging combinationally equivalent flops.\n" );
if ( fEquiv )
while ( 1 )
{
p = Gia_ManSeqCleanup( pTemp = p );
if ( fVerbose )
Gia_ManReportImprovement( pTemp, p );
Gia_ManStop( pTemp );
if ( Gia_ManRegNum(p) == 0 )
break;
p = Gia_ManReduceEquiv( pTemp = p, fVerbose );
if ( p == pTemp )
break;
Gia_ManStop( pTemp );
}
return p;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END