mirror of https://github.com/YosysHQ/abc.git
248 lines
7.6 KiB
C
248 lines
7.6 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [saigRetFwd.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Sequential AIG package.]
|
|
|
|
Synopsis [Most-forward retiming.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
Revision [$Id: saigRetFwd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "saig.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
static inline Aig_Obj_t * Aig_ObjFanoutStatic( Aig_Obj_t * pObj, int i ) { return ((Aig_Obj_t **)pObj->pData)[i]; }
|
|
static inline void Aig_ObjSetFanoutStatic( Aig_Obj_t * pObj, Aig_Obj_t * pFan ) { ((Aig_Obj_t **)pObj->pData)[pObj->nRefs++] = pFan; }
|
|
|
|
#define Aig_ObjForEachFanoutStatic( pObj, pFan, i ) \
|
|
for ( i = 0; (i < (int)(pObj)->nRefs) && ((pFan) = Aig_ObjFanoutStatic(pObj, i)); i++ )
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Allocate static fanout for all nodes in the AIG manager.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Aig_Obj_t ** Aig_ManStaticFanoutStart( Aig_Man_t * p )
|
|
{
|
|
Aig_Obj_t ** ppFanouts, * pObj;
|
|
int i, nFanouts, nFanoutsAlloc;
|
|
// allocate fanouts
|
|
nFanoutsAlloc = 2 * Aig_ManObjNumMax(p) - Aig_ManPiNum(p) - Aig_ManPoNum(p);
|
|
ppFanouts = ABC_ALLOC( Aig_Obj_t *, nFanoutsAlloc );
|
|
// mark up storage
|
|
nFanouts = 0;
|
|
Aig_ManForEachObj( p, pObj, i )
|
|
{
|
|
pObj->pData = ppFanouts + nFanouts;
|
|
nFanouts += pObj->nRefs;
|
|
pObj->nRefs = 0;
|
|
}
|
|
assert( nFanouts < nFanoutsAlloc );
|
|
// add fanouts
|
|
Aig_ManForEachObj( p, pObj, i )
|
|
{
|
|
if ( Aig_ObjChild0(pObj) )
|
|
Aig_ObjSetFanoutStatic( Aig_ObjFanin0(pObj), pObj );
|
|
if ( Aig_ObjChild1(pObj) )
|
|
Aig_ObjSetFanoutStatic( Aig_ObjFanin1(pObj), pObj );
|
|
}
|
|
return ppFanouts;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Marks the objects reachable from the given object.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Aig_ManMarkAutonomous_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
|
|
{
|
|
Aig_Obj_t * pFanout;
|
|
int i;
|
|
if ( Aig_ObjIsTravIdCurrent(p, pObj) )
|
|
return;
|
|
Aig_ObjSetTravIdCurrent(p, pObj);
|
|
Aig_ObjForEachFanoutStatic( pObj, pFanout, i )
|
|
Aig_ManMarkAutonomous_rec( p, pFanout );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Marks with current trav ID nodes reachable from Const1 and PIs.]
|
|
|
|
Description [Returns the number of unreachable registers.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_ManMarkAutonomous( Aig_Man_t * p )
|
|
{
|
|
Aig_Obj_t ** ppFanouts;
|
|
Aig_Obj_t * pObj, * pObjLi, * pObjLo;
|
|
int i;
|
|
// temporarily connect register outputs to register inputs
|
|
Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
|
|
{
|
|
pObjLo->pFanin0 = pObjLi;
|
|
pObjLi->nRefs = 1;
|
|
}
|
|
// mark nodes reachable from Const1 and PIs
|
|
Aig_ManIncrementTravId( p );
|
|
ppFanouts = Aig_ManStaticFanoutStart( p );
|
|
Aig_ManMarkAutonomous_rec( p, Aig_ManConst1(p) );
|
|
Saig_ManForEachPi( p, pObj, i )
|
|
Aig_ManMarkAutonomous_rec( p, pObj );
|
|
ABC_FREE( ppFanouts );
|
|
// disconnect LIs/LOs and label unreachable registers
|
|
Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
|
|
{
|
|
assert( pObjLo->pFanin0 && pObjLi->nRefs == 1 );
|
|
pObjLo->pFanin0 = NULL;
|
|
pObjLi->nRefs = 0;
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Derives the cut for forward retiming.]
|
|
|
|
Description [Assumes topological ordering of the nodes.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Aig_Man_t * Saig_ManRetimeForwardOne( Aig_Man_t * p, int * pnRegFixed, int * pnRegMoves )
|
|
{
|
|
Aig_Man_t * pNew;
|
|
Vec_Ptr_t * vCut;
|
|
Aig_Obj_t * pObj, * pFanin;
|
|
int i;
|
|
// mark the retimable nodes
|
|
Saig_ManMarkAutonomous( p );
|
|
// mark the retimable registers with the fresh trav ID
|
|
Aig_ManIncrementTravId( p );
|
|
*pnRegFixed = 0;
|
|
Saig_ManForEachLo( p, pObj, i )
|
|
if ( Aig_ObjIsTravIdPrevious(p, pObj) )
|
|
Aig_ObjSetTravIdCurrent(p, pObj);
|
|
else
|
|
(*pnRegFixed)++;
|
|
// mark all the nodes that can be retimed forward
|
|
*pnRegMoves = 0;
|
|
Aig_ManForEachNode( p, pObj, i )
|
|
if ( Aig_ObjIsTravIdCurrent(p, Aig_ObjFanin0(pObj)) && Aig_ObjIsTravIdCurrent(p, Aig_ObjFanin1(pObj)) )
|
|
{
|
|
Aig_ObjSetTravIdCurrent(p, pObj);
|
|
(*pnRegMoves)++;
|
|
}
|
|
// mark the remaining registers
|
|
Saig_ManForEachLo( p, pObj, i )
|
|
Aig_ObjSetTravIdCurrent(p, pObj);
|
|
// find the cut (all such marked objects that fanout into unmarked nodes)
|
|
vCut = Vec_PtrAlloc( 1000 );
|
|
Aig_ManIncrementTravId( p );
|
|
Aig_ManForEachObj( p, pObj, i )
|
|
{
|
|
if ( Aig_ObjIsTravIdPrevious(p, pObj) )
|
|
continue;
|
|
pFanin = Aig_ObjFanin0(pObj);
|
|
if ( pFanin && Aig_ObjIsTravIdPrevious(p, pFanin) )
|
|
{
|
|
Vec_PtrPush( vCut, pFanin );
|
|
Aig_ObjSetTravIdCurrent( p, pFanin );
|
|
}
|
|
pFanin = Aig_ObjFanin1(pObj);
|
|
if ( pFanin && Aig_ObjIsTravIdPrevious(p, pFanin) )
|
|
{
|
|
Vec_PtrPush( vCut, pFanin );
|
|
Aig_ObjSetTravIdCurrent( p, pFanin );
|
|
}
|
|
}
|
|
// finally derive the new manager
|
|
pNew = Saig_ManRetimeDupForward( p, vCut );
|
|
Vec_PtrFree( vCut );
|
|
return pNew;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Derives the cut for forward retiming.]
|
|
|
|
Description [Assumes topological ordering of the nodes.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Aig_Man_t * Saig_ManRetimeForward( Aig_Man_t * p, int nMaxIters, int fVerbose )
|
|
{
|
|
Aig_Man_t * pNew, * pTemp;
|
|
int i, clk, nRegFixed, nRegMoves = 1;
|
|
pNew = p;
|
|
for ( i = 0; i < nMaxIters && nRegMoves > 0; i++ )
|
|
{
|
|
clk = clock();
|
|
pNew = Saig_ManRetimeForwardOne( pTemp = pNew, &nRegFixed, &nRegMoves );
|
|
if ( fVerbose )
|
|
{
|
|
printf( "%2d : And = %6d. Reg = %5d. Unret = %5d. Move = %6d. ",
|
|
i + 1, Aig_ManNodeNum(pTemp), Aig_ManRegNum(pTemp), nRegFixed, nRegMoves );
|
|
ABC_PRT( "Time", clock() - clk );
|
|
}
|
|
if ( pTemp != p )
|
|
Aig_ManStop( pTemp );
|
|
}
|
|
clk = clock();
|
|
pNew = Aig_ManReduceLaches( pNew, fVerbose );
|
|
if ( fVerbose )
|
|
{
|
|
ABC_PRT( "Register sharing time", clock() - clk );
|
|
}
|
|
return pNew;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|