mirror of https://github.com/YosysHQ/abc.git
350 lines
11 KiB
C
350 lines
11 KiB
C
/**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
|
|
|