mirror of https://github.com/YosysHQ/abc.git
Improved buffering.
This commit is contained in:
parent
4c6804c3ae
commit
1dca7458f3
|
|
@ -2451,10 +2451,6 @@ SOURCE=.\src\map\scl\scl.h
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\map\scl\sclBuff.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\map\scl\sclBuffer.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ int Map_MatchNodePhase( Map_Man_t * p, Map_Node_t * pNode, int fPhase )
|
|||
for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
|
||||
{
|
||||
// limit gate sizes based on fanout count
|
||||
if ( (pNode->nRefs > 8 && pCut->nLeaves > 2) || (pNode->nRefs > 4 && pCut->nLeaves > 3) )
|
||||
if ( (pNode->nRefs > 3 && pCut->nLeaves > 2) || (pNode->nRefs > 1 && pCut->nLeaves > 3) )
|
||||
continue;
|
||||
pMatch = pCut->M + fPhase;
|
||||
if ( pMatch->pSupers == NULL )
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
SRC += src/map/scl/scl.c \
|
||||
src/map/scl/sclBuff.c \
|
||||
src/map/scl/sclBuffer.c \
|
||||
src/map/scl/sclDnsize.c \
|
||||
src/map/scl/sclLib.c \
|
||||
|
|
|
|||
|
|
@ -554,14 +554,15 @@ int Scl_CommandBuffer( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
{
|
||||
Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
|
||||
Abc_Ntk_t * pNtkRes;
|
||||
int Degree, fUseInvs;
|
||||
int FanMin, FanMax, fUseInvs;
|
||||
int c, fVerbose;
|
||||
int fOldAlgo = 0;
|
||||
Degree = 4;
|
||||
fUseInvs = 0;
|
||||
fVerbose = 0;
|
||||
FanMin = 6;
|
||||
FanMax = 14;
|
||||
fUseInvs = 0;
|
||||
fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "Naivh" ) ) != EOF )
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "NMaivh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
|
|
@ -571,9 +572,20 @@ int Scl_CommandBuffer( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
Degree = atoi(argv[globalUtilOptind]);
|
||||
FanMin = atoi(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( Degree < 0 )
|
||||
if ( FanMin < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'M':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-M\" should be followed by a positive integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
FanMax = atoi(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( FanMax < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'a':
|
||||
|
|
@ -605,9 +617,9 @@ int Scl_CommandBuffer( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
|
||||
// modify the current network
|
||||
if ( fOldAlgo )
|
||||
pNtkRes = Abc_SclPerformBuffering( pNtk, Degree, fUseInvs, fVerbose );
|
||||
pNtkRes = Abc_SclPerformBuffering( pNtk, FanMax, fUseInvs, fVerbose );
|
||||
else
|
||||
pNtkRes = Abc_SclBufPerform( pNtk, fVerbose );
|
||||
pNtkRes = Abc_SclBufPerform( pNtk, FanMin, FanMax, fVerbose );
|
||||
if ( pNtkRes == NULL )
|
||||
{
|
||||
Abc_Print( -1, "The command has failed.\n" );
|
||||
|
|
@ -618,9 +630,10 @@ int Scl_CommandBuffer( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
return 0;
|
||||
|
||||
usage:
|
||||
fprintf( pAbc->Err, "usage: buffer [-N num] [-aivh]\n" );
|
||||
fprintf( pAbc->Err, "usage: buffer [-NM num] [-aivh]\n" );
|
||||
fprintf( pAbc->Err, "\t performs buffering of the mapped network\n" );
|
||||
fprintf( pAbc->Err, "\t-N <num> : the max allowed fanout count of node/buffer [default = %d]\n", Degree );
|
||||
fprintf( pAbc->Err, "\t-N <num> : the min fanout considered by the algorithm [default = %d]\n", FanMin );
|
||||
fprintf( pAbc->Err, "\t-M <num> : the max allowed fanout count of node/buffer [default = %d]\n", FanMax );
|
||||
fprintf( pAbc->Err, "\t-a : toggle using old algorithm [default = %s]\n", fOldAlgo? "yes": "no" );
|
||||
fprintf( pAbc->Err, "\t-i : toggle using interters instead of buffers [default = %s]\n", fUseInvs? "yes": "no" );
|
||||
fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
|
|
|
|||
|
|
@ -1,238 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [sclBuff.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Standard-cell library representation.]
|
||||
|
||||
Synopsis [Buffering algorithms.]
|
||||
|
||||
Author [Alan Mishchenko, Niklas Een]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - August 24, 2012.]
|
||||
|
||||
Revision [$Id: sclBuff.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "sclSize.h"
|
||||
#include "map/mio/mio.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Make sure the network is in topo order without dangling nodes.]
|
||||
|
||||
Description [Returns 1 iff the network is fine.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_SclCheckNtk( Abc_Ntk_t * p, int fVerbose )
|
||||
{
|
||||
Abc_Obj_t * pObj, * pFanin;
|
||||
int i, k, fFlag = 1;
|
||||
Abc_NtkIncrementTravId( p );
|
||||
Abc_NtkForEachCi( p, pObj, i )
|
||||
Abc_NodeSetTravIdCurrent( pObj );
|
||||
Abc_NtkForEachNode( p, pObj, i )
|
||||
{
|
||||
Abc_ObjForEachFanin( pObj, pFanin, k )
|
||||
if ( !Abc_NodeIsTravIdCurrent( pFanin ) )
|
||||
printf( "obj %d and its fanin %d are not in the topo order\n", Abc_ObjId(pObj), Abc_ObjId(pFanin) ), fFlag = 0;
|
||||
Abc_NodeSetTravIdCurrent( pObj );
|
||||
if ( Abc_ObjFanoutNum(pObj) == 0 )
|
||||
printf( "node %d has no fanout\n", Abc_ObjId(pObj) ), fFlag = 0;
|
||||
if ( !fFlag )
|
||||
break;
|
||||
}
|
||||
if ( fFlag && fVerbose )
|
||||
printf( "The network is in topo order and no dangling nodes.\n" );
|
||||
return fFlag;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_SclCheckNtk2( Abc_Ntk_t * p )
|
||||
{
|
||||
Abc_Obj_t * pObj, * pFanout;
|
||||
int i, k;
|
||||
Abc_NtkStartReverseLevels( p, 0 );
|
||||
Abc_NtkForEachNode( p, pObj, i )
|
||||
{
|
||||
if ( Abc_ObjFanoutNum(pObj) <= 3 )
|
||||
continue;
|
||||
printf( "Node %5d (%2d) : fans = %3d ", i, Abc_ObjLevel(pObj), Abc_ObjFanoutNum(pObj) );
|
||||
Abc_ObjForEachFanout( pObj, pFanout, k )
|
||||
printf( "%d ", Abc_ObjReverseLevel(pFanout) );
|
||||
printf( "\n" );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs buffering of the mapped network.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NodeCompareLevels( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 )
|
||||
{
|
||||
int Diff = Abc_ObjLevel(*pp1) - Abc_ObjLevel(*pp2);
|
||||
if ( Diff < 0 )
|
||||
return -1;
|
||||
if ( Diff > 0 )
|
||||
return 1;
|
||||
Diff = (*pp1)->Id - (*pp2)->Id; // needed to make qsort() platform-infependent
|
||||
if ( Diff < 0 )
|
||||
return -1;
|
||||
if ( Diff > 0 )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
int Abc_SclComputeReverseLevel( Abc_Obj_t * pObj )
|
||||
{
|
||||
Abc_Obj_t * pFanout;
|
||||
int i, Level = 0;
|
||||
Abc_ObjForEachFanout( pObj, pFanout, i )
|
||||
Level = Abc_MaxInt( Level, pFanout->Level );
|
||||
return Level + 1;
|
||||
}
|
||||
Abc_Obj_t * Abc_SclPerformBufferingOne( Abc_Obj_t * pObj, int Degree, int fUseInvs, int fVerbose )
|
||||
{
|
||||
Vec_Ptr_t * vFanouts;
|
||||
Abc_Obj_t * pBuffer, * pFanout;
|
||||
int i, Degree0 = Degree;
|
||||
assert( Abc_ObjFanoutNum(pObj) > Degree );
|
||||
// collect fanouts and sort by reverse level
|
||||
vFanouts = Vec_PtrAlloc( Abc_ObjFanoutNum(pObj) );
|
||||
Abc_NodeCollectFanouts( pObj, vFanouts );
|
||||
Vec_PtrSort( vFanouts, (int (*)(void))Abc_NodeCompareLevels );
|
||||
// select the first Degree fanouts
|
||||
if ( fUseInvs )
|
||||
pBuffer = Abc_NtkCreateNodeInv( pObj->pNtk, NULL );
|
||||
else
|
||||
pBuffer = Abc_NtkCreateNodeBuf( pObj->pNtk, NULL );
|
||||
// check if it is possible to not increase level
|
||||
if ( Vec_PtrSize(vFanouts) < 2 * Degree )
|
||||
{
|
||||
Abc_Obj_t * pFanPrev = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, Vec_PtrSize(vFanouts)-1-Degree);
|
||||
Abc_Obj_t * pFanThis = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, Degree-1);
|
||||
Abc_Obj_t * pFanLast = (Abc_Obj_t *)Vec_PtrEntryLast(vFanouts);
|
||||
if ( Abc_ObjLevel(pFanThis) == Abc_ObjLevel(pFanLast) &&
|
||||
Abc_ObjLevel(pFanPrev) < Abc_ObjLevel(pFanThis) )
|
||||
{
|
||||
// find the first one whose level is the same as last
|
||||
Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, i )
|
||||
if ( Abc_ObjLevel(pFanout) == Abc_ObjLevel(pFanLast) )
|
||||
break;
|
||||
assert( i < Vec_PtrSize(vFanouts) );
|
||||
if ( i > 1 )
|
||||
Degree = i;
|
||||
}
|
||||
// make the last two more well-balanced
|
||||
if ( Degree == Degree0 && Degree > Vec_PtrSize(vFanouts) - Degree )
|
||||
Degree = Vec_PtrSize(vFanouts)/2 + (Vec_PtrSize(vFanouts) & 1);
|
||||
assert( Degree <= Degree0 );
|
||||
}
|
||||
// select fanouts
|
||||
Vec_PtrForEachEntryStop( Abc_Obj_t *, vFanouts, pFanout, i, Degree )
|
||||
Abc_ObjPatchFanin( pFanout, pObj, pBuffer );
|
||||
if ( fVerbose )
|
||||
{
|
||||
printf( "%5d : ", Abc_ObjId(pObj) );
|
||||
Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, i )
|
||||
printf( "%d%s ", Abc_ObjLevel(pFanout), i == Degree-1 ? " " : "" );
|
||||
printf( "\n" );
|
||||
}
|
||||
Vec_PtrFree( vFanouts );
|
||||
Abc_ObjAddFanin( pBuffer, pObj );
|
||||
pBuffer->Level = Abc_SclComputeReverseLevel( pBuffer );
|
||||
return pBuffer;
|
||||
}
|
||||
void Abc_SclPerformBuffering_rec( Abc_Obj_t * pObj, int Degree, int fUseInvs, int fVerbose )
|
||||
{
|
||||
Abc_Obj_t * pFanout;
|
||||
int i;
|
||||
if ( Abc_NodeIsTravIdCurrent( pObj ) )
|
||||
return;
|
||||
Abc_NodeSetTravIdCurrent( pObj );
|
||||
pObj->Level = 0;
|
||||
if ( Abc_ObjIsCo(pObj) )
|
||||
return;
|
||||
assert( Abc_ObjIsCi(pObj) || Abc_ObjIsNode(pObj) );
|
||||
// buffer fanouts and collect reverse levels
|
||||
Abc_ObjForEachFanout( pObj, pFanout, i )
|
||||
Abc_SclPerformBuffering_rec( pFanout, Degree, fUseInvs, fVerbose );
|
||||
// perform buffering as long as needed
|
||||
while ( Abc_ObjFanoutNum(pObj) > Degree )
|
||||
Abc_SclPerformBufferingOne( pObj, Degree, fUseInvs, fVerbose );
|
||||
// compute the new level of the node
|
||||
pObj->Level = Abc_SclComputeReverseLevel( pObj );
|
||||
}
|
||||
Abc_Ntk_t * Abc_SclPerformBuffering( Abc_Ntk_t * p, int Degree, int fUseInvs, int fVerbose )
|
||||
{
|
||||
Vec_Int_t * vCiLevs;
|
||||
Abc_Ntk_t * pNew;
|
||||
Abc_Obj_t * pObj;
|
||||
int i;
|
||||
assert( Abc_NtkHasMapping(p) );
|
||||
if ( fUseInvs )
|
||||
printf( "Warning!!! Using inverters instead of buffers.\n" );
|
||||
// remember CI levels
|
||||
vCiLevs = Vec_IntAlloc( Abc_NtkCiNum(p) );
|
||||
Abc_NtkForEachCi( p, pObj, i )
|
||||
Vec_IntPush( vCiLevs, Abc_ObjLevel(pObj) );
|
||||
// perform buffering
|
||||
Abc_NtkIncrementTravId( p );
|
||||
Abc_NtkForEachCi( p, pObj, i )
|
||||
Abc_SclPerformBuffering_rec( pObj, Degree, fUseInvs, fVerbose );
|
||||
// recompute logic levels
|
||||
Abc_NtkForEachCi( p, pObj, i )
|
||||
pObj->Level = Vec_IntEntry( vCiLevs, i );
|
||||
Abc_NtkForEachNode( p, pObj, i )
|
||||
Abc_ObjLevelNew( pObj );
|
||||
Vec_IntFree( vCiLevs );
|
||||
// duplication in topo order
|
||||
pNew = Abc_NtkDupDfs( p );
|
||||
Abc_SclCheckNtk( pNew, fVerbose );
|
||||
// Abc_NtkDelete( pNew );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -59,6 +59,7 @@ struct Buf_Man_t_
|
|||
int nDuplicate;
|
||||
int nBranch0;
|
||||
int nBranch1;
|
||||
int nBranchCrit;
|
||||
};
|
||||
|
||||
static inline int Abc_BufNodeArr( Buf_Man_t * p, Abc_Obj_t * pObj ) { return Vec_IntEntry( p->vArr, Abc_ObjId(pObj) ); }
|
||||
|
|
@ -74,6 +75,177 @@ static inline int Abc_BufEdgeSlack( Buf_Man_t * p, Abc_Obj_t * pObj, Abc_Obj_t
|
|||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Make sure the network is in topo order without dangling nodes.]
|
||||
|
||||
Description [Returns 1 iff the network is fine.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_SclCheckNtk( Abc_Ntk_t * p, int fVerbose )
|
||||
{
|
||||
Abc_Obj_t * pObj, * pFanin;
|
||||
int i, k, fFlag = 1;
|
||||
Abc_NtkIncrementTravId( p );
|
||||
Abc_NtkForEachCi( p, pObj, i )
|
||||
Abc_NodeSetTravIdCurrent( pObj );
|
||||
Abc_NtkForEachNode( p, pObj, i )
|
||||
{
|
||||
Abc_ObjForEachFanin( pObj, pFanin, k )
|
||||
if ( !Abc_NodeIsTravIdCurrent( pFanin ) )
|
||||
printf( "obj %d and its fanin %d are not in the topo order\n", Abc_ObjId(pObj), Abc_ObjId(pFanin) ), fFlag = 0;
|
||||
Abc_NodeSetTravIdCurrent( pObj );
|
||||
if ( Abc_ObjFanoutNum(pObj) == 0 )
|
||||
printf( "node %d has no fanout\n", Abc_ObjId(pObj) ), fFlag = 0;
|
||||
if ( !fFlag )
|
||||
break;
|
||||
}
|
||||
if ( fFlag && fVerbose )
|
||||
printf( "The network is in topo order and no dangling nodes.\n" );
|
||||
return fFlag;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs buffering of the mapped network (old code).]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NodeCompareLevels( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 )
|
||||
{
|
||||
int Diff = Abc_ObjLevel(*pp1) - Abc_ObjLevel(*pp2);
|
||||
if ( Diff < 0 )
|
||||
return -1;
|
||||
if ( Diff > 0 )
|
||||
return 1;
|
||||
Diff = (*pp1)->Id - (*pp2)->Id; // needed to make qsort() platform-infependent
|
||||
if ( Diff < 0 )
|
||||
return -1;
|
||||
if ( Diff > 0 )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
int Abc_SclComputeReverseLevel( Abc_Obj_t * pObj )
|
||||
{
|
||||
Abc_Obj_t * pFanout;
|
||||
int i, Level = 0;
|
||||
Abc_ObjForEachFanout( pObj, pFanout, i )
|
||||
Level = Abc_MaxInt( Level, pFanout->Level );
|
||||
return Level + 1;
|
||||
}
|
||||
Abc_Obj_t * Abc_SclPerformBufferingOne( Abc_Obj_t * pObj, int Degree, int fUseInvs, int fVerbose )
|
||||
{
|
||||
Vec_Ptr_t * vFanouts;
|
||||
Abc_Obj_t * pBuffer, * pFanout;
|
||||
int i, Degree0 = Degree;
|
||||
assert( Abc_ObjFanoutNum(pObj) > Degree );
|
||||
// collect fanouts and sort by reverse level
|
||||
vFanouts = Vec_PtrAlloc( Abc_ObjFanoutNum(pObj) );
|
||||
Abc_NodeCollectFanouts( pObj, vFanouts );
|
||||
Vec_PtrSort( vFanouts, (int (*)(void))Abc_NodeCompareLevels );
|
||||
// select the first Degree fanouts
|
||||
if ( fUseInvs )
|
||||
pBuffer = Abc_NtkCreateNodeInv( pObj->pNtk, NULL );
|
||||
else
|
||||
pBuffer = Abc_NtkCreateNodeBuf( pObj->pNtk, NULL );
|
||||
// check if it is possible to not increase level
|
||||
if ( Vec_PtrSize(vFanouts) < 2 * Degree )
|
||||
{
|
||||
Abc_Obj_t * pFanPrev = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, Vec_PtrSize(vFanouts)-1-Degree);
|
||||
Abc_Obj_t * pFanThis = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, Degree-1);
|
||||
Abc_Obj_t * pFanLast = (Abc_Obj_t *)Vec_PtrEntryLast(vFanouts);
|
||||
if ( Abc_ObjLevel(pFanThis) == Abc_ObjLevel(pFanLast) &&
|
||||
Abc_ObjLevel(pFanPrev) < Abc_ObjLevel(pFanThis) )
|
||||
{
|
||||
// find the first one whose level is the same as last
|
||||
Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, i )
|
||||
if ( Abc_ObjLevel(pFanout) == Abc_ObjLevel(pFanLast) )
|
||||
break;
|
||||
assert( i < Vec_PtrSize(vFanouts) );
|
||||
if ( i > 1 )
|
||||
Degree = i;
|
||||
}
|
||||
// make the last two more well-balanced
|
||||
if ( Degree == Degree0 && Degree > Vec_PtrSize(vFanouts) - Degree )
|
||||
Degree = Vec_PtrSize(vFanouts)/2 + (Vec_PtrSize(vFanouts) & 1);
|
||||
assert( Degree <= Degree0 );
|
||||
}
|
||||
// select fanouts
|
||||
Vec_PtrForEachEntryStop( Abc_Obj_t *, vFanouts, pFanout, i, Degree )
|
||||
Abc_ObjPatchFanin( pFanout, pObj, pBuffer );
|
||||
if ( fVerbose )
|
||||
{
|
||||
printf( "%5d : ", Abc_ObjId(pObj) );
|
||||
Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, i )
|
||||
printf( "%d%s ", Abc_ObjLevel(pFanout), i == Degree-1 ? " " : "" );
|
||||
printf( "\n" );
|
||||
}
|
||||
Vec_PtrFree( vFanouts );
|
||||
Abc_ObjAddFanin( pBuffer, pObj );
|
||||
pBuffer->Level = Abc_SclComputeReverseLevel( pBuffer );
|
||||
return pBuffer;
|
||||
}
|
||||
void Abc_SclPerformBuffering_rec( Abc_Obj_t * pObj, int Degree, int fUseInvs, int fVerbose )
|
||||
{
|
||||
Abc_Obj_t * pFanout;
|
||||
int i;
|
||||
if ( Abc_NodeIsTravIdCurrent( pObj ) )
|
||||
return;
|
||||
Abc_NodeSetTravIdCurrent( pObj );
|
||||
pObj->Level = 0;
|
||||
if ( Abc_ObjIsCo(pObj) )
|
||||
return;
|
||||
assert( Abc_ObjIsCi(pObj) || Abc_ObjIsNode(pObj) );
|
||||
// buffer fanouts and collect reverse levels
|
||||
Abc_ObjForEachFanout( pObj, pFanout, i )
|
||||
Abc_SclPerformBuffering_rec( pFanout, Degree, fUseInvs, fVerbose );
|
||||
// perform buffering as long as needed
|
||||
while ( Abc_ObjFanoutNum(pObj) > Degree )
|
||||
Abc_SclPerformBufferingOne( pObj, Degree, fUseInvs, fVerbose );
|
||||
// compute the new level of the node
|
||||
pObj->Level = Abc_SclComputeReverseLevel( pObj );
|
||||
}
|
||||
Abc_Ntk_t * Abc_SclPerformBuffering( Abc_Ntk_t * p, int Degree, int fUseInvs, int fVerbose )
|
||||
{
|
||||
Vec_Int_t * vCiLevs;
|
||||
Abc_Ntk_t * pNew;
|
||||
Abc_Obj_t * pObj;
|
||||
int i;
|
||||
assert( Abc_NtkHasMapping(p) );
|
||||
if ( fUseInvs )
|
||||
printf( "Warning!!! Using inverters instead of buffers.\n" );
|
||||
// remember CI levels
|
||||
vCiLevs = Vec_IntAlloc( Abc_NtkCiNum(p) );
|
||||
Abc_NtkForEachCi( p, pObj, i )
|
||||
Vec_IntPush( vCiLevs, Abc_ObjLevel(pObj) );
|
||||
// perform buffering
|
||||
Abc_NtkIncrementTravId( p );
|
||||
Abc_NtkForEachCi( p, pObj, i )
|
||||
Abc_SclPerformBuffering_rec( pObj, Degree, fUseInvs, fVerbose );
|
||||
// recompute logic levels
|
||||
Abc_NtkForEachCi( p, pObj, i )
|
||||
pObj->Level = Vec_IntEntry( vCiLevs, i );
|
||||
Abc_NtkForEachNode( p, pObj, i )
|
||||
Abc_ObjLevelNew( pObj );
|
||||
Vec_IntFree( vCiLevs );
|
||||
// duplication in topo order
|
||||
pNew = Abc_NtkDupDfs( p );
|
||||
Abc_SclCheckNtk( pNew, fVerbose );
|
||||
// Abc_NtkDelete( pNew );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
|
@ -134,8 +306,10 @@ void Abc_BufAddToQue( Buf_Man_t * p, Abc_Obj_t * pObj )
|
|||
if ( Abc_ObjFanoutNum(pObj) < p->nFanMin )
|
||||
return;
|
||||
Vec_FltWriteEntry( p->vCounts, Abc_ObjId(pObj), Abc_ObjFanoutNum(pObj) );
|
||||
assert( !Vec_QueIsMember(p->vQue, Abc_ObjId(pObj)) );
|
||||
Vec_QuePush( p->vQue, Abc_ObjId(pObj) );
|
||||
if ( Vec_QueIsMember(p->vQue, Abc_ObjId(pObj)) )
|
||||
Vec_QueUpdate( p->vQue, Abc_ObjId(pObj) );
|
||||
else
|
||||
Vec_QuePush( p->vQue, Abc_ObjId(pObj) );
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -241,7 +415,7 @@ void Abc_BufUpdateDep( Buf_Man_t * p, Abc_Obj_t * pObj )
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Buf_Man_t * Buf_ManStart( Abc_Ntk_t * pNtk )
|
||||
Buf_Man_t * Buf_ManStart( Abc_Ntk_t * pNtk, int FanMin, int FanMax )
|
||||
{
|
||||
Buf_Man_t * p;
|
||||
Abc_Obj_t * pObj;
|
||||
|
|
@ -249,8 +423,8 @@ Buf_Man_t * Buf_ManStart( Abc_Ntk_t * pNtk )
|
|||
int i;
|
||||
p = ABC_CALLOC( Buf_Man_t, 1 );
|
||||
p->pNtk = pNtk;
|
||||
p->nFanMin = 6;
|
||||
// p->nFanMax = 16;
|
||||
p->nFanMin = FanMin;
|
||||
p->nFanMax = FanMax;
|
||||
// allocate arrays
|
||||
p->nObjStart = Abc_NtkObjNumMax(p->pNtk);
|
||||
p->nObjAlloc = (6 * Abc_NtkObjNumMax(p->pNtk) / 3) + 100;
|
||||
|
|
@ -279,15 +453,14 @@ Buf_Man_t * Buf_ManStart( Abc_Ntk_t * pNtk )
|
|||
Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pObj, i )
|
||||
Abc_BufComputeDep( p, pObj );
|
||||
Abc_BufUpdateGlobal( p );
|
||||
// Abc_NtkForEachNode( p->pNtk, pObj, i )
|
||||
// printf( "%4d : %4d %4d\n", i, Abc_BufNodeArr(p, pObj), Abc_BufNodeDep(p, pObj) );
|
||||
// create fanout queue
|
||||
Abc_NtkForEachCi( p->pNtk, pObj, i )
|
||||
Abc_BufAddToQue( p, pObj );
|
||||
Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
|
||||
Abc_BufAddToQue( p, pObj );
|
||||
Vec_PtrFree( vNodes );
|
||||
// print everything
|
||||
// Abc_NtkForEachNode( p->pNtk, pObj, i )
|
||||
// printf( "%4d : %4d %4d\n", i, Abc_BufNodeArr(p, pObj), Abc_BufNodeDep(p, pObj) );
|
||||
p->vDelays = Vec_IntAlloc( 100 );
|
||||
p->vOrder = Vec_IntAlloc( 100 );
|
||||
p->vNonCrit = Vec_IntAlloc( 100 );
|
||||
|
|
@ -297,8 +470,8 @@ Buf_Man_t * Buf_ManStart( Abc_Ntk_t * pNtk )
|
|||
}
|
||||
void Buf_ManStop( Buf_Man_t * p )
|
||||
{
|
||||
printf( "Sep = %d. Dup = %d. Br0 = %d. Br1 = %d. ",
|
||||
p->nSeparate, p->nDuplicate, p->nBranch0, p->nBranch1 );
|
||||
printf( "Sep = %d. Dup = %d. Br0 = %d. Br1 = %d. BrC = %d. ",
|
||||
p->nSeparate, p->nDuplicate, p->nBranch0, p->nBranch1, p->nBranchCrit );
|
||||
printf( "Orig = %d. Add = %d. Rem = %d.\n",
|
||||
p->nObjStart, Abc_NtkObjNumMax(p->pNtk) - p->nObjStart,
|
||||
p->nObjAlloc - Abc_NtkObjNumMax(p->pNtk) );
|
||||
|
|
@ -337,17 +510,14 @@ Vec_Int_t * Abc_BufSortByDelay( Buf_Man_t * p, int iPivot )
|
|||
Abc_ObjForEachFanout( pObj, pFanout, i )
|
||||
{
|
||||
int Slack = Abc_BufEdgeSlack(p, pObj, pFanout);
|
||||
if ( Slack < 0 )
|
||||
printf( "%d ", Slack );
|
||||
assert( Slack >= 0 );
|
||||
Vec_IntPush( p->vDelays, Abc_MaxInt(0, Slack) );
|
||||
}
|
||||
pOrder = Abc_QuickSortCost( Vec_IntArray(p->vDelays), Vec_IntSize(p->vDelays), 0 );
|
||||
//Vec_IntPrint( p->vDelays );
|
||||
Vec_IntClear( p->vOrder );
|
||||
for ( i = 0; i < Vec_IntSize(p->vDelays); i++ )
|
||||
Vec_IntPush( p->vOrder, Abc_ObjId(Abc_ObjFanout(pObj, pOrder[i])) );
|
||||
ABC_FREE( pOrder );
|
||||
// print
|
||||
// for ( i = 0; i < Vec_IntSize(p->vDelays); i++ )
|
||||
// printf( "%5d - %5d ", Vec_IntEntry(p->vOrder, i), Abc_BufEdgeSlack(p, pObj, Abc_NtkObj(p->pNtk, Vec_IntEntry(p->vOrder, i))) );
|
||||
return p->vOrder;
|
||||
|
|
@ -368,6 +538,34 @@ void Abc_BufPrintOne( Buf_Man_t * p, int iPivot )
|
|||
printf( " }\n" );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_BufReplaceBufsByInvs( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Abc_Obj_t * pObj, * pInv;
|
||||
int i, Counter = 0;
|
||||
Abc_NtkForEachNode( pNtk, pObj, i )
|
||||
{
|
||||
if ( !Abc_NodeIsBuf(pObj) )
|
||||
continue;
|
||||
assert( pObj->pData == Mio_LibraryReadBuf((Mio_Library_t *)pNtk->pManFunc) );
|
||||
pObj->pData = Mio_LibraryReadInv((Mio_Library_t *)pNtk->pManFunc);
|
||||
pInv = Abc_NtkCreateNodeInv( pNtk, Abc_ObjFanin0(pObj) );
|
||||
Abc_ObjPatchFanin( pObj, Abc_ObjFanin0(pObj), pInv );
|
||||
Counter++;
|
||||
}
|
||||
printf( "Replaced %d buffers by invertor pairs.\n", Counter );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
|
@ -388,17 +586,6 @@ int Abc_BufComputeAverage( Buf_Man_t * p, int iPivot, Vec_Int_t * vOrder )
|
|||
Average += Abc_BufEdgeSlack( p, pObj, pFanout );
|
||||
return Average / Vec_IntSize(vOrder);
|
||||
}
|
||||
int Abc_BufCountNonCritical_( Buf_Man_t * p, int iPivot, Vec_Int_t * vOrder )
|
||||
{
|
||||
Abc_Obj_t * pObj, * pFanout;
|
||||
int i;
|
||||
Vec_IntClear( p->vNonCrit );
|
||||
pObj = Abc_NtkObj( p->pNtk, iPivot );
|
||||
Abc_NtkForEachObjVec( vOrder, p->pNtk, pFanout, i )
|
||||
if ( Abc_BufEdgeSlack( p, pObj, pFanout ) > 5*BUF_SCALE/2 )
|
||||
Vec_IntPush( p->vNonCrit, Abc_ObjId(pFanout) );
|
||||
return Vec_IntSize(p->vNonCrit);
|
||||
}
|
||||
Abc_Obj_t * Abc_BufFindNonBuffDriver( Buf_Man_t * p, Abc_Obj_t * pObj )
|
||||
{
|
||||
return (Abc_ObjIsNode(pObj) && Abc_NodeIsBuf(pObj)) ? Abc_BufFindNonBuffDriver(p, Abc_ObjFanin0(pObj)) : pObj;
|
||||
|
|
@ -421,35 +608,30 @@ int Abc_BufCountNonCritical( Buf_Man_t * p, Abc_Obj_t * pObj )
|
|||
int i;
|
||||
Vec_IntClear( p->vNonCrit );
|
||||
Abc_ObjForEachFanout( pObj, pFanout, i )
|
||||
if ( Abc_BufEdgeSlack( p, pObj, pFanout ) > 3*BUF_SCALE )
|
||||
if ( Abc_BufEdgeSlack( p, pObj, pFanout ) > 5*BUF_SCALE/2 )
|
||||
Vec_IntPush( p->vNonCrit, Abc_ObjId(pFanout) );
|
||||
return Vec_IntSize(p->vNonCrit);
|
||||
}
|
||||
void Abc_BufPerformOne( Buf_Man_t * p, int iPivot, int fVerbose )
|
||||
{
|
||||
Abc_Obj_t * pObj, * pFanout;
|
||||
Vec_Int_t * vOrder;
|
||||
int Fastest, Slowest, Average;
|
||||
int i, j, nCrit, nNonCrit;
|
||||
int DelayMax = p->DelayMax;
|
||||
assert( Abc_NtkObjNumMax(p->pNtk) + 30 < p->nObjAlloc );
|
||||
pObj = Abc_NtkObj( p->pNtk, iPivot );
|
||||
// assert( Vec_FltEntry(p->vCounts, iPivot) == (float)Abc_ObjFanoutNum(pObj) );
|
||||
nNonCrit = Abc_BufCountNonCritical( p, pObj );
|
||||
nCrit = Abc_ObjFanoutNum(pObj) - nNonCrit;
|
||||
if ( fVerbose )
|
||||
{
|
||||
vOrder = Abc_BufSortByDelay( p, iPivot );
|
||||
//Abc_BufPrintOne( p, iPivot );
|
||||
Fastest = Abc_BufEdgeSlack( p, pObj, Abc_NtkObj(p->pNtk, Vec_IntEntry(vOrder,0)) );
|
||||
Slowest = Abc_BufEdgeSlack( p, pObj, Abc_NtkObj(p->pNtk, Vec_IntEntryLast(vOrder)) );
|
||||
Average = Abc_BufComputeAverage( p, iPivot, vOrder );
|
||||
printf( "FI =%2d. FO =%4d. ", Abc_ObjFaninNum(pObj), Abc_ObjFanoutNum(pObj) );
|
||||
printf( "Fastest =%5d. Slowest =%5d. Ave =%5d. Crit =%3d. NonCrit =%3d. ", Fastest, Slowest, Average, nCrit, nNonCrit );
|
||||
printf( "ObjId = %6d : %-10s FI = %d. FO =%4d. Crit =%4d. ",
|
||||
Abc_ObjId(pObj), Mio_GateReadName((Mio_Gate_t *)pObj->pData), Abc_ObjFaninNum(pObj), Abc_ObjFanoutNum(pObj), nCrit );
|
||||
}
|
||||
// decide based on these
|
||||
assert( Abc_NtkObjNumMax(p->pNtk) + 30 < p->nObjAlloc );
|
||||
// consider three cases
|
||||
if ( nCrit > 0 && nNonCrit > 1 )
|
||||
{
|
||||
// separate using buffer
|
||||
// (1) both critical and non-critical are present - split them by adding buffer
|
||||
Abc_Obj_t * pBuffer = Abc_NtkCreateNodeBuf( p->pNtk, pObj );
|
||||
Abc_NtkForEachObjVec( p->vNonCrit, p->pNtk, pFanout, i )
|
||||
Abc_ObjPatchFanin( pFanout, pObj, pBuffer );
|
||||
|
|
@ -463,10 +645,9 @@ printf( "Fastest =%5d. Slowest =%5d. Ave =%5d. Crit =%3d. NonCrit =%3d. ", Fas
|
|||
if ( fVerbose )
|
||||
printf( "Adding buffer\n" );
|
||||
}
|
||||
|
||||
else if ( nNonCrit < 2 && Abc_ObjFanoutNum(pObj) > 4 && Abc_ObjFanoutNum(pObj) < 12 && Abc_ObjIsNode(pObj) )
|
||||
else if ( nCrit > 0 && Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > p->nFanMin )//&& Abc_ObjFaninNum(pObj) < 2 )
|
||||
{
|
||||
// duplicate
|
||||
// (2) only critical are present - duplicate
|
||||
Abc_Obj_t * pClone = Abc_NtkDupObj( p->pNtk, pObj, 0 );
|
||||
Abc_ObjForEachFanin( pObj, pFanout, i )
|
||||
Abc_ObjAddFanin( pClone, pFanout );
|
||||
|
|
@ -480,26 +661,24 @@ printf( "Adding buffer\n" );
|
|||
Abc_BufUpdateDep( p, pClone );
|
||||
Abc_BufAddToQue( p, pObj );
|
||||
Abc_BufAddToQue( p, pClone );
|
||||
Abc_ObjForEachFanin( pObj, pFanout, i )
|
||||
Abc_BufAddToQue( p, pFanout );
|
||||
p->nDuplicate++;
|
||||
// add fanins to queue
|
||||
if ( fVerbose )
|
||||
printf( "Duplicating node\n" );
|
||||
}
|
||||
|
||||
else if ( Abc_ObjFanoutNum(pObj) >= 12 )
|
||||
else if ( (nCrit > 0 && Abc_ObjFanoutNum(pObj) > 8) || Abc_ObjFanoutNum(pObj) > p->nFanMax )
|
||||
{
|
||||
// branch (consider buffer)
|
||||
// int nFan = Abc_ObjFanoutNum(pObj);
|
||||
int nFan = 64;
|
||||
double Res = pow(nFan, 0.34);
|
||||
int Temp = (int)pow(Abc_ObjFanoutNum(pObj), 0.34);
|
||||
int nDegree = Abc_MinInt( 4, (int)pow(Abc_ObjFanoutNum(pObj), 0.34) );
|
||||
int n1Degree = Abc_ObjFanoutNum(pObj) / nDegree + 1;
|
||||
int n1Number = Abc_ObjFanoutNum(pObj) % nDegree;
|
||||
int nFirst = n1Degree * n1Number;
|
||||
// Abc_Obj_t * pNonBuff = Abc_BufFindNonBuffDriver( p, pObj );
|
||||
// create inverters
|
||||
// (2) only critical or only non-critical - add buffer/inverter tree
|
||||
int nDegree, n1Degree, n1Number, nFirst;
|
||||
int iFirstBuf = Abc_NtkObjNumMax( p->pNtk );
|
||||
// nDegree = Abc_MinInt( 3, (int)pow(Abc_ObjFanoutNum(pObj), 0.34) );
|
||||
nDegree = Abc_MinInt( 10, (int)pow(Abc_ObjFanoutNum(pObj), 0.5) );
|
||||
n1Degree = Abc_ObjFanoutNum(pObj) / nDegree + 1;
|
||||
n1Number = Abc_ObjFanoutNum(pObj) % nDegree;
|
||||
nFirst = n1Degree * n1Number;
|
||||
p->nBranchCrit += (nCrit > 0);
|
||||
// create inverters
|
||||
Abc_NodeCollectFanouts( pObj, p->vFanouts );
|
||||
if ( Abc_ObjIsNode(pObj) && Abc_NodeIsBuf(pObj) )
|
||||
{
|
||||
|
|
@ -520,16 +699,13 @@ printf( "Adding %d inverters\n", nDegree );
|
|||
if ( fVerbose )
|
||||
printf( "Adding %d buffers\n", nDegree );
|
||||
}
|
||||
// create inverters
|
||||
// connect inverters
|
||||
Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanouts, pFanout, i )
|
||||
{
|
||||
j = (i < nFirst) ? i/n1Degree : n1Number + ((i - nFirst)/(n1Degree - 1));
|
||||
assert( j >= 0 && j < nDegree );
|
||||
Abc_ObjPatchFanin( pFanout, pObj, Abc_NtkObj(p->pNtk, iFirstBuf + j) );
|
||||
}
|
||||
// remove node
|
||||
// if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) == 0 )
|
||||
// Abc_NtkDeleteObj_rec( pObj, 1 );
|
||||
// update timing
|
||||
for ( i = 0; i < nDegree; i++ )
|
||||
Abc_BufCreateEdges( p, Abc_NtkObj(p->pNtk, iFirstBuf + i) );
|
||||
|
|
@ -548,19 +724,18 @@ printf( "Doing nothing\n" );
|
|||
// if ( DelayMax != p->DelayMax )
|
||||
// printf( "%d (%.2f) ", p->DelayMax, 1.0 * p->DelayMax * p->DelayInv / BUF_SCALE );
|
||||
}
|
||||
Abc_Ntk_t * Abc_SclBufPerform( Abc_Ntk_t * pNtk, int fVerbose )
|
||||
Abc_Ntk_t * Abc_SclBufPerform( Abc_Ntk_t * pNtk, int FanMin, int FanMax, int fVerbose )
|
||||
{
|
||||
Abc_Ntk_t * pNew;
|
||||
Buf_Man_t * p = Buf_ManStart( pNtk );
|
||||
Buf_Man_t * p = Buf_ManStart( pNtk, FanMin, FanMax );
|
||||
int i, Limit = ABC_INFINITY;
|
||||
// int i, Limit = 3;
|
||||
for ( i = 0; i < Limit && Vec_QueSize(p->vQue); i++ )
|
||||
Abc_BufPerformOne( p, Vec_QuePop(p->vQue), fVerbose );
|
||||
Buf_ManStop( p );
|
||||
// duplication in topo order
|
||||
// Abc_BufReplaceBufsByInvs( pNtk );
|
||||
// duplicate network in topo order
|
||||
pNew = Abc_NtkDupDfs( pNtk );
|
||||
Abc_SclCheckNtk( pNew, fVerbose );
|
||||
// Abc_NtkDelete( pNew );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -711,14 +711,16 @@ void Abc_SclHashCells( SC_Lib * p )
|
|||
}
|
||||
int Abc_SclCellFind( SC_Lib * p, char * pName )
|
||||
{
|
||||
return *Abc_SclHashLookup( p, pName );
|
||||
int *pPlace = Abc_SclHashLookup( p, pName );
|
||||
return pPlace ? *pPlace : -1;
|
||||
}
|
||||
int Abc_SclClassCellNum( SC_Cell * pClass )
|
||||
{
|
||||
SC_Cell * pCell;
|
||||
int i, Count = 0;
|
||||
SC_RingForEachCell( pClass, pCell, i )
|
||||
Count++;
|
||||
if ( !pCell->fSkip )
|
||||
Count++;
|
||||
return Count;
|
||||
}
|
||||
|
||||
|
|
@ -954,15 +956,16 @@ float Abc_SclComputeDelayClassPin( SC_Lib * p, SC_Cell * pRepr, int iPin, float
|
|||
SC_Cell * pCell;
|
||||
float Delay = 0;
|
||||
int i, Count = 0;
|
||||
SC_RingForEachCell( pRepr, pCell, i )
|
||||
Count++;
|
||||
SC_RingForEachCell( pRepr, pCell, i )
|
||||
{
|
||||
if ( pRepr == pCell && Count > 1 ) // skip the first gate
|
||||
if ( pCell->fSkip )
|
||||
continue;
|
||||
// if ( pRepr == pCell ) // skip the first gate
|
||||
// continue;
|
||||
Delay += Abc_SclComputeDelayCellPin( p, pCell, iPin, Slew, Gain );
|
||||
Count++;
|
||||
}
|
||||
return Delay / Abc_MaxInt(1, Count-1);
|
||||
return Delay / Abc_MaxInt(1, Count);
|
||||
}
|
||||
float Abc_SclComputeAreaClass( SC_Cell * pRepr )
|
||||
{
|
||||
|
|
@ -971,6 +974,8 @@ float Abc_SclComputeAreaClass( SC_Cell * pRepr )
|
|||
int i, Count = 0;
|
||||
SC_RingForEachCell( pRepr, pCell, i )
|
||||
{
|
||||
if ( pCell->fSkip )
|
||||
continue;
|
||||
Area += pCell->area;
|
||||
Count++;
|
||||
}
|
||||
|
|
@ -988,6 +993,35 @@ float Abc_SclComputeAreaClass( SC_Cell * pRepr )
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_SclMarkSkippedCells( SC_Lib * p )
|
||||
{
|
||||
char FileName[1000];
|
||||
char Buffer[1000], * pName;
|
||||
SC_Cell * pCell;
|
||||
FILE * pFile;
|
||||
int CellId, nSkipped = 0;
|
||||
sprintf( FileName, "%s.skip", p->pName );
|
||||
pFile = fopen( FileName, "rb" );
|
||||
if ( pFile == NULL )
|
||||
return;
|
||||
while ( fgets( Buffer, 999, pFile ) != NULL )
|
||||
{
|
||||
pName = strtok( Buffer, "\r\n\t " );
|
||||
if ( pName == NULL )
|
||||
continue;
|
||||
CellId = Abc_SclCellFind( p, pName );
|
||||
if ( CellId == -1 )
|
||||
{
|
||||
printf( "Cannot find cell \"%s\" in the library \"%s\".\n", pName, p->pName );
|
||||
continue;
|
||||
}
|
||||
pCell = SC_LibCell( p, CellId );
|
||||
pCell->fSkip = 1;
|
||||
nSkipped++;
|
||||
}
|
||||
fclose( pFile );
|
||||
printf( "Marked %d cells for skipping in the library \"%s\".\n", nSkipped, p->pName );
|
||||
}
|
||||
void Abc_SclPrintCells( SC_Lib * p, float Slew, float Gain )
|
||||
{
|
||||
SC_Cell * pCell, * pRepr;
|
||||
|
|
@ -998,6 +1032,7 @@ void Abc_SclPrintCells( SC_Lib * p, float Slew, float Gain )
|
|||
printf( "has %d cells in %d classes. ",
|
||||
Vec_PtrSize(p->vCells), Vec_PtrSize(p->vCellClasses) );
|
||||
printf( "Delay estimate is based on slew %.2f and gain %.2f.\n", Slew, Gain );
|
||||
Abc_SclMarkSkippedCells( p );
|
||||
// find the longest name
|
||||
SC_LibForEachCellClass( p, pRepr, k )
|
||||
SC_RingForEachCell( pRepr, pCell, i )
|
||||
|
|
@ -1017,7 +1052,9 @@ void Abc_SclPrintCells( SC_Lib * p, float Slew, float Gain )
|
|||
SC_RingForEachCell( pRepr, pCell, i )
|
||||
{
|
||||
Abc_SclComputeParametersCell( p, pCell, Slew, &ED, &PD );
|
||||
printf( " %3d : ", i+1 );
|
||||
printf( " %3d ", i+1 );
|
||||
printf( "%s", pCell->fSkip ? "s" : " " );
|
||||
printf( " : " );
|
||||
printf( "%-*s ", nLength, pCell->pName );
|
||||
printf( "%2d ", pCell->drive_strength );
|
||||
printf( "A =%8.2f ", pCell->area );
|
||||
|
|
@ -1027,7 +1064,7 @@ void Abc_SclPrintCells( SC_Lib * p, float Slew, float Gain )
|
|||
printf( "C =%5.1f ff ", Abc_SclGatePinCapAve(p, pCell) );
|
||||
printf( "Lm =%5.1f ff ", 0.01 * Gain * Abc_SclGatePinCapAve(p, pCell) );
|
||||
// printf( "MaxS =%5.1f ps ", SC_CellPin(pCell, pCell->n_inputs)->max_out_slew );
|
||||
printf( "Lm2 =%5.0f ff", SC_CellPin(pCell, pCell->n_inputs)->max_out_cap );
|
||||
printf( "Lm2 =%5.0f ff ", SC_CellPin(pCell, pCell->n_inputs)->max_out_cap );
|
||||
printf( "\n" );
|
||||
}
|
||||
}
|
||||
|
|
@ -1052,6 +1089,7 @@ Vec_Str_t * Abc_SclDeriveGenlibStr( SC_Lib * p, float Slew, float Gain, int nGat
|
|||
SC_Cell * pRepr;
|
||||
SC_Pin * pPin;
|
||||
int i, k, Count = 2;
|
||||
Abc_SclMarkSkippedCells( p );
|
||||
vStr = Vec_StrAlloc( 1000 );
|
||||
Vec_StrPrintStr( vStr, "GATE _const0_ 0.00 z=CONST0;\n" );
|
||||
Vec_StrPrintStr( vStr, "GATE _const1_ 0.00 z=CONST1;\n" );
|
||||
|
|
@ -1078,6 +1116,7 @@ Vec_Str_t * Abc_SclDeriveGenlibStr( SC_Lib * p, float Slew, float Gain, int nGat
|
|||
SC_CellForEachPinIn( pRepr, pPin, k )
|
||||
{
|
||||
float Delay = Abc_SclComputeDelayClassPin( p, pRepr, k, Slew, Gain );
|
||||
assert( Delay > 0 );
|
||||
Vec_StrPrintStr( vStr, " PIN " );
|
||||
sprintf( Buffer, "%-4s", pPin->pName );
|
||||
Vec_StrPrintStr( vStr, Buffer );
|
||||
|
|
|
|||
|
|
@ -166,6 +166,7 @@ struct SC_Cell_
|
|||
{
|
||||
char * pName;
|
||||
int Id;
|
||||
int fSkip; // skip this cell during genlib computation
|
||||
int seq; // -- set to TRUE by parser if a sequential element
|
||||
int unsupp; // -- set to TRUE by parser if cell contains information we cannot handle
|
||||
float area;
|
||||
|
|
|
|||
|
|
@ -358,25 +358,37 @@ static inline SC_Cell * Abc_SclObjResiable( SC_Man * p, Abc_Obj_t * pObj, int fU
|
|||
***********************************************************************/
|
||||
static inline void Abc_SclDumpStats( SC_Man * p, char * pFileName, abctime Time )
|
||||
{
|
||||
static char FileNameOld[1000] = {0};
|
||||
static int nNodesOld, nAreaOld, nDelayOld;
|
||||
FILE * pTable;
|
||||
pTable = fopen( pFileName, "a+" );
|
||||
fprintf( pTable, "%s ", p->pNtk->pName );
|
||||
fprintf( pTable, "%d ", Abc_NtkPiNum(p->pNtk) );
|
||||
fprintf( pTable, "%d ", Abc_NtkPoNum(p->pNtk) );
|
||||
fprintf( pTable, "%d ", Abc_NtkNodeNum(p->pNtk) );
|
||||
fprintf( pTable, "%d ", (int)p->SumArea );
|
||||
fprintf( pTable, "%d ", (int)p->ReportDelay );
|
||||
// fprintf( pTable, "%.2f ", 1.0*Time/CLOCKS_PER_SEC );
|
||||
fprintf( pTable, "\n" );
|
||||
if ( strcmp( FileNameOld, p->pNtk->pName ) )
|
||||
{
|
||||
sprintf( FileNameOld, "%s", p->pNtk->pName );
|
||||
fprintf( pTable, "\n" );
|
||||
fprintf( pTable, "%s ", p->pNtk->pName );
|
||||
fprintf( pTable, "%d ", Abc_NtkPiNum(p->pNtk) );
|
||||
fprintf( pTable, "%d ", Abc_NtkPoNum(p->pNtk) );
|
||||
fprintf( pTable, "%d ", (nNodesOld = Abc_NtkNodeNum(p->pNtk)) );
|
||||
fprintf( pTable, "%d ", (nAreaOld = (int)p->SumArea) );
|
||||
fprintf( pTable, "%d ", (nDelayOld = (int)p->ReportDelay) );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( pTable, " " );
|
||||
fprintf( pTable, "%.1f ", 100.0 * Abc_NtkNodeNum(p->pNtk) / nNodesOld );
|
||||
fprintf( pTable, "%.1f ", 100.0 * (int)p->SumArea / nAreaOld );
|
||||
fprintf( pTable, "%.1f ", 100.0 * (int)p->ReportDelay / nDelayOld );
|
||||
}
|
||||
// fprintf( pTable, "%.2f ", 1.0*Time/CLOCKS_PER_SEC );
|
||||
fclose( pTable );
|
||||
}
|
||||
|
||||
|
||||
/*=== sclBuff.c ===============================================================*/
|
||||
/*=== sclBuffer.c ===============================================================*/
|
||||
extern int Abc_SclCheckNtk( Abc_Ntk_t * p, int fVerbose );
|
||||
extern Abc_Ntk_t * Abc_SclPerformBuffering( Abc_Ntk_t * p, int Degree, int fUseInvs, int fVerbose );
|
||||
/*=== sclBuffer.c ===============================================================*/
|
||||
extern Abc_Ntk_t * Abc_SclBufPerform( Abc_Ntk_t * pNtk, int fVerbose );
|
||||
extern Abc_Ntk_t * Abc_SclBufPerform( Abc_Ntk_t * pNtk, int FanMin, int FanMax, int fVerbose );
|
||||
/*=== sclDnsize.c ===============================================================*/
|
||||
extern void Abc_SclDnsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars );
|
||||
/*=== sclLoad.c ===============================================================*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue