/**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_ManCiNum(p) - Aig_ManCoNum(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, nRegFixed, nRegMoves = 1; abctime clk; pNew = p; for ( i = 0; i < nMaxIters && nRegMoves > 0; i++ ) { clk = Abc_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", Abc_Clock() - clk ); } if ( pTemp != p ) Aig_ManStop( pTemp ); } clk = Abc_Clock(); pNew = Aig_ManReduceLaches( pNew, fVerbose ); if ( fVerbose ) { ABC_PRT( "Register sharing time", Abc_Clock() - clk ); } return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END