/**CFile**************************************************************** FileName [abcIfif.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Experiment with technology mapping.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcIfif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "map/if/if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define IFIF_MAX_LEAVES 6 typedef struct Abc_IffObj_t_ Abc_IffObj_t; struct Abc_IffObj_t_ { float Delay[IFIF_MAX_LEAVES+1]; // separate delay // int nLeaves; // int pLeaves[IFIF_MAX_LEAVES]; }; typedef struct Abc_IffMan_t_ Abc_IffMan_t; struct Abc_IffMan_t_ { Abc_Ntk_t * pNtk; Ifif_Par_t * pPars; // internal data int nObjs; Abc_IffObj_t * pObjs; }; static inline Abc_IffObj_t * Abc_IffObj( Abc_IffMan_t * p, int i ) { assert( i >= 0 && i < p->nObjs ); return p->pObjs + i; } static inline float Abc_IffDelay( Abc_IffMan_t * p, Abc_Obj_t * pObj, int fDelay1 ) { return Abc_IffObj(p, Abc_ObjId(pObj))->Delay[fDelay1]; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_IffMan_t * Abc_NtkIfifStart( Abc_Ntk_t * pNtk, Ifif_Par_t * pPars ) { Abc_IffMan_t * p; p = ABC_CALLOC( Abc_IffMan_t, 1 ); p->pNtk = pNtk; p->pPars = pPars; // internal data p->nObjs = Abc_NtkObjNumMax( pNtk ); p->pObjs = ABC_CALLOC( Abc_IffObj_t, p->nObjs ); return p; } void Abc_NtkIfifStop( Abc_IffMan_t * p ) { // internal data ABC_FREE( p->pObjs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Collects fanins into ppNodes in decreasing order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ObjSortByDelay( Abc_IffMan_t * p, Abc_Obj_t * pObj, int fDelay1, Abc_Obj_t ** ppNodes ) { Abc_Obj_t * pFanin; int i, a, k = 0; Abc_ObjForEachFanin( pObj, pFanin, i ) { ppNodes[k++] = pFanin; if ( Abc_ObjIsCi(pFanin) ) continue; for ( a = k-1; a > 0; a-- ) if ( Abc_IffDelay(p, ppNodes[a-1], fDelay1) + p->pPars->pLutDelays[a-1] < Abc_IffDelay(p, ppNodes[a], fDelay1) + p->pPars->pLutDelays[a] ) ABC_SWAP( Abc_Obj_t *, ppNodes[a-1], ppNodes[a] ); } /* for ( a = 1; a < k; a++ ) { float D1 = Abc_IffDelay(p, ppNodes[a-1], fDelay1); float D2 = Abc_IffDelay(p, ppNodes[a], fDelay1); if ( Abc_ObjIsCi(ppNodes[a-1]) || Abc_ObjIsCi(ppNodes[a]) ) continue; assert( Abc_IffDelay(p, ppNodes[a-1], fDelay1) + p->pPars->pLutDelays[a-1] >= Abc_IffDelay(p, ppNodes[a], fDelay1) + p->pPars->pLutDelays[a] - 0.01 ); } */ } /**Function************************************************************* Synopsis [This is the delay which object has all by itself.] Description [This delay is stored in Delay0.] SideEffects [] SeeAlso [] ***********************************************************************/ float Abc_ObjDelay0( Abc_IffMan_t * p, Abc_Obj_t * pObj ) { int i; float Delay0 = 0; Abc_Obj_t * ppNodes[6]; Abc_ObjSortByDelay( p, pObj, 1, ppNodes ); for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ ) Delay0 = Abc_MaxFloat( Delay0, Abc_IffDelay(p, ppNodes[i], 1) + p->pPars->pLutDelays[i] ); return Delay0; } /**Function************************************************************* Synopsis [This is the delay object has in the structure.] Description [This delay is stored in Delay1.] SideEffects [] SeeAlso [] ***********************************************************************/ float Abc_ObjDelay1( Abc_IffMan_t * p, Abc_Obj_t * pObj ) { int i, fVeryVerbose = 0; // Abc_IffObj_t * pIfif = Abc_IffObj( p, Abc_ObjId(pObj) ); Abc_Obj_t * ppNodes[6]; float Delay1, DelayNew; if ( Abc_ObjFaninNum(pObj) == 0 ) return 0; // sort fanins by delay1+LutDelay Abc_ObjSortByDelay( p, pObj, 1, ppNodes ); // print verbose results if ( fVeryVerbose ) { printf( "Object %d Level %d\n", Abc_ObjId(pObj), Abc_ObjLevel(pObj) ); for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ ) { printf( "Fanin %d : ", i ); printf( "D0 %3.2f ", Abc_IffDelay(p, ppNodes[i], 0) ); printf( "D0* %3.2f ", Abc_IffDelay(p, ppNodes[i], 0) + p->pPars->pLutDelays[i] - p->pPars->DelayWire ); printf( "D1 %3.2f", Abc_IffDelay(p, ppNodes[i], 1) + p->pPars->pLutDelays[i] ); printf( "\n" ); } printf( "\n" ); } /* // for the first nDegree delays, sort them by the minimum Delay1+LutDelay and Delay0-Wire+LutDelay Delay1 = 0; pIfif->nLeaves = 0; for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ ) { if ( Abc_ObjIsNode(ppNodes[i]) && pIfif->nLeaves < p->pPars->nDegree ) { DelayNew = Abc_MinFloat( Abc_IffDelay(p, ppNodes[i], 1) + p->pPars->pLutDelays[i], Abc_IffDelay(p, ppNodes[i], 0) + p->pPars->pLutDelays[i] - p->pPars->DelayWire ); pIfif->pLeaves[pIfif->nLeaves++] = Abc_ObjId(ppNodes[i]); } else DelayNew = Abc_IffDelay(p, ppNodes[i], 1) + p->pPars->pLutDelays[i]; Delay1 = Abc_MaxFloat( Delay1, DelayNew ); } */ // for the first nDegree delays, sort them by the minimum Delay1+LutDelay and Delay0-Wire+LutDelay Delay1 = 0; for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ ) { if ( i < p->pPars->nDegree ) DelayNew = Abc_MinFloat( Abc_IffDelay(p, ppNodes[i], 1) + p->pPars->pLutDelays[i], Abc_IffDelay(p, ppNodes[i], 0) + p->pPars->pLutDelays[i] - p->pPars->DelayWire ); else DelayNew = Abc_IffDelay(p, ppNodes[i], 1) + p->pPars->pLutDelays[i]; Delay1 = Abc_MaxFloat( Delay1, DelayNew ); } assert( Delay1 > 0 ); return Delay1; } /**Function************************************************************* Synopsis [This is the delay which object has all by itself.] Description [This delay is stored in Delay0.] SideEffects [] SeeAlso [] ***********************************************************************/ float Abc_ObjDelayDegree( Abc_IffMan_t * p, Abc_Obj_t * pObj, int d ) { int i; float Delay0 = 0, DelayNew; Abc_Obj_t * ppNodes[6]; assert( d >= 0 && d <= p->pPars->nDegree ); Abc_ObjSortByDelay( p, pObj, p->pPars->nDegree, ppNodes ); for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ ) { DelayNew = Abc_IffDelay(p, ppNodes[i], p->pPars->nDegree) + p->pPars->pLutDelays[i]; if ( i == 0 && d > 0 ) DelayNew = Abc_MinFloat(DelayNew, Abc_IffDelay(p, ppNodes[i], d-1) + p->pPars->pLutDelays[i] - p->pPars->DelayWire ); Delay0 = Abc_MaxFloat( Delay0, DelayNew ); } return Delay0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPerformIfif( Abc_Ntk_t * pNtk, Ifif_Par_t * pPars ) { Abc_IffMan_t * p; Abc_IffObj_t * pIffObj; Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; float Delay, Delay10, DegreeFinal; int i, d, Count10; assert( pPars->pLutLib->LutMax >= 0 && pPars->pLutLib->LutMax <= IFIF_MAX_LEAVES ); assert( pPars->nLutSize >= 0 && pPars->nLutSize <= IFIF_MAX_LEAVES ); assert( pPars->nDegree >= 0 && pPars->nDegree <= IFIF_MAX_LEAVES ); // convert to AIGs Abc_NtkToAig( pNtk ); Abc_NtkLevel( pNtk ); // print parameters if ( pPars->fVerbose ) { printf( "Running mapper into LUT structures with the following parameters:\n" ); printf( "Pin+Wire: {" ); for ( i = 0; i < pPars->pLutLib->LutMax; i++ ) printf( " %3.2f", pPars->pLutDelays[i] ); printf( " } " ); printf( "Wire %3.2f Degree %d Type: %s\n", pPars->DelayWire, pPars->nDegree, pPars->fCascade? "Cascade" : "Cluster" ); } // start manager p = Abc_NtkIfifStart( pNtk, pPars ); // printf( "Running experiment with LUT delay %d and degree %d (LUT size is %d).\n", DelayWire, nDegree, nLutSize ); // compute the delay vNodes = Abc_NtkDfs( pNtk, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { assert( Abc_ObjIsNode(pObj) ); pIffObj = Abc_IffObj( p, Abc_ObjId(pObj) ); if ( pPars->fCascade ) { for ( d = 0; d <= pPars->nDegree; d++ ) pIffObj->Delay[d] = Abc_ObjDelayDegree( p, pObj, d ); } else { pIffObj->Delay[0] = Abc_ObjDelay0( p, pObj ); pIffObj->Delay[1] = Abc_ObjDelay1( p, pObj ); } } // get final degree number if ( pPars->fCascade ) DegreeFinal = pPars->nDegree; else DegreeFinal = 1; if ( p->pPars->fVeryVerbose ) Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { printf( "Node %3d : Lev =%3d ", Abc_ObjId(pObj), Abc_ObjLevel(pObj) ); for ( d = 0; d <= DegreeFinal; d++ ) printf( "Del%d =%4.2f ", d, Abc_IffDelay(p, pObj, d) ); printf( "\n" ); } Vec_PtrFree( vNodes ); // consider delay at the outputs Delay = 0; Abc_NtkForEachCo( pNtk, pObj, i ) Delay = Abc_MaxFloat( Delay, Abc_IffDelay(p, Abc_ObjFanin0(pObj), DegreeFinal) ); Delay10 = 0.9 * Delay; // consider delay at the outputs Count10 = 0; Abc_NtkForEachCo( pNtk, pObj, i ) if ( Abc_IffDelay(p, Abc_ObjFanin0(pObj), DegreeFinal) >= Delay10 ) Count10++; printf( "Critical delay %5.2f. Critical outputs %5.2f %%\n", Delay, 100.0 * Count10 / Abc_NtkCoNum(pNtk) ); // printf( "%.2f %.2f\n", Delay, 100.0 * Count10 / Abc_NtkCoNum(pNtk) ); // derive a new network // stop manager Abc_NtkIfifStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END