Experimental algorithm for edge optimization.

This commit is contained in:
Alan Mishchenko 2016-04-13 15:54:14 -07:00
parent b9e403b46e
commit 813b0e5851
5 changed files with 404 additions and 14 deletions

View File

@ -132,6 +132,7 @@ struct Gia_Man_t_
Vec_Int_t * vFanout; // static fanout
Vec_Int_t * vMapping; // mapping for each node
Vec_Wec_t * vMapping2; // mapping for each node
Vec_Wec_t * vFanouts2; // mapping fanouts
Vec_Int_t * vCellMapping; // mapping for each node
void * pSatlutWinman; // windowing for SAT-based mapping
Vec_Int_t * vPacking; // packing information
@ -139,6 +140,7 @@ struct Gia_Man_t_
char * pCellStr; // cell description
Vec_Int_t * vLutConfigs; // LUT configurations
Vec_Int_t * vEdgeDelay; // special edge information
Vec_Int_t * vEdgeDelayR; // special edge information
Vec_Int_t * vEdge1; // special edge information
Vec_Int_t * vEdge2; // special edge information
Abc_Cex_t * pCexComb; // combinational counter-example
@ -997,6 +999,8 @@ static inline int Gia_ObjIsLut2( Gia_Man_t * p, int Id ) { re
static inline int Gia_ObjLutSize2( Gia_Man_t * p, int Id ) { return Vec_IntSize(Vec_WecEntry(p->vMapping2, Id)); }
static inline Vec_Int_t * Gia_ObjLutFanins2( Gia_Man_t * p, int Id ) { return Vec_WecEntry(p->vMapping2, Id); }
static inline int Gia_ObjLutFanin2( Gia_Man_t * p, int Id, int i ) { return Vec_IntEntry(Vec_WecEntry(p->vMapping2, Id), i); }
static inline int Gia_ObjLutFanoutNum2( Gia_Man_t * p, int Id ) { return Vec_IntSize(Vec_WecEntry(p->vFanouts2, Id)); }
static inline int Gia_ObjLutFanout2( Gia_Man_t * p, int Id, int i ) { return Vec_IntEntry(Vec_WecEntry(p->vFanouts2, Id), i); }
static inline int Gia_ManHasCellMapping( Gia_Man_t * p ) { return p->vCellMapping != NULL; }
static inline int Gia_ObjIsCell( Gia_Man_t * p, int iLit ) { return Vec_IntEntry(p->vCellMapping, iLit) != 0; }
@ -1026,6 +1030,8 @@ static inline int Gia_ObjCellId( Gia_Man_t * p, int iLit ) { re
for ( i = Vec_IntSize(vIds)-1; i >= 0 && (vVec = Vec_WecEntry(p->vMapping2, (iObj = Vec_IntEntry(vIds, i)))); i-- )
#define Gia_LutForEachFanin2( p, i, iFan, k ) \
for ( k = 0; k < Gia_ObjLutSize2(p,i) && ((iFan = Gia_ObjLutFanin2(p,i,k)),1); k++ )
#define Gia_LutForEachFanout2( p, i, iFan, k ) \
for ( k = 0; k < Gia_ObjLutFanoutNum2(p,i) && ((iFan = Gia_ObjLutFanout2(p,i,k)),1); k++ )
#define Gia_ManForEachCell( p, i ) \
for ( i = 2; i < 2*Gia_ManObjNum(p); i++ ) if ( !Gia_ObjIsCell(p, i) ) {} else

View File

@ -633,6 +633,357 @@ int Gia_ManEvalWindow( Gia_Man_t * p, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, V
return DelayMax;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Edg_ManToMapping( Gia_Man_t * p )
{
int iObj, iFanin, k;
assert( Gia_ManHasMapping(p) );
Vec_WecFreeP( &p->vMapping2 );
Vec_WecFreeP( &p->vFanouts2 );
p->vMapping2 = Vec_WecStart( Gia_ManObjNum(p) );
p->vFanouts2 = Vec_WecStart( Gia_ManObjNum(p) );
Gia_ManForEachLut( p, iObj )
{
assert( Gia_ObjLutSize(p, iObj) <= 4 );
Gia_LutForEachFanin( p, iObj, iFanin, k )
{
Vec_WecPush( p->vMapping2, iObj, iFanin );
Vec_WecPush( p->vFanouts2, iFanin, iObj );
}
}
}
/**Function*************************************************************
Synopsis [Computes delay for the given edge assignment.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Edg_ObjEvalEdgeDelay( Gia_Man_t * p, int iObj, Vec_Int_t * vDelay )
{
int DelayEdge = 0; // 2;
int DelayNoEdge = 1;
int i, iFan, Delay, DelayMax = 0;
assert( Gia_ObjIsLut2(p, iObj) );
Gia_LutForEachFanin2( p, iObj, iFan, i )
{
Delay = Vec_IntEntry(vDelay, iFan) + (Gia_ObjHaveEdge(p, iObj, iFan) ? DelayEdge : DelayNoEdge);
DelayMax = Abc_MaxInt( DelayMax, Delay );
}
//printf( "Obj %d - Level %d\n", iObj, DelayMax );
return DelayMax;
}
int Edg_ManEvalEdgeDelay( Gia_Man_t * p )
{
int iLut, Delay, DelayMax = 0;
assert( p->vEdge1 && p->vEdge2 );
if ( p->vEdgeDelay == NULL )
p->vEdgeDelay = Vec_IntStart( Gia_ManObjNum(p) );
else
Vec_IntFill( p->vEdgeDelay, Gia_ManObjNum(p), 0 );
Gia_ManForEachLut2( p, iLut )
{
Delay = Edg_ObjEvalEdgeDelay(p, iLut, p->vEdgeDelay);
Vec_IntWriteEntry( p->vEdgeDelay, iLut, Delay );
DelayMax = Abc_MaxInt( DelayMax, Delay );
}
return DelayMax;
}
static inline int Edg_ObjEvalEdgeDelayR( Gia_Man_t * p, int iObj, Vec_Int_t * vDelay )
{
int DelayEdge = 0; // 2;
int DelayNoEdge = 1;
int i, iFan, Delay, DelayMax = 0;
assert( Gia_ObjIsLut2(p, iObj) );
Gia_LutForEachFanout2( p, iObj, iFan, i )
{
Delay = Vec_IntEntry(vDelay, iFan) + (Gia_ObjHaveEdge(p, iObj, iFan) ? DelayEdge : DelayNoEdge);
DelayMax = Abc_MaxInt( DelayMax, Delay );
}
//printf( "Obj %d - LevelR %d\n", iObj, DelayMax );
return DelayMax;
}
int Edg_ManEvalEdgeDelayR( Gia_Man_t * p )
{
// int k, DelayNoEdge = 1;
int iLut, Delay, DelayMax = 0;
assert( p->vEdge1 && p->vEdge2 );
if ( p->vEdgeDelayR == NULL )
p->vEdgeDelayR = Vec_IntStart( Gia_ManObjNum(p) );
else
Vec_IntFill( p->vEdgeDelayR, Gia_ManObjNum(p), 0 );
// Gia_ManForEachCoDriverId( p, iLut, k )
// Vec_IntWriteEntry( p->vEdgeDelayR, iLut, DelayNoEdge );
Gia_ManForEachLut2Reverse( p, iLut )
{
Delay = Edg_ObjEvalEdgeDelayR(p, iLut, p->vEdgeDelayR);
Vec_IntWriteEntry( p->vEdgeDelayR, iLut, Delay );
DelayMax = Abc_MaxInt( DelayMax, Delay );
}
return DelayMax;
}
void Edg_ManCollectCritEdges( Gia_Man_t * p, Vec_Wec_t * vEdges, int DelayMax )
{
Vec_Int_t * vLevel;
int k, iLut, Delay1, Delay2;
assert( p->vEdge1 && p->vEdge2 );
Vec_WecClear( vEdges );
Vec_WecInit( vEdges, DelayMax + 1 );
Gia_ManForEachLut2( p, iLut )
{
Delay1 = Vec_IntEntry( p->vEdgeDelay, iLut );
Delay2 = Vec_IntEntry( p->vEdgeDelayR, iLut );
assert( Delay1 + Delay2 <= DelayMax );
if ( Delay1 + Delay2 == DelayMax )
Vec_WecPush( vEdges, Delay1, iLut );
}
// every level should have critical nodes, except the first one
//Vec_WecPrint( vEdges, 0 );
Vec_WecForEachLevelStart( vEdges, vLevel, k, 1 )
assert( Vec_IntSize(vLevel) > 0 );
}
/**Function*************************************************************
Synopsis [Update one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Edg_ObjImprove( Gia_Man_t * p, int iObj, int nEdgeLimit, int DelayMax, int fVerbose )
{
int nFaninsC = 0, nFanoutsC = 0; // critical
int nFaninsEC = 0, nFanoutsEC = 0; // edge-critical
int nFaninsENC = 0, nFanoutsENC = 0; // edge-non-critial
int pFanins[4], pFanouts[4];
int nEdgeDiff, nEdges = 0, Count = 0;
int i, iNext, Delay1, Delay2;
// count how many fanins have critical edge
Delay1 = Vec_IntEntry( p->vEdgeDelayR, iObj );
//if ( Delay1 > 1 )
Gia_LutForEachFanin2( p, iObj, iNext, i )
{
if ( !Gia_ObjIsAnd(Gia_ManObj(p, iNext)) )
continue;
Delay2 = Vec_IntEntry( p->vEdgeDelay, iNext );
if ( Gia_ObjHaveEdge(p, iObj, iNext) )
{
nEdges++;
assert( Delay1 + Delay2 <= DelayMax );
if ( Delay1 + Delay2 == DelayMax )
nFaninsEC++;
else
nFaninsENC++;
}
else
{
assert( Delay1 + Delay2 + 1 <= DelayMax );
if ( Delay1 + Delay2 + 1 == DelayMax )
pFanins[nFaninsC++] = iNext;
}
}
// count how many fanouts have critical edge
Delay1 = Vec_IntEntry( p->vEdgeDelay, iObj );
//if ( Delay2 < DelayMax - 1 )
Gia_LutForEachFanout2( p, iObj, iNext, i )
{
//if ( !Gia_ObjIsAnd(Gia_ManObj(p, iNext)) )
// continue;
assert( Gia_ObjIsAnd(Gia_ManObj(p, iNext)) );
Delay2 = Vec_IntEntry( p->vEdgeDelayR, iNext );
if ( Gia_ObjHaveEdge(p, iObj, iNext) )
{
nEdges++;
assert( Delay1 + Delay2 <= DelayMax );
if ( Delay1 + Delay2 == DelayMax )
nFanoutsEC++;
else
nFanoutsENC++;
}
else
{
assert( Delay1 + Delay2 + 1 <= DelayMax );
if ( Delay1 + Delay2 + 1 == DelayMax )
{
if ( nFanoutsC < nEdgeLimit )
pFanouts[nFanoutsC] = iNext;
nFanoutsC++;
}
}
}
if ( fVerbose )
{
printf( "%8d : ", iObj );
printf( "Edges = %d ", nEdges );
printf( "Fanins (all %d EC %d ENC %d C %d) ",
Gia_ObjLutSize2(p, iObj), nFaninsEC, nFaninsENC, nFaninsC );
printf( "Fanouts (all %d EC %d ENC %d C %d) ",
Gia_ObjLutFanoutNum2(p, iObj), nFanoutsEC, nFanoutsENC, nFanoutsC );
}
// consider simple cases
assert( nEdges <= nEdgeLimit );
if ( nEdges == nEdgeLimit )
{
if ( fVerbose )
printf( "Full\n" );
return 0;
}
nEdgeDiff = nEdgeLimit - nEdges;
// check if fanins or fanouts could be improved
if ( nFaninsEC == 0 && nFaninsC && nFaninsC <= nEdgeDiff )
{
for ( i = 0; i < nFaninsC; i++ )
if ( Gia_ObjEdgeCount(pFanins[i], p->vEdge1, p->vEdge2) == nEdgeLimit )
break;
if ( i == nFaninsC )
{
for ( i = 0; i < nFaninsC; i++ )
{
Count += Gia_ObjEdgeAdd( iObj, pFanins[i], p->vEdge1, p->vEdge2 );
Count += Gia_ObjEdgeAdd( pFanins[i], iObj, p->vEdge1, p->vEdge2 );
}
if ( Count )
printf( "Wrong number of edges.\n" );
if ( fVerbose )
printf( "Fixed %d critical fanins\n", nFaninsC );
return 1;
}
}
if ( nFanoutsEC == 0 && nFanoutsC && nFanoutsC <= nEdgeDiff )
{
for ( i = 0; i < nFanoutsC; i++ )
if ( Gia_ObjEdgeCount(pFanouts[i], p->vEdge1, p->vEdge2) == nEdgeLimit )
break;
if ( i == nFanoutsC )
{
for ( i = 0; i < nFanoutsC; i++ )
{
Count += Gia_ObjEdgeAdd( iObj, pFanouts[i], p->vEdge1, p->vEdge2 );
Count += Gia_ObjEdgeAdd( pFanouts[i], iObj, p->vEdge1, p->vEdge2 );
}
if ( Count )
printf( "Wrong number of edges.\n" );
if ( fVerbose )
printf( "Fixed %d critical fanouts\n", nFanoutsC );
return 1;
}
}
if ( fVerbose )
printf( "Cannot fix\n" );
return 0;
}
/**Function*************************************************************
Synopsis [Finds edge assignment.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Edg_ManAssignEdgeNew( Gia_Man_t * p, int nEdges, int fVerbose )
{
int DelayNoEdge = 1;
int fLevelVerbose = 0;
Vec_Int_t * vLevel;
Vec_Wec_t * vEdges = Vec_WecStart(0);
Vec_Int_t * vEdge1 = NULL, * vEdge2 = NULL;
int DelayD = 0, DelayR = 0, DelayPrev = ABC_INFINITY;
int k, j, i, iLast = -1, iObj;
if ( fVerbose )
printf( "Running edge assignment with E = %d.\n", nEdges );
// create fanouts
Edg_ManToMapping( p );
// create empty assignment
Vec_IntFreeP( &p->vEdge1 );
Vec_IntFreeP( &p->vEdge2 );
p->vEdge1 = Vec_IntStart( Gia_ManObjNum(p) );
p->vEdge2 = Vec_IntStart( Gia_ManObjNum(p) );
// perform optimization
for ( i = 0; i < 10000; i++ )
{
// if there is no improvement after 10 iterations, quit
if ( i > iLast + 50 )
break;
// create delay information
DelayD = Edg_ManEvalEdgeDelay( p );
DelayR = Edg_ManEvalEdgeDelayR( p );
assert( DelayD == DelayR + DelayNoEdge );
if ( DelayPrev > DelayD )
{
//printf( "Saving backup point at %d levels.\n", DelayD );
Vec_IntFreeP( &vEdge1 ); vEdge1 = Vec_IntDup( p->vEdge1 );
Vec_IntFreeP( &vEdge2 ); vEdge2 = Vec_IntDup( p->vEdge2 );
DelayPrev = DelayD;
iLast = i;
}
if ( fVerbose )
printf( "\nIter %4d : Delay = %4d\n", i, DelayD );
// collect critical nodes (nodes with critical edges)
Edg_ManCollectCritEdges( p, vEdges, DelayD );
// sort levels according to the number of critical edges
if ( fLevelVerbose )
{
Vec_WecForEachLevel( vEdges, vLevel, k )
Vec_IntPush( vLevel, k );
}
Vec_WecSort( vEdges, 0 );
if ( fLevelVerbose )
{
Vec_WecForEachLevel( vEdges, vLevel, k )
{
int Level = Vec_IntPop( vLevel );
printf( "%d: Level %2d : ", k, Level );
Vec_IntPrint( vLevel );
}
}
Vec_WecForEachLevel( vEdges, vLevel, k )
{
Vec_IntForEachEntry( vLevel, iObj, j )
if ( Edg_ObjImprove(p, iObj, nEdges, DelayD, fVerbose) ) // improved
break;
if ( j < Vec_IntSize(vLevel) )
break;
}
if ( k == Vec_WecSize(vEdges) ) // if we could not improve anything, quit
break;
}
Vec_WecFree( vEdges );
// update to the saved version
Vec_IntFreeP( &p->vEdge1 ); p->vEdge1 = vEdge1;
Vec_IntFreeP( &p->vEdge2 ); p->vEdge2 = vEdge2;
return DelayD;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////

View File

@ -95,6 +95,7 @@ void Gia_ManStop( Gia_Man_t * p )
Vec_IntFreeP( &p->vCofVars );
Vec_IntFreeP( &p->vLutConfigs );
Vec_IntFreeP( &p->vEdgeDelay );
Vec_IntFreeP( &p->vEdgeDelayR );
Vec_IntFreeP( &p->vEdge1 );
Vec_IntFreeP( &p->vEdge2 );
Vec_IntFreeP( &p->vUserPiIds );
@ -117,6 +118,7 @@ void Gia_ManStop( Gia_Man_t * p )
Vec_PtrFreeP( &p->vTtInputs );
Vec_IntFreeP( &p->vMapping );
Vec_WecFreeP( &p->vMapping2 );
Vec_WecFreeP( &p->vFanouts2 );
Vec_IntFreeP( &p->vCellMapping );
Vec_IntFreeP( &p->vPacking );
Vec_IntFreeP( &p->vConfigs );

View File

@ -364,7 +364,7 @@ Vec_Int_t * Gia_ManOrderWithBoxes( Gia_Man_t * p )
// verify counts
assert( curCi == Gia_ManCiNum(p) );
assert( curCo == Gia_ManCoNum(p) );
assert( Vec_IntSize(vNodes) == Gia_ManObjNum(p) );
//assert( Vec_IntSize(vNodes) == Gia_ManObjNum(p) );
return vNodes;
}

View File

@ -34849,21 +34849,36 @@ usage:
***********************************************************************/
int Abc_CommandAbc9Edge( Abc_Frame_t * pAbc, int argc, char ** argv )
{
int c, DelayMax = 0, fReverse = 0, fUseTwo = 1, fUsePack = 0, fVerbose = 0;
extern int Edg_ManAssignEdgeNew( Gia_Man_t * p, int nEdges, int fVerbose );
int c, DelayMax = 0, nEdges = 1, fReverse = 0, fUsePack = 0, fUseOld = 0, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "repvh" ) ) != EOF )
while ( ( c = Extra_UtilGetopt( argc, argv, "Erpovh" ) ) != EOF )
{
switch ( c )
{
case 'E':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-E\" should be followed by a positive integer.\n" );
goto usage;
}
nEdges = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( nEdges != 1 && nEdges != 2 )
{
Abc_Print( -1, "Edge limit (%d) should be 1 or 2.\n", nEdges );
goto usage;
}
break;
case 'r':
fReverse ^= 1;
break;
case 'e':
fUseTwo ^= 1;
break;
case 'p':
fUsePack ^= 1;
break;
case 'o':
fUseOld ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
@ -34887,29 +34902,45 @@ int Abc_CommandAbc9Edge( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Print( 0, "Current AIG has mapping into %d-LUTs.\n", Gia_ManLutSizeMax(pAbc->pGia) );
return 0;
}
if ( fUsePack )
{
if ( pAbc->pGia->vPacking == NULL )
{
Abc_Print( -1, "Packing information is not present.\n" );
return 0;
}
Gia_ManConvertPackingToEdges( pAbc->pGia );
return 0;
}
if ( !fUseOld )
{
if ( pAbc->pGia->pManTime != NULL && Tim_ManBoxNum((Tim_Man_t*)pAbc->pGia->pManTime) )
{
printf( "Currently this version of the algorithm does not work for designs with boxes.\n" );
return 0;
}
Edg_ManAssignEdgeNew( pAbc->pGia, nEdges, fVerbose );
return 0;
}
if ( pAbc->pGia->pManTime && fReverse )
{
Abc_Print( 0, "Reverse computation does not work when boxes are present.\n" );
return 0;
}
if ( fUsePack )
{
Gia_ManConvertPackingToEdges( pAbc->pGia );
return 0;
}
if ( fReverse )
DelayMax = Gia_ManComputeEdgeDelay2( pAbc->pGia );
else
DelayMax = Gia_ManComputeEdgeDelay( pAbc->pGia, fUseTwo );
DelayMax = Gia_ManComputeEdgeDelay( pAbc->pGia, nEdges == 2 );
//printf( "The number of edges = %d. Delay = %d.\n", Gia_ManEvalEdgeCount(pAbc->pGia), DelayMax );
return 0;
usage:
Abc_Print( -2, "usage: &edge [-repvh]\n" );
Abc_Print( -2, "usage: &edge [-E num] [-rpovh]\n" );
Abc_Print( -2, "\t find edge assignment of the LUT-mapped network\n" );
Abc_Print( -2, "\t-E num : the limit on the number of edges (1 <= num <= 2) [default = %d]\n", nEdges );
Abc_Print( -2, "\t-r : toggles using reverse order [default = %s]\n", fReverse? "yes": "no" );
Abc_Print( -2, "\t-e : toggles different edge assignments [default = %s]\n", fUseTwo? "yes": "no" );
Abc_Print( -2, "\t-p : toggles deriving edges from packing [default = %s]\n", fUsePack? "yes": "no" );
Abc_Print( -2, "\t-o : toggles using old algorithm [default = %s]\n", fUseOld? "yes": "no" );
Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : prints the command usage\n");
return 1;