Commit dd25b90f by Alan Mishchenko

Improvements to gate sizing.

parent a5d07fa4
......@@ -67,6 +67,12 @@ struct SC_Man_
Vec_Flt_t * vTimesOut; // output arrival times
Vec_Que_t * vQue; // outputs by their time
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 MaxDelay; // max delay
float SumArea0; // total area at the begining
......@@ -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++ )
Vec_QuePush( p->vQue, i );
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;
}
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->vGatesBest );
// Vec_QuePrint( p->vQue );
......
......@@ -218,6 +218,7 @@ Vec_Int_t * Abc_SclFindNodesToUpdate( Abc_Obj_t * pPivot, Vec_Int_t ** pvEvals )
Abc_NtkForEachObjVec( vNodes, p, pObj, i )
Abc_ObjForEachFanout( pObj, pNext, k )
if ( pNext->fMarkA && !pNext->fMarkB )
// if ( !pNext->fMarkB )
{
assert( pObj->fMarkB );
Vec_IntPush( *pvEvals, Abc_ObjId(pObj) );
......@@ -242,39 +243,38 @@ Vec_Int_t * Abc_SclFindNodesToUpdate( Abc_Obj_t * pPivot, Vec_Int_t ** pvEvals )
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;
Vec_Int_t * vChamps; // best gate for each node
Vec_Flt_t * vSavings; // best gain for each node
Vec_Int_t * vRecalcs, * vEvals, * vUpdate;
Vec_Int_t * vRecalcs, * vEvals;
Abc_Obj_t * pObj, * pTemp;
float dGain, dGainBest;
int i, k, n, Entry, gateBest;
int nUpsizes = 0;
// return nUpsizes;
int i, k, n, gateBest, Limit, iIterLast;
// compute savings due to upsizing each node
vChamps = Vec_IntAlloc( Vec_IntSize(vPathNodes) );
vSavings = Vec_FltAlloc( Vec_IntSize(vPathNodes) );
Vec_QueClear( p->vNodeByGain );
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
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
pCellOld = Abc_SclObjCell( p, pObj );
Abc_SclConeStore( p, vRecalcs );
Abc_SclLoadStore( p, pObj );
// try different gate sizes for this node
dGainBest = 0.0;
gateBest = -1;
dGainBest = 0.0;
SC_RingForEachCell( pCellOld, pCellNew, k )
{
if ( pCellNew == pCellOld )
continue;
if ( k > Notches )
break;
//printf( "Tring %s\n", pCellNew->pName );
// set new cell
Abc_SclObjSetCell( p, pObj, 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
Abc_NtkForEachObjVec( vEvals, p->pNtk, pTemp, n )
dGain += Abc_SclObjGain( p, pTemp );
dGain /= Vec_IntSize(vEvals);
if ( dGain <= 0.0 )
continue;
// put back timing and load
//printf( "gain is %f\n", dGain );
// save best gain
if ( dGainBest < dGain )
{
dGainBest = dGain;
gateBest = pCellNew->Id;
}
}
//printf( "gain is %f\n", dGainBest );
// remember savings
assert( dGainBest >= 0.0 );
Vec_IntPush( vChamps, gateBest );
Vec_FltPush( vSavings, dGainBest );
if ( gateBest >= 0 )
{
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
Abc_SclObjSetCell( p, pObj, pCellOld );
Abc_SclConeRestore( p, vRecalcs );
......@@ -310,47 +310,22 @@ int Abc_SclFindUpsizes( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notch
Vec_IntFree( vRecalcs );
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
{
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++ )
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 )
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) );
for ( i = 0; i < Limit; i++ )
{
// get the object
pObj = Abc_NtkObj( p->pNtk, Vec_IntEntry(vPathNodes, Entry) );
pObj = Abc_NtkObj( p->pNtk, Vec_QuePop(p->vNodeByGain) );
assert( pObj->fMarkA );
// find old and new gates
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 );
// 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
Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew );
p->SumArea += pCellNew->area - pCellOld->area;
......@@ -358,14 +333,10 @@ int Abc_SclFindUpsizes( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notch
// record the update
Vec_IntPush( p->vUpdates, Abc_ObjId(pObj) );
Vec_IntPush( p->vUpdates, pCellNew->Id );
// remember when this node was upsized
Vec_IntWriteEntry( p->vNodeIter, Abc_ObjId(pObj), iIter );
}
// cleanup
nUpsizes = Vec_IntSize(vUpdate);
Vec_IntFree( vUpdate );
Vec_IntFree( vChamps );
Vec_FltFree( vSavings );
return nUpsizes;
return Limit;
}
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
Vec_IntClear( vUpdate );
Vec_IntForEachEntryTwo( vGates, vGatesBest, GateId, GateId2, i )
assert( GateId == GateId2 );
//printf( "Updating gates.\n" );
}
......@@ -449,9 +419,10 @@ if ( memcmp( pLoads, p->pLoads, sizeof(SC_Pair) * p->nObjs ) )
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( "Win:%3d. ", win );
printf( "PO:%5d. ", nPathPos );
printf( "Path:%6d. ", nPathNodes );
printf( "Gate:%5d. ", nUpsizes );
......@@ -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 * vPathNodes; // critical nodes and PIs
Vec_Int_t * vTFO;
int i, nUpsizes = -1;
int i, win, nUpsizes = -1;
int nAllPos, nAllNodes, nAllTfos, nAllUpsizes;
clock_t clk;
......@@ -512,24 +483,33 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nIters, int Wind
// perform upsizing
nAllPos = nAllNodes = nAllTfos = nAllUpsizes = 0;
for ( i = 0; nUpsizes && i < nIters; i++ )
for ( i = 0; i < nIters; i++ )
{
// detect critical path
clk = clock();
vPathPos = Abc_SclFindCriticalCoWindow( p, Window );
vPathNodes = Abc_SclFindCriticalNodeWindow( p, vPathPos, Window );
p->timeCone += clock() - clk;
// selectively upsize the nodes
clk = clock();
nUpsizes = Abc_SclFindUpsizes( p, vPathNodes, Ratio, Notches );
p->timeSize += clock() - clk;
// unmark critical path
clk = clock();
Abc_SclUnmarkCriticalNodeWindow( p, vPathNodes );
Abc_SclUnmarkCriticalNodeWindow( p, vPathPos );
p->timeCone += clock() - clk;
for ( win = Window; win <= 100; win *= 2 )
{
// detect critical path
clk = clock();
vPathPos = Abc_SclFindCriticalCoWindow( p, win );
vPathNodes = Abc_SclFindCriticalNodeWindow( p, vPathPos, win );
p->timeCone += clock() - clk;
// selectively upsize the nodes
clk = clock();
nUpsizes = Abc_SclFindUpsizes( p, vPathNodes, Ratio, Notches, i );
p->timeSize += clock() - clk;
// unmark critical path
clk = clock();
Abc_SclUnmarkCriticalNodeWindow( p, vPathNodes );
Abc_SclUnmarkCriticalNodeWindow( p, vPathPos );
p->timeCone += clock() - clk;
if ( nUpsizes > 0 )
break;
Vec_IntFree( vPathPos );
Vec_IntFree( vPathNodes );
}
if ( nUpsizes == 0 )
break;
// update timing information
clk = clock();
......@@ -547,7 +527,7 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nIters, int Wind
}
// 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);
nAllNodes += Vec_IntSize(vPathNodes);
nAllTfos += Vec_IntSize(vTFO);
......@@ -561,7 +541,7 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nIters, int Wind
if ( fVerbose )
{
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
p->timeTotal = clock() - p->timeTotal;
p->timeOther = p->timeTotal - p->timeCone - p->timeSize - p->timeTime;
......
......@@ -226,7 +226,10 @@ static inline int Vec_QuePop( Vec_Que_t * p )
assert( p->nSize > 1 );
Res = p->pHeap[1]; p->pOrder[Res] = -1;
if ( --p->nSize == 1 )
{
p->pHeap[1] = -1;
return Res;
}
v = p->pHeap[p->nSize]; p->pHeap[p->nSize] = -1;
p->pHeap[1] = v; p->pOrder[v] = 1;
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