Commit dd25b90f by Alan Mishchenko

Improvements to gate sizing.

parent a5d07fa4
...@@ -67,6 +67,12 @@ struct SC_Man_ ...@@ -67,6 +67,12 @@ struct SC_Man_
Vec_Flt_t * vTimesOut; // output arrival times Vec_Flt_t * vTimesOut; // output arrival times
Vec_Que_t * vQue; // outputs by their time Vec_Que_t * vQue; // outputs by their time
SC_WireLoad * pWLoadUsed; // name of the used WireLoad model SC_WireLoad * pWLoadUsed; // name of the used WireLoad model
// intermediate data
Vec_Que_t * vNodeByGain; // nodes by gain
Vec_Flt_t * vNode2Gain; // mapping node into its gain
Vec_Int_t * vNode2Gate; // mapping node into its best gate
Vec_Int_t * vNodeIter; // the last iteration the node was upsized
// optimization parameters
float SumArea; // total area float SumArea; // total area
float MaxDelay; // max delay float MaxDelay; // max delay
float SumArea0; // total area at the begining float SumArea0; // total area at the begining
...@@ -147,10 +153,21 @@ static inline SC_Man * Abc_SclManAlloc( SC_Lib * pLib, Abc_Ntk_t * pNtk ) ...@@ -147,10 +153,21 @@ static inline SC_Man * Abc_SclManAlloc( SC_Lib * pLib, Abc_Ntk_t * pNtk )
for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ ) for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ )
Vec_QuePush( p->vQue, i ); Vec_QuePush( p->vQue, i );
p->vUpdates = Vec_IntAlloc( 1000 ); p->vUpdates = Vec_IntAlloc( 1000 );
// intermediate data
p->vNode2Gain = Vec_FltStart( p->nObjs );
p->vNode2Gate = Vec_IntStart( p->nObjs );
p->vNodeByGain = Vec_QueAlloc( p->nObjs );
Vec_QueSetCosts( p->vNodeByGain, Vec_FltArray(p->vNode2Gain) );
p->vNodeIter = Vec_IntStartFull( p->nObjs );
return p; return p;
} }
static inline void Abc_SclManFree( SC_Man * p ) static inline void Abc_SclManFree( SC_Man * p )
{ {
Vec_IntFreeP( &p->vNodeIter );
Vec_QueFreeP( &p->vNodeByGain );
Vec_FltFreeP( &p->vNode2Gain );
Vec_IntFreeP( &p->vNode2Gate );
// intermediate data
Vec_IntFreeP( &p->vUpdates ); Vec_IntFreeP( &p->vUpdates );
Vec_IntFreeP( &p->vGatesBest ); Vec_IntFreeP( &p->vGatesBest );
// Vec_QuePrint( p->vQue ); // Vec_QuePrint( p->vQue );
......
...@@ -218,6 +218,7 @@ Vec_Int_t * Abc_SclFindNodesToUpdate( Abc_Obj_t * pPivot, Vec_Int_t ** pvEvals ) ...@@ -218,6 +218,7 @@ Vec_Int_t * Abc_SclFindNodesToUpdate( Abc_Obj_t * pPivot, Vec_Int_t ** pvEvals )
Abc_NtkForEachObjVec( vNodes, p, pObj, i ) Abc_NtkForEachObjVec( vNodes, p, pObj, i )
Abc_ObjForEachFanout( pObj, pNext, k ) Abc_ObjForEachFanout( pObj, pNext, k )
if ( pNext->fMarkA && !pNext->fMarkB ) if ( pNext->fMarkA && !pNext->fMarkB )
// if ( !pNext->fMarkB )
{ {
assert( pObj->fMarkB ); assert( pObj->fMarkB );
Vec_IntPush( *pvEvals, Abc_ObjId(pObj) ); Vec_IntPush( *pvEvals, Abc_ObjId(pObj) );
...@@ -242,39 +243,38 @@ Vec_Int_t * Abc_SclFindNodesToUpdate( Abc_Obj_t * pPivot, Vec_Int_t ** pvEvals ) ...@@ -242,39 +243,38 @@ Vec_Int_t * Abc_SclFindNodesToUpdate( Abc_Obj_t * pPivot, Vec_Int_t ** pvEvals )
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
int Abc_SclFindUpsizes( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notches ) int Abc_SclFindUpsizes( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notches, int iIter )
{ {
SC_Cell * pCellOld, * pCellNew; SC_Cell * pCellOld, * pCellNew;
Vec_Int_t * vChamps; // best gate for each node Vec_Int_t * vRecalcs, * vEvals;
Vec_Flt_t * vSavings; // best gain for each node
Vec_Int_t * vRecalcs, * vEvals, * vUpdate;
Abc_Obj_t * pObj, * pTemp; Abc_Obj_t * pObj, * pTemp;
float dGain, dGainBest; float dGain, dGainBest;
int i, k, n, Entry, gateBest; int i, k, n, gateBest, Limit, iIterLast;
int nUpsizes = 0;
// return nUpsizes;
// compute savings due to upsizing each node // compute savings due to upsizing each node
vChamps = Vec_IntAlloc( Vec_IntSize(vPathNodes) ); Vec_QueClear( p->vNodeByGain );
vSavings = Vec_FltAlloc( Vec_IntSize(vPathNodes) );
Abc_NtkForEachObjVec( vPathNodes, p->pNtk, pObj, i ) Abc_NtkForEachObjVec( vPathNodes, p->pNtk, pObj, i )
{ {
iIterLast = Vec_IntEntry(p->vNodeIter, Abc_ObjId(pObj));
if ( iIterLast >= 0 && iIterLast + 10 > iIter )
continue;
// compute nodes to recalculate timing and nodes to evaluate afterwards // compute nodes to recalculate timing and nodes to evaluate afterwards
vRecalcs = Abc_SclFindNodesToUpdate( pObj, &vEvals ); vRecalcs = Abc_SclFindNodesToUpdate( pObj, &vEvals );
assert( Vec_IntSize(vEvals) > 0 );
//printf( "%d -> %d\n", Vec_IntSize(vRecalcs), Vec_IntSize(vEvals) );
// save old gate, timing, fanin load // save old gate, timing, fanin load
pCellOld = Abc_SclObjCell( p, pObj ); pCellOld = Abc_SclObjCell( p, pObj );
Abc_SclConeStore( p, vRecalcs ); Abc_SclConeStore( p, vRecalcs );
Abc_SclLoadStore( p, pObj ); Abc_SclLoadStore( p, pObj );
// try different gate sizes for this node // try different gate sizes for this node
dGainBest = 0.0;
gateBest = -1; gateBest = -1;
dGainBest = 0.0;
SC_RingForEachCell( pCellOld, pCellNew, k ) SC_RingForEachCell( pCellOld, pCellNew, k )
{ {
if ( pCellNew == pCellOld ) if ( pCellNew == pCellOld )
continue; continue;
if ( k > Notches ) if ( k > Notches )
break; break;
//printf( "Tring %s\n", pCellNew->pName );
// set new cell // set new cell
Abc_SclObjSetCell( p, pObj, pCellNew ); Abc_SclObjSetCell( p, pObj, pCellNew );
Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew ); Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew );
...@@ -288,21 +288,21 @@ int Abc_SclFindUpsizes( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notch ...@@ -288,21 +288,21 @@ int Abc_SclFindUpsizes( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notch
Abc_NtkForEachObjVec( vEvals, p->pNtk, pTemp, n ) Abc_NtkForEachObjVec( vEvals, p->pNtk, pTemp, n )
dGain += Abc_SclObjGain( p, pTemp ); dGain += Abc_SclObjGain( p, pTemp );
dGain /= Vec_IntSize(vEvals); dGain /= Vec_IntSize(vEvals);
if ( dGain <= 0.0 ) // save best gain
continue;
// put back timing and load
//printf( "gain is %f\n", dGain );
if ( dGainBest < dGain ) if ( dGainBest < dGain )
{ {
dGainBest = dGain; dGainBest = dGain;
gateBest = pCellNew->Id; gateBest = pCellNew->Id;
} }
} }
//printf( "gain is %f\n", dGainBest );
// remember savings // remember savings
assert( dGainBest >= 0.0 ); if ( gateBest >= 0 )
Vec_IntPush( vChamps, gateBest ); {
Vec_FltPush( vSavings, dGainBest ); assert( dGainBest > 0.0 );
Vec_FltWriteEntry( p->vNode2Gain, Abc_ObjId(pObj), dGainBest );
Vec_IntWriteEntry( p->vNode2Gate, Abc_ObjId(pObj), gateBest );
Vec_QuePush( p->vNodeByGain, Abc_ObjId(pObj) );
}
// put back old cell and timing // put back old cell and timing
Abc_SclObjSetCell( p, pObj, pCellOld ); Abc_SclObjSetCell( p, pObj, pCellOld );
Abc_SclConeRestore( p, vRecalcs ); Abc_SclConeRestore( p, vRecalcs );
...@@ -310,47 +310,22 @@ int Abc_SclFindUpsizes( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notch ...@@ -310,47 +310,22 @@ int Abc_SclFindUpsizes( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notch
Vec_IntFree( vRecalcs ); Vec_IntFree( vRecalcs );
Vec_IntFree( vEvals ); Vec_IntFree( vEvals );
} }
assert( Vec_IntSize(vChamps) == Vec_IntSize(vPathNodes) ); if ( Vec_QueSize(p->vNodeByGain) < 3 )
return 0;
// we have computed the gains - find the best ones Limit = Abc_MinInt( Vec_QueSize(p->vNodeByGain), (int)(0.01 * Ratio * Vec_IntSize(vPathNodes)) + 1 );
{ //printf( "\nSelecting %d out of %d\n", Limit, Vec_QueSize(p->vNodeByGain) );
Vec_Int_t * vCosts;
float Max = Vec_FltFindMax( vSavings );
float Factor = 1.0 * (1<<28) / Max, This;
int i, Limit, * pPerm;
// find a good factor
vCosts = Vec_IntAlloc( Vec_FltSize(vSavings) );
Vec_FltForEachEntry( vSavings, This, i )
{
Vec_IntPush( vCosts, (int)(This * Factor) );
assert( (int)(This * Factor) < (1<<30) );
}
pPerm = Abc_QuickSortCost( Vec_IntArray(vCosts), Vec_IntSize(vCosts), 1 );
assert( Vec_FltEntry(vSavings, pPerm[0]) >= Vec_FltEntry(vSavings, pPerm[Vec_FltSize(vSavings)-1]) );
// find those that are good to update
Limit = Abc_MaxInt( 1, (int)(0.01 * Ratio * Vec_IntSize(vChamps)) );
vUpdate = Vec_IntAlloc( Limit );
for ( i = 0; i < Limit; i++ ) for ( i = 0; i < Limit; i++ )
if ( Vec_FltEntry(vSavings, pPerm[i]) > 0 )
{
assert( Vec_IntEntry(vChamps, pPerm[i]) >= 0 );
Vec_IntPush( vUpdate, pPerm[i] );
}
Vec_IntFree( vCosts );
ABC_FREE( pPerm );
}
// update the network
Vec_IntForEachEntry( vUpdate, Entry, i )
{ {
// get the object // get the object
pObj = Abc_NtkObj( p->pNtk, Vec_IntEntry(vPathNodes, Entry) ); pObj = Abc_NtkObj( p->pNtk, Vec_QuePop(p->vNodeByGain) );
assert( pObj->fMarkA ); assert( pObj->fMarkA );
// find old and new gates // find old and new gates
pCellOld = Abc_SclObjCell( p, pObj ); pCellOld = Abc_SclObjCell( p, pObj );
pCellNew = SC_LibCell( p->pLib, Vec_IntEntry(vChamps, Entry) ); pCellNew = SC_LibCell( p->pLib, Vec_IntEntry(p->vNode2Gate, Abc_ObjId(pObj)) );
assert( pCellNew != NULL ); assert( pCellNew != NULL );
// printf( "%6d %s -> %s \n", Abc_ObjId(pObj), pCellOld->pName, pCellNew->pName ); // printf( "%6d %20s -> %20s ", Abc_ObjId(pObj), pCellOld->pName, pCellNew->pName );
// printf( "gain is %f\n", Vec_FltEntry(p->vNode2Gain, Abc_ObjId(pObj)) );
// update gate // update gate
Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew ); Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew );
p->SumArea += pCellNew->area - pCellOld->area; p->SumArea += pCellNew->area - pCellOld->area;
...@@ -358,14 +333,10 @@ int Abc_SclFindUpsizes( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notch ...@@ -358,14 +333,10 @@ int Abc_SclFindUpsizes( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notch
// record the update // record the update
Vec_IntPush( p->vUpdates, Abc_ObjId(pObj) ); Vec_IntPush( p->vUpdates, Abc_ObjId(pObj) );
Vec_IntPush( p->vUpdates, pCellNew->Id ); Vec_IntPush( p->vUpdates, pCellNew->Id );
// remember when this node was upsized
Vec_IntWriteEntry( p->vNodeIter, Abc_ObjId(pObj), iIter );
} }
return Limit;
// cleanup
nUpsizes = Vec_IntSize(vUpdate);
Vec_IntFree( vUpdate );
Vec_IntFree( vChamps );
Vec_FltFree( vSavings );
return nUpsizes;
} }
void Abc_SclApplyUpdateToBest( Vec_Int_t * vGates, Vec_Int_t * vGatesBest, Vec_Int_t * vUpdate ) void Abc_SclApplyUpdateToBest( Vec_Int_t * vGates, Vec_Int_t * vGatesBest, Vec_Int_t * vUpdate )
{ {
...@@ -375,7 +346,6 @@ void Abc_SclApplyUpdateToBest( Vec_Int_t * vGates, Vec_Int_t * vGatesBest, Vec_I ...@@ -375,7 +346,6 @@ void Abc_SclApplyUpdateToBest( Vec_Int_t * vGates, Vec_Int_t * vGatesBest, Vec_I
Vec_IntClear( vUpdate ); Vec_IntClear( vUpdate );
Vec_IntForEachEntryTwo( vGates, vGatesBest, GateId, GateId2, i ) Vec_IntForEachEntryTwo( vGates, vGatesBest, GateId, GateId2, i )
assert( GateId == GateId2 ); assert( GateId == GateId2 );
//printf( "Updating gates.\n" );
} }
...@@ -449,9 +419,10 @@ if ( memcmp( pLoads, p->pLoads, sizeof(SC_Pair) * p->nObjs ) ) ...@@ -449,9 +419,10 @@ if ( memcmp( pLoads, p->pLoads, sizeof(SC_Pair) * p->nObjs ) )
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
void Abc_SclUpsizePrint( SC_Man * p, int Iter, int nPathPos, int nPathNodes, int nUpsizes, int nTFOs, int fVerbose ) void Abc_SclUpsizePrint( SC_Man * p, int Iter, int win, int nPathPos, int nPathNodes, int nUpsizes, int nTFOs, int fVerbose )
{ {
printf( "%4d ", Iter ); printf( "%4d ", Iter );
printf( "Win:%3d. ", win );
printf( "PO:%5d. ", nPathPos ); printf( "PO:%5d. ", nPathPos );
printf( "Path:%6d. ", nPathNodes ); printf( "Path:%6d. ", nPathNodes );
printf( "Gate:%5d. ", nUpsizes ); printf( "Gate:%5d. ", nUpsizes );
...@@ -488,7 +459,7 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nIters, int Wind ...@@ -488,7 +459,7 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nIters, int Wind
Vec_Int_t * vPathPos; // critical POs Vec_Int_t * vPathPos; // critical POs
Vec_Int_t * vPathNodes; // critical nodes and PIs Vec_Int_t * vPathNodes; // critical nodes and PIs
Vec_Int_t * vTFO; Vec_Int_t * vTFO;
int i, nUpsizes = -1; int i, win, nUpsizes = -1;
int nAllPos, nAllNodes, nAllTfos, nAllUpsizes; int nAllPos, nAllNodes, nAllTfos, nAllUpsizes;
clock_t clk; clock_t clk;
...@@ -512,17 +483,19 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nIters, int Wind ...@@ -512,17 +483,19 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nIters, int Wind
// perform upsizing // perform upsizing
nAllPos = nAllNodes = nAllTfos = nAllUpsizes = 0; nAllPos = nAllNodes = nAllTfos = nAllUpsizes = 0;
for ( i = 0; nUpsizes && i < nIters; i++ ) for ( i = 0; i < nIters; i++ )
{
for ( win = Window; win <= 100; win *= 2 )
{ {
// detect critical path // detect critical path
clk = clock(); clk = clock();
vPathPos = Abc_SclFindCriticalCoWindow( p, Window ); vPathPos = Abc_SclFindCriticalCoWindow( p, win );
vPathNodes = Abc_SclFindCriticalNodeWindow( p, vPathPos, Window ); vPathNodes = Abc_SclFindCriticalNodeWindow( p, vPathPos, win );
p->timeCone += clock() - clk; p->timeCone += clock() - clk;
// selectively upsize the nodes // selectively upsize the nodes
clk = clock(); clk = clock();
nUpsizes = Abc_SclFindUpsizes( p, vPathNodes, Ratio, Notches ); nUpsizes = Abc_SclFindUpsizes( p, vPathNodes, Ratio, Notches, i );
p->timeSize += clock() - clk; p->timeSize += clock() - clk;
// unmark critical path // unmark critical path
...@@ -530,6 +503,13 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nIters, int Wind ...@@ -530,6 +503,13 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nIters, int Wind
Abc_SclUnmarkCriticalNodeWindow( p, vPathNodes ); Abc_SclUnmarkCriticalNodeWindow( p, vPathNodes );
Abc_SclUnmarkCriticalNodeWindow( p, vPathPos ); Abc_SclUnmarkCriticalNodeWindow( p, vPathPos );
p->timeCone += clock() - clk; p->timeCone += clock() - clk;
if ( nUpsizes > 0 )
break;
Vec_IntFree( vPathPos );
Vec_IntFree( vPathNodes );
}
if ( nUpsizes == 0 )
break;
// update timing information // update timing information
clk = clock(); clk = clock();
...@@ -547,7 +527,7 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nIters, int Wind ...@@ -547,7 +527,7 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nIters, int Wind
} }
// report and cleanup // report and cleanup
Abc_SclUpsizePrint( p, i, Vec_IntSize(vPathPos), Vec_IntSize(vPathNodes), nUpsizes, Vec_IntSize(vTFO), fVeryVerbose ); //|| (i == nIters-1) ); Abc_SclUpsizePrint( p, i, win, Vec_IntSize(vPathPos), Vec_IntSize(vPathNodes), nUpsizes, Vec_IntSize(vTFO), fVeryVerbose ); //|| (i == nIters-1) );
nAllPos += Vec_IntSize(vPathPos); nAllPos += Vec_IntSize(vPathPos);
nAllNodes += Vec_IntSize(vPathNodes); nAllNodes += Vec_IntSize(vPathNodes);
nAllTfos += Vec_IntSize(vTFO); nAllTfos += Vec_IntSize(vTFO);
...@@ -561,7 +541,7 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nIters, int Wind ...@@ -561,7 +541,7 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nIters, int Wind
if ( fVerbose ) if ( fVerbose )
{ {
Abc_SclTimeNtkRecompute( p, &p->SumArea, &p->MaxDelay, 0 ); Abc_SclTimeNtkRecompute( p, &p->SumArea, &p->MaxDelay, 0 );
Abc_SclUpsizePrint( p, i, nAllPos/i, nAllNodes/i, nAllUpsizes/i, nAllTfos/i, 1 ); Abc_SclUpsizePrint( p, i, Window, nAllPos/i, nAllNodes/i, nAllUpsizes/i, nAllTfos/i, 1 );
// report runtime // report runtime
p->timeTotal = clock() - p->timeTotal; p->timeTotal = clock() - p->timeTotal;
p->timeOther = p->timeTotal - p->timeCone - p->timeSize - p->timeTime; p->timeOther = p->timeTotal - p->timeCone - p->timeSize - p->timeTime;
......
...@@ -226,7 +226,10 @@ static inline int Vec_QuePop( Vec_Que_t * p ) ...@@ -226,7 +226,10 @@ static inline int Vec_QuePop( Vec_Que_t * p )
assert( p->nSize > 1 ); assert( p->nSize > 1 );
Res = p->pHeap[1]; p->pOrder[Res] = -1; Res = p->pHeap[1]; p->pOrder[Res] = -1;
if ( --p->nSize == 1 ) if ( --p->nSize == 1 )
{
p->pHeap[1] = -1;
return Res; return Res;
}
v = p->pHeap[p->nSize]; p->pHeap[p->nSize] = -1; v = p->pHeap[p->nSize]; p->pHeap[p->nSize] = -1;
p->pHeap[1] = v; p->pOrder[v] = 1; p->pHeap[1] = v; p->pOrder[v] = 1;
Vec_QueMoveDown( p, v ); Vec_QueMoveDown( p, v );
......
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