/**CFile**************************************************************** FileName [acbUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Various utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - July 21, 2015.] Revision [$Id: acbUtil.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "acb.h" #include "base/abc/abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collecting TFI and TFO.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Acb_ObjCollectTfi_rec( Acb_Ntk_t * p, int iObj, int fTerm ) { int * pFanin, iFanin, i; if ( Acb_ObjSetTravIdCur(p, iObj) ) return; if ( !fTerm && Acb_ObjIsCi(p, iObj) ) return; Acb_ObjForEachFaninFast( p, iObj, pFanin, iFanin, i ) Acb_ObjCollectTfi_rec( p, iFanin, fTerm ); Vec_IntPush( &p->vArray0, iObj ); } Vec_Int_t * Acb_ObjCollectTfi( Acb_Ntk_t * p, int iObj, int fTerm ) { int i, Node; Vec_IntClear( &p->vArray0 ); Acb_NtkIncTravId( p ); if ( iObj > 0 ) { Vec_IntForEachEntry( &p->vSuppOld, Node, i ) Acb_ObjCollectTfi_rec( p, Node, fTerm ); Acb_ObjCollectTfi_rec( p, iObj, fTerm ); } else Acb_NtkForEachCo( p, iObj, i ) Acb_ObjCollectTfi_rec( p, iObj, fTerm ); return &p->vArray0; } void Acb_ObjCollectTfo_rec( Acb_Ntk_t * p, int iObj, int fTerm ) { int iFanout, i; if ( Acb_ObjSetTravIdCur(p, iObj) ) return; if ( !fTerm && Acb_ObjIsCo(p, iObj) ) return; Acb_ObjForEachFanout( p, iObj, iFanout, i ) Acb_ObjCollectTfo_rec( p, iFanout, fTerm ); Vec_IntPush( &p->vArray1, iObj ); } Vec_Int_t * Acb_ObjCollectTfo( Acb_Ntk_t * p, int iObj, int fTerm ) { int i; Vec_IntClear( &p->vArray1 ); Acb_NtkIncTravId( p ); if ( iObj > 0 ) Acb_ObjCollectTfo_rec( p, iObj, fTerm ); else Acb_NtkForEachCi( p, iObj, i ) Acb_ObjCollectTfo_rec( p, iObj, fTerm ); return &p->vArray1; } /**Function************************************************************* Synopsis [Computing and updating direct and reverse logic level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Acb_ObjComputeLevelD( Acb_Ntk_t * p, int iObj ) { int * pFanins, iFanin, k, Level = 0; Acb_ObjForEachFaninFast( p, iObj, pFanins, iFanin, k ) Level = Abc_MaxInt( Level, Acb_ObjLevelD(p, iFanin) ); return Acb_ObjSetLevelD( p, iObj, Level + !Acb_ObjIsCio(p, iObj) ); } int Acb_NtkComputeLevelD( Acb_Ntk_t * p, Vec_Int_t * vTfo ) { // it is assumed that vTfo contains CO nodes and level of new nodes was already updated int i, iObj, Level = 0; if ( !Acb_NtkHasObjLevelD( p ) ) Acb_NtkCleanObjLevelD( p ); Vec_IntForEachEntryReverse( vTfo, iObj, i ) Acb_ObjComputeLevelD( p, iObj ); Acb_NtkForEachCo( p, iObj, i ) Level = Abc_MaxInt( Level, Acb_ObjLevelD(p, iObj) ); p->LevelMax = Level; return Level; } int Acb_ObjComputeLevelR( Acb_Ntk_t * p, int iObj ) { int iFanout, k, Level = 0; Acb_ObjForEachFanout( p, iObj, iFanout, k ) Level = Abc_MaxInt( Level, Acb_ObjLevelR(p, iFanout) ); return Acb_ObjSetLevelR( p, iObj, Level + !Acb_ObjIsCio(p, iObj) ); } int Acb_NtkComputeLevelR( Acb_Ntk_t * p, Vec_Int_t * vTfi ) { // it is assumed that vTfi contains CI nodes int i, iObj, Level = 0; if ( !Acb_NtkHasObjLevelR( p ) ) Acb_NtkCleanObjLevelR( p ); Vec_IntForEachEntryReverse( vTfi, iObj, i ) Acb_ObjComputeLevelR( p, iObj ); Acb_NtkForEachCi( p, iObj, i ) Level = Abc_MaxInt( Level, Acb_ObjLevelR(p, iObj) ); // assert( p->LevelMax == Level ); p->LevelMax = Level; return Level; } void Acb_NtkUpdateLevelD( Acb_Ntk_t * p, int Pivot ) { Vec_Int_t * vTfo = Acb_ObjCollectTfo( p, Pivot, 1 ); Acb_NtkComputeLevelD( p, vTfo ); } /**Function************************************************************* Synopsis [Computing and updating direct and reverse path count.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Acb_ObjSlack( Acb_Ntk_t * p, int iObj ) { int LevelSum = Acb_ObjLevelD(p, iObj) + Acb_ObjLevelR(p, iObj); assert( !Acb_ObjIsCio(p, iObj) + p->LevelMax >= LevelSum ); return !Acb_ObjIsCio(p, iObj) + p->LevelMax - LevelSum; } int Acb_ObjComputePathD( Acb_Ntk_t * p, int iObj ) { int * pFanins, iFanin, k, Path = 0; assert( !Acb_ObjIsCi(p, iObj) ); Acb_ObjForEachFaninFast( p, iObj, pFanins, iFanin, k ) if ( !Acb_ObjSlack(p, iFanin) ) Path += Acb_ObjPathD(p, iFanin); return Acb_ObjSetPathD( p, iObj, Path ); } int Acb_NtkComputePathsD( Acb_Ntk_t * p, Vec_Int_t * vTfo, int fReverse ) { int i, iObj, Path = 0; //Vec_IntPrint( vTfo ); if ( !Acb_NtkHasObjPathD( p ) ) Acb_NtkCleanObjPathD( p ); // it is assumed that vTfo contains CI nodes //assert( Acb_ObjSlack(p, Vec_IntEntry(vTfo, 0)) ); if ( fReverse ) { Vec_IntForEachEntryReverse( vTfo, iObj, i ) { if ( Acb_ObjIsCi(p, iObj) ) Acb_ObjSetPathD( p, iObj, Acb_ObjSlack(p, iObj) == 0 ); else if ( Acb_ObjSlack(p, iObj) ) Acb_ObjSetPathD( p, iObj, 0 ); else Acb_ObjComputePathD( p, iObj ); } } else { Vec_IntForEachEntry( vTfo, iObj, i ) { if ( Acb_ObjIsCi(p, iObj) ) Acb_ObjSetPathD( p, iObj, Acb_ObjSlack(p, iObj) == 0 ); else if ( Acb_ObjSlack(p, iObj) ) Acb_ObjSetPathD( p, iObj, 0 ); else Acb_ObjComputePathD( p, iObj ); } } Acb_NtkForEachCo( p, iObj, i ) Path += Acb_ObjPathD(p, iObj); p->nPaths = Path; return Path; } int Acb_ObjComputePathR( Acb_Ntk_t * p, int iObj ) { int iFanout, k, Path = 0; assert( !Acb_ObjIsCo(p, iObj) ); Acb_ObjForEachFanout( p, iObj, iFanout, k ) if ( !Acb_ObjSlack(p, iFanout) ) Path += Acb_ObjPathR(p, iFanout); return Acb_ObjSetPathR( p, iObj, Path ); } int Acb_NtkComputePathsR( Acb_Ntk_t * p, Vec_Int_t * vTfi, int fReverse ) { int i, iObj, Path = 0; if ( !Acb_NtkHasObjPathR( p ) ) Acb_NtkCleanObjPathR( p ); // it is assumed that vTfi contains CO nodes //assert( Acb_ObjSlack(p, Vec_IntEntry(vTfi, 0)) ); if ( fReverse ) { Vec_IntForEachEntryReverse( vTfi, iObj, i ) { if ( Acb_ObjIsCo(p, iObj) ) Acb_ObjSetPathR( p, iObj, Acb_ObjSlack(p, iObj) == 0 ); else if ( Acb_ObjSlack(p, iObj) ) Acb_ObjSetPathR( p, iObj, 0 ); else Acb_ObjComputePathR( p, iObj ); } } else { Vec_IntForEachEntry( vTfi, iObj, i ) { if ( Acb_ObjIsCo(p, iObj) ) Acb_ObjSetPathR( p, iObj, Acb_ObjSlack(p, iObj) == 0 ); else if ( Acb_ObjSlack(p, iObj) ) Acb_ObjSetPathR( p, iObj, 0 ); else Acb_ObjComputePathR( p, iObj ); } } Acb_NtkForEachCi( p, iObj, i ) Path += Acb_ObjPathR(p, iObj); // assert( p->nPaths == Path ); p->nPaths = Path; return Path; } void Acb_NtkPrintPaths( Acb_Ntk_t * p ) { int iObj; Acb_NtkForEachObj( p, iObj ) { printf( "Obj = %5d : ", iObj ); printf( "LevelD = %5d ", Acb_ObjLevelD(p, iObj) ); printf( "LevelR = %5d ", Acb_ObjLevelR(p, iObj) ); printf( "PathD = %5d ", Acb_ObjPathD(p, iObj) ); printf( "PathR = %5d ", Acb_ObjPathR(p, iObj) ); printf( "Paths = %5d ", Acb_ObjPathD(p, iObj) * Acb_ObjPathR(p, iObj) ); printf( "\n" ); } } int Acb_NtkComputePaths( Acb_Ntk_t * p ) { int LevelD, LevelR; Vec_Int_t * vTfi = Acb_ObjCollectTfi( p, -1, 1 ); Vec_Int_t * vTfo = Acb_ObjCollectTfo( p, -1, 1 ); Acb_NtkComputeLevelD( p, vTfo ); LevelD = p->LevelMax; Acb_NtkComputeLevelR( p, vTfi ); LevelR = p->LevelMax; assert( LevelD == LevelR ); Acb_NtkComputePathsD( p, vTfo, 1 ); Acb_NtkComputePathsR( p, vTfi, 1 ); return p->nPaths; } void Abc_NtkComputePaths( Abc_Ntk_t * p ) { extern Acb_Ntk_t * Acb_NtkFromAbc( Abc_Ntk_t * p ); Acb_Ntk_t * pNtk = Acb_NtkFromAbc( p ); Acb_NtkCreateFanout( pNtk ); Acb_NtkCleanObjCounts( pNtk ); printf( "Computed %d paths.\n", Acb_NtkComputePaths(pNtk) ); Acb_NtkPrintPaths( pNtk ); Acb_ManFree( pNtk->pDesign ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Acb_ObjUpdatePriority( Acb_Ntk_t * p, int iObj ) { int nPaths; if ( Acb_ObjIsCio(p, iObj) || Acb_ObjLevelD(p, iObj) == 1 ) return; if ( p->vQue == NULL ) { Acb_NtkCleanObjCounts( p ); p->vQue = Vec_QueAlloc( 1000 ); Vec_QueSetPriority( p->vQue, Vec_FltArrayP(&p->vCounts) ); } nPaths = Acb_ObjPathD(p, iObj) * Acb_ObjPathR(p, iObj); Acb_ObjSetCounts( p, iObj, (float)nPaths ); if ( Vec_QueIsMember( p->vQue, iObj ) ) { //printf( "Updating object %d with count %d\n", iObj, nPaths ); Vec_QueUpdate( p->vQue, iObj ); } else if ( nPaths ) { //printf( "Adding object %d with count %d\n", iObj, nPaths ); Vec_QuePush( p->vQue, iObj ); } } void Acb_NtkUpdateTiming( Acb_Ntk_t * p, int iObj ) { int i, Entry, LevelMax = p->LevelMax; int LevelD, LevelR, nPaths1, nPaths2; // assuming that direct level of the new nodes (including iObj) is up to date Vec_Int_t * vTfi = Acb_ObjCollectTfi( p, iObj, 1 ); Vec_Int_t * vTfo = Acb_ObjCollectTfo( p, iObj, 1 ); if ( iObj > 0 ) { assert( Vec_IntEntryLast(vTfi) == iObj ); assert( Vec_IntEntryLast(vTfo) == iObj ); Vec_IntPop( vTfo ); } Acb_NtkComputeLevelD( p, vTfo ); LevelD = p->LevelMax; Acb_NtkComputeLevelR( p, vTfi ); LevelR = p->LevelMax; assert( LevelD == LevelR ); if ( iObj > 0 && LevelMax > p->LevelMax ) // reduced level { iObj = -1; vTfi = Acb_ObjCollectTfi( p, -1, 1 ); vTfo = Acb_ObjCollectTfo( p, -1, 1 ); Vec_QueClear( p->vQue ); // add backup here } if ( iObj > 0 ) Acb_NtkComputePathsD( p, vTfi, 0 ); Acb_NtkComputePathsD( p, vTfo, 1 ); nPaths1 = p->nPaths; if ( iObj > 0 ) Acb_NtkComputePathsR( p, vTfo, 0 ); Acb_NtkComputePathsR( p, vTfi, 1 ); nPaths2 = p->nPaths; assert( nPaths1 == nPaths2 ); Vec_IntForEachEntry( vTfi, Entry, i ) Acb_ObjUpdatePriority( p, Entry ); if ( iObj > 0 ) Vec_IntForEachEntry( vTfo, Entry, i ) Acb_ObjUpdatePriority( p, Entry ); // printf( "Updating timing for object %d.\n", iObj ); // Acb_NtkPrintPaths( p ); // while ( (Entry = (int)Vec_QueTopPriority(p->vQue)) > 0 ) // printf( "Obj = %5d : Prio = %d.\n", Vec_QuePop(p->vQue), Entry ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Acb_NtkPrintNode( Acb_Ntk_t * p, int iObj ) { int k, iFanin, * pFanins; printf( "Node %5d : ", iObj ); Acb_ObjForEachFaninFast( p, iObj, pFanins, iFanin, k ) printf( "%d ", iFanin ); printf( "LevelD = %d. LevelR = %d.\n", Acb_ObjLevelD(p, iObj), Acb_ObjLevelR(p, iObj) ); } int Acb_NtkCreateNode( Acb_Ntk_t * p, word uTruth, Vec_Int_t * vSupp ) { int Pivot = Acb_ObjAlloc( p, ABC_OPER_LUT, Vec_IntSize(vSupp), 0 ); Acb_ObjSetTruth( p, Pivot, uTruth ); Acb_ObjAddFanins( p, Pivot, vSupp ); Acb_ObjAddFaninFanout( p, Pivot ); Acb_ObjComputeLevelD( p, Pivot ); return Pivot; } void Acb_NtkResetNode( Acb_Ntk_t * p, int Pivot, word uTruth, Vec_Int_t * vSupp ) { // remember old fanins int k, iFanin, * pFanins; Vec_Int_t * vFanins = Vec_IntAlloc( 6 ); assert( !Acb_ObjIsCio(p, Pivot) ); Acb_ObjForEachFaninFast( p, Pivot, pFanins, iFanin, k ) Vec_IntPush( vFanins, iFanin ); // update function Vec_WrdSetEntry( &p->vObjTruth, Pivot, uTruth ); Vec_IntErase( Vec_WecEntry(&p->vCnfs, Pivot) ); // remove old fanins Acb_ObjRemoveFaninFanout( p, Pivot ); Acb_ObjRemoveFanins( p, Pivot ); // add new fanins if ( vSupp != NULL ) { assert( Acb_ObjFanoutNum(p, Pivot) > 0 ); Acb_ObjAddFanins( p, Pivot, vSupp ); Acb_ObjAddFaninFanout( p, Pivot ); } else if ( Acb_ObjFanoutNum(p, Pivot) == 0 ) Acb_ObjCleanType( p, Pivot ); // delete dangling fanins Vec_IntForEachEntry( vFanins, iFanin, k ) if ( !Acb_ObjIsCio(p, iFanin) && Acb_ObjFanoutNum(p, iFanin) == 0 ) Acb_NtkResetNode( p, iFanin, 0, NULL ); Vec_IntFree( vFanins ); } void Acb_NtkSaveSupport( Acb_Ntk_t * p, int iObj ) { int k, iFanin, * pFanins; Vec_IntClear( &p->vSuppOld ); Acb_ObjForEachFaninFast( p, iObj, pFanins, iFanin, k ) Vec_IntPush( &p->vSuppOld, iFanin ); } void Acb_NtkUpdateNode( Acb_Ntk_t * p, int Pivot, word uTruth, Vec_Int_t * vSupp ) { //int Level = Acb_ObjLevelD(p, Pivot); Acb_NtkSaveSupport( p, Pivot ); //Acb_NtkPrintNode( p, Pivot ); Acb_NtkResetNode( p, Pivot, uTruth, vSupp ); Acb_ObjComputeLevelD( p, Pivot ); //assert( Level > Acb_ObjLevelD(p, Pivot) ); //Acb_NtkPrintNode( p, Pivot ); if ( p->vQue == NULL ) Acb_NtkUpdateLevelD( p, Pivot ); else // Acb_NtkUpdateTiming( p, Pivot ); Acb_NtkUpdateTiming( p, -1 ); Vec_IntClear( &p->vSuppOld ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END