/**CFile**************************************************************** FileName [giaRetime.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Performs most-forward retiming for AIG with flop classes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaRetime.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 objects reachables from Const0 and PIs/ Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManMarkAutonomous_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return pObj->fMark0; Gia_ObjSetTravIdCurrent(p, pObj); assert( pObj->fMark0 == 0 ); if ( Gia_ObjIsPi(p, pObj) || Gia_ObjIsConst0(pObj) ) return pObj->fMark0 = 1; if ( Gia_ObjIsCo(pObj) ) return pObj->fMark0 = Gia_ManMarkAutonomous_rec( p, Gia_ObjFanin0(pObj) ); if ( Gia_ObjIsCi(pObj) ) return pObj->fMark0 = Gia_ManMarkAutonomous_rec( p, Gia_ObjRoToRi(p, pObj) ); assert( Gia_ObjIsAnd(pObj) ); if ( Gia_ManMarkAutonomous_rec( p, Gia_ObjFanin0(pObj) ) ) return pObj->fMark0 = 1; return pObj->fMark0 = Gia_ManMarkAutonomous_rec( p, Gia_ObjFanin1(pObj) ); } /**Function************************************************************* Synopsis [Marks with current trav ROs reachable from Const0 and PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManMarkAutonomous( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManCleanMark0( p ); Gia_ManIncrementTravId( p ); Gia_ManForEachRo( p, pObj, i ) Gia_ManMarkAutonomous_rec( p, pObj ); Gia_ManIncrementTravId( p ); Gia_ManForEachRo( p, pObj, i ) if ( pObj->fMark0 ) Gia_ObjSetTravIdCurrent( p, pObj ); Gia_ManCleanMark0( p ); } /**Function************************************************************* Synopsis [Duplicates the AIG recursively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManRetimeDup_rec( Gia_Man_t * pNew, Gia_Obj_t * pObj ) { if ( ~pObj->Value ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ManRetimeDup_rec( pNew, Gia_ObjFanin0(pObj) ); Gia_ManRetimeDup_rec( pNew, Gia_ObjFanin1(pObj) ); pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } /**Function************************************************************* Synopsis [Duplicates the AIG while retiming the registers to the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManRetimeDupForward( Gia_Man_t * p, Vec_Ptr_t * vCut ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pObjRi, * pObjRo; int i; // create the new manager pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManHashAlloc( pNew ); // create the true PIs Gia_ManFillValue( p ); Gia_ManSetPhase( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); // create the registers Vec_PtrForEachEntry( Gia_Obj_t *, vCut, pObj, i ) pObj->Value = Abc_LitNotCond( Gia_ManAppendCi(pNew), pObj->fPhase ); // duplicate logic above the cut Gia_ManForEachCo( p, pObj, i ) Gia_ManRetimeDup_rec( pNew, Gia_ObjFanin0(pObj) ); // create the true POs Gia_ManForEachPo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); // remember value in LI Gia_ManForEachRi( p, pObj, i ) pObj->Value = Gia_ObjFanin0Copy(pObj); // transfer values from the LIs to the LOs Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) pObjRo->Value = pObjRi->Value; // erase the data values on the internal nodes of the cut Vec_PtrForEachEntry( Gia_Obj_t *, vCut, pObj, i ) if ( Gia_ObjIsAnd(pObj) ) pObj->Value = ~0; // duplicate logic below the cut Vec_PtrForEachEntry( Gia_Obj_t *, vCut, pObj, i ) { Gia_ManRetimeDup_rec( pNew, pObj ); Gia_ManAppendCo( pNew, Abc_LitNotCond( pObj->Value, pObj->fPhase ) ); } Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Vec_PtrSize(vCut) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Derives the cut for forward retiming.] Description [Assumes topological ordering of the nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManRetimeForwardOne( Gia_Man_t * p, int * pnRegFixed, int * pnRegMoves ) { Vec_Int_t * vFlopClasses = NULL; Vec_Int_t * vObjClasses = NULL; Gia_Man_t * pNew; Vec_Ptr_t * vCut; Gia_Obj_t * pObj; int i; if ( p->vFlopClasses ) { // printf( "Performing retiming with register classes.\n" ); vObjClasses = Vec_IntAlloc( Gia_ManObjNum(p) ); for ( i = 0; i < Gia_ManObjNum(p); i++ ) Vec_IntPush( vObjClasses, -1 ); Gia_ManForEachRo( p, pObj, i ) Vec_IntWriteEntry( vObjClasses, Gia_ObjId(p, pObj), Vec_IntEntry(p->vFlopClasses, i) ); vFlopClasses = Vec_IntAlloc( Gia_ManRegNum(p) ); } // mark the retimable nodes Gia_ManIncrementTravId( p ); Gia_ManMarkAutonomous( p ); // mark the retimable registers with the fresh trav ID Gia_ManIncrementTravId( p ); *pnRegFixed = 0; Gia_ManForEachRo( p, pObj, i ) if ( Gia_ObjIsTravIdPrevious(p, pObj) ) Gia_ObjSetTravIdCurrent(p, pObj); else (*pnRegFixed)++; // mark all the nodes that can be retimed forward *pnRegMoves = 0; Gia_ManForEachAnd( p, pObj, i ) if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) && Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) ) { if ( vObjClasses && Vec_IntEntry(vObjClasses, Gia_ObjFaninId0(pObj, i)) != Vec_IntEntry(vObjClasses, Gia_ObjFaninId1(pObj, i)) ) continue; if ( vObjClasses ) Vec_IntWriteEntry( vObjClasses, Gia_ObjId(p, pObj), Vec_IntEntry(vObjClasses, Gia_ObjFaninId0(pObj, i)) ); Gia_ObjSetTravIdCurrent(p, pObj); (*pnRegMoves)++; } // mark the remaining registers Gia_ManForEachRo( p, pObj, i ) Gia_ObjSetTravIdCurrent(p, pObj); // find the cut (all such marked objects that fanout into unmarked nodes) vCut = Vec_PtrAlloc( 1000 ); Gia_ManIncrementTravId( p ); Gia_ManForEachObj( p, pObj, i ) { if ( Gia_ObjIsTravIdPrevious(p, pObj) ) continue; if ( (Gia_ObjIsCo(pObj) || Gia_ObjIsAnd(pObj)) && Gia_ObjIsTravIdPrevious(p, Gia_ObjFanin0(pObj)) ) { if ( vFlopClasses ) Vec_IntPush( vFlopClasses, Vec_IntEntry(vObjClasses, Gia_ObjFaninId0(pObj, i)) ); Vec_PtrPush( vCut, Gia_ObjFanin0(pObj) ); Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin0(pObj) ); } if ( Gia_ObjIsAnd(pObj) && Gia_ObjIsTravIdPrevious(p, Gia_ObjFanin1(pObj)) ) { if ( vFlopClasses ) Vec_IntPush( vFlopClasses, Vec_IntEntry(vObjClasses, Gia_ObjFaninId1(pObj, i)) ); Vec_PtrPush( vCut, Gia_ObjFanin1(pObj) ); Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin1(pObj) ); } } assert( vFlopClasses == NULL || Vec_IntSize(vFlopClasses) == Vec_PtrSize(vCut) ); // finally derive the new manager pNew = Gia_ManRetimeDupForward( p, vCut ); Vec_PtrFree( vCut ); if ( vObjClasses ) Vec_IntFree( vObjClasses ); pNew->vFlopClasses = vFlopClasses; return pNew; } /**Function************************************************************* Synopsis [Derives the cut for forward retiming.] Description [Assumes topological ordering of the nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManRetimeForward( Gia_Man_t * p, int nMaxIters, int fVerbose ) { Gia_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 = Gia_ManRetimeForwardOne( pTemp = pNew, &nRegFixed, &nRegMoves ); if ( fVerbose ) { printf( "%2d : And = %6d. Reg = %5d. Unret = %5d. Move = %6d. ", i + 1, Gia_ManAndNum(pTemp), Gia_ManRegNum(pTemp), nRegFixed, nRegMoves ); ABC_PRT( "Time", Abc_Clock() - clk ); } if ( pTemp != p ) Gia_ManStop( pTemp ); } /* clk = Abc_Clock(); pNew = Gia_ManReduceLaches( pNew, fVerbose ); if ( fVerbose ) { ABC_PRT( "Register sharing time", Abc_Clock() - clk ); } */ return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END