Commit 1dca7458 by Alan Mishchenko

Improved buffering.

parent 4c6804c3
......@@ -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 )
......
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" );
......
/**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
......@@ -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;
}
......@@ -955,14 +957,15 @@ float Abc_SclComputeDelayClassPin( SC_Lib * p, SC_Cell * pRepr, int iPin, float
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 ===============================================================*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment