Commit 05772a79 by Alan Mishchenko

Version abc80707

parent c7b331ef
...@@ -3322,6 +3322,10 @@ SOURCE=.\src\aig\nwk\nwkMerge.c ...@@ -3322,6 +3322,10 @@ SOURCE=.\src\aig\nwk\nwkMerge.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\src\aig\nwk\nwkMerge.h
# End Source File
# Begin Source File
SOURCE=.\src\aig\nwk\nwkObj.c SOURCE=.\src\aig\nwk\nwkObj.c
# End Source File # End Source File
# Begin Source File # Begin Source File
......
...@@ -108,21 +108,6 @@ struct Nwk_Obj_t_ ...@@ -108,21 +108,6 @@ struct Nwk_Obj_t_
Nwk_Obj_t ** pFanio; // fanins/fanouts Nwk_Obj_t ** pFanio; // fanins/fanouts
}; };
// the LUT merging parameters
typedef struct Nwk_LMPars_t_ Nwk_LMPars_t;
struct Nwk_LMPars_t_
{
int nMaxLutSize; // the max LUT size for merging (N=5)
int nMaxSuppSize; // the max total support size after merging (S=5)
int nMaxDistance; // the max number of nodes separating LUTs
int nMaxLevelDiff; // the max difference in levels
int nMaxFanout; // the max number of fanouts to traverse
int fUseTfiTfo; // enables the use of TFO/TFO nodes as candidates
int fVeryVerbose; // enables additional verbose output
int fVerbose; // enables verbose output
};
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS /// /// MACRO DEFINITIONS ///
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
***********************************************************************/ ***********************************************************************/
#include "nwk.h" #include "nwk.h"
#include "nwkMerge.h"
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
/// DECLARATIONS /// /// DECLARATIONS ///
...@@ -30,7 +31,7 @@ ...@@ -30,7 +31,7 @@
/**Function************************************************************* /**Function*************************************************************
Synopsis [Marks the fanins of the node with the current trav ID.] Synopsis [Allocates the graph.]
Description [] Description []
...@@ -39,24 +40,22 @@ ...@@ -39,24 +40,22 @@
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
void Nwk_ManMarkFanins_rec( Nwk_Obj_t * pLut, int nLevMin ) Nwk_Grf_t * Nwk_ManGraphAlloc( int nVertsMax )
{ {
Nwk_Obj_t * pNext; Nwk_Grf_t * p;
int i; p = ALLOC( Nwk_Grf_t, 1 );
if ( !Nwk_ObjIsNode(pLut) ) memset( p, 0, sizeof(Nwk_Grf_t) );
return; p->nVertsMax = nVertsMax;
if ( Nwk_ObjIsTravIdCurrent( pLut ) ) p->nEdgeHash = Aig_PrimeCudd( 3 * nVertsMax );
return; p->pEdgeHash = CALLOC( Nwk_Edg_t *, p->nEdgeHash );
Nwk_ObjSetTravIdCurrent( pLut ); p->pMemEdges = Aig_MmFixedStart( sizeof(Nwk_Edg_t), p->nEdgeHash );
if ( Nwk_ObjLevel(pLut) < nLevMin ) p->vPairs = Vec_IntAlloc( 1000 );
return; return p;
Nwk_ObjForEachFanin( pLut, pNext, i )
Nwk_ManMarkFanins_rec( pNext, nLevMin );
} }
/**Function************************************************************* /**Function*************************************************************
Synopsis [Marks the fanouts of the node with the current trav ID.] Synopsis [Deallocates the graph.]
Description [] Description []
...@@ -65,26 +64,85 @@ void Nwk_ManMarkFanins_rec( Nwk_Obj_t * pLut, int nLevMin ) ...@@ -65,26 +64,85 @@ void Nwk_ManMarkFanins_rec( Nwk_Obj_t * pLut, int nLevMin )
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
void Nwk_ManMarkFanouts_rec( Nwk_Obj_t * pLut, int nLevMax, int nFanMax ) void Nwk_ManGraphFree( Nwk_Grf_t * p )
{ {
Nwk_Obj_t * pNext; if ( p->vPairs ) Vec_IntFree( p->vPairs );
int i; if ( p->pMemEdges ) Aig_MmFixedStop( p->pMemEdges, 0 );
if ( !Nwk_ObjIsNode(pLut) ) if ( p->pMemVerts ) Aig_MmFlexStop( p->pMemVerts, 0 );
return; FREE( p->pVerts );
if ( Nwk_ObjIsTravIdCurrent( pLut ) ) FREE( p->pEdgeHash );
return; FREE( p->pMapLut2Id );
Nwk_ObjSetTravIdCurrent( pLut ); FREE( p->pMapId2Lut );
if ( Nwk_ObjLevel(pLut) > nLevMax ) free( p );
return; }
if ( Nwk_ObjFanoutNum(pLut) > nFanMax )
/**Function*************************************************************
Synopsis [Prepares the graph for solving the problem.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Nwk_ManGraphReportMemoryUsage( Nwk_Grf_t * p )
{
p->nMemBytes1 =
sizeof(Nwk_Grf_t) +
sizeof(void *) * p->nEdgeHash +
sizeof(int) * (p->nObjs + p->nVertsMax) +
sizeof(Nwk_Edg_t) * p->nEdges;
p->nMemBytes2 =
sizeof(Nwk_Vrt_t) * p->nVerts +
sizeof(int) * 2 * p->nEdges;
printf( "Memory usage stats: Preprocessing = %.2f Mb. Solving = %.2f Mb.\n",
1.0 * p->nMemBytes1 / (1<<20), 1.0 * p->nMemBytes2 / (1<<20) );
}
/**Function*************************************************************
Synopsis [Finds or adds the edge to the graph.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Nwk_ManGraphHashEdge( Nwk_Grf_t * p, int iLut1, int iLut2 )
{
Nwk_Edg_t * pEntry;
unsigned Key;
if ( iLut1 == iLut2 )
return; return;
Nwk_ObjForEachFanout( pLut, pNext, i ) if ( iLut1 > iLut2 )
Nwk_ManMarkFanouts_rec( pNext, nLevMax, nFanMax ); {
Key = iLut1;
iLut1 = iLut2;
iLut2 = Key;
}
assert( iLut1 < iLut2 );
if ( p->nObjs < iLut2 )
p->nObjs = iLut2;
Key = (unsigned)(741457 * iLut1 + 4256249 * iLut2) % p->nEdgeHash;
for ( pEntry = p->pEdgeHash[Key]; pEntry; pEntry = pEntry->pNext )
if ( pEntry->iNode1 == iLut1 && pEntry->iNode2 == iLut2 )
return;
pEntry = (Nwk_Edg_t *)Aig_MmFixedEntryFetch( p->pMemEdges );
pEntry->iNode1 = iLut1;
pEntry->iNode2 = iLut2;
pEntry->pNext = p->pEdgeHash[Key];
p->pEdgeHash[Key] = pEntry;
p->nEdges++;
} }
/**Function************************************************************* /**Function*************************************************************
Synopsis [Collects the circle of nodes around the given set.] Synopsis [Adds one entry to the list.]
Description [] Description []
...@@ -93,39 +151,22 @@ void Nwk_ManMarkFanouts_rec( Nwk_Obj_t * pLut, int nLevMax, int nFanMax ) ...@@ -93,39 +151,22 @@ void Nwk_ManMarkFanouts_rec( Nwk_Obj_t * pLut, int nLevMax, int nFanMax )
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
void Nwk_ManCollectCircle( Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, int nFanMax ) static inline void Nwk_ManGraphListAdd( Nwk_Grf_t * p, int * pList, Nwk_Vrt_t * pVertex )
{ {
Nwk_Obj_t * pObj, * pNext; if ( *pList )
int i, k;
Vec_PtrClear( vNext );
Vec_PtrForEachEntry( vStart, pObj, i )
{ {
Nwk_ObjForEachFanin( pObj, pNext, k ) Nwk_Vrt_t * pHead;
{ pHead = p->pVerts[*pList];
if ( !Nwk_ObjIsNode(pNext) ) pVertex->iPrev = 0;
continue; pVertex->iNext = pHead->Id;
if ( Nwk_ObjIsTravIdCurrent( pNext ) ) pHead->iPrev = pVertex->Id;
continue;
Nwk_ObjSetTravIdCurrent( pNext );
Vec_PtrPush( vNext, pNext );
}
Nwk_ObjForEachFanout( pObj, pNext, k )
{
if ( !Nwk_ObjIsNode(pNext) )
continue;
if ( Nwk_ObjIsTravIdCurrent( pNext ) )
continue;
Nwk_ObjSetTravIdCurrent( pNext );
if ( Nwk_ObjFanoutNum(pNext) > nFanMax )
continue;
Vec_PtrPush( vNext, pNext );
}
} }
*pList = pVertex->Id;
} }
/**Function************************************************************* /**Function*************************************************************
Synopsis [Collects the circle of nodes removes from the given one.] Synopsis [Deletes one entry from the list.]
Description [] Description []
...@@ -134,68 +175,215 @@ void Nwk_ManCollectCircle( Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, int nFanMax ) ...@@ -134,68 +175,215 @@ void Nwk_ManCollectCircle( Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, int nFanMax )
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
void Nwk_ManCollectNonOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) static inline void Nwk_ManGraphListDelete( Nwk_Grf_t * p, int * pList, Nwk_Vrt_t * pVertex )
{ {
Vec_Ptr_t * vTemp; assert( *pList );
Nwk_Obj_t * pObj; if ( pVertex->iPrev )
int i, k; {
Vec_PtrClear( vCands ); // assert( p->pVerts[pVertex->iPrev]->iNext == pVertex->Id );
if ( pPars->nMaxSuppSize - Nwk_ObjFaninNum(pLut) <= 1 ) p->pVerts[pVertex->iPrev]->iNext = pVertex->iNext;
return; }
if ( pVertex->iNext )
{
// assert( p->pVerts[pVertex->iNext]->iPrev == pVertex->Id );
p->pVerts[pVertex->iNext]->iPrev = pVertex->iPrev;
}
if ( *pList == pVertex->Id )
*pList = pVertex->iNext;
pVertex->iPrev = pVertex->iNext = 0;
}
// collect nodes removed by this distance /**Function*************************************************************
assert( pPars->nMaxDistance > 0 );
Vec_PtrClear( vStart ); Synopsis [Inserts the edge into one of the linked lists.]
Vec_PtrPush( vStart, pLut );
Nwk_ManIncrementTravId( pLut->pMan ); Description []
Nwk_ObjSetTravIdCurrent( pLut );
for ( i = 1; i < pPars->nMaxDistance; i++ ) SideEffects []
SeeAlso []
***********************************************************************/
static inline void Nwk_ManGraphListInsert( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex )
{
Nwk_Vrt_t * pNext;
assert( pVertex->nEdges > 0 );
if ( pVertex->nEdges == 1 )
{ {
Nwk_ManCollectCircle( vStart, vNext, pPars->nMaxFanout ); pNext = p->pVerts[ pVertex->pEdges[0] ];
vTemp = vStart; if ( pNext->nEdges >= NWK_MAX_LIST )
vStart = vNext; Nwk_ManGraphListAdd( p, p->pLists1 + NWK_MAX_LIST, pVertex );
vNext = vTemp; else
// collect the nodes in vStart Nwk_ManGraphListAdd( p, p->pLists1 + pNext->nEdges, pVertex );
Vec_PtrForEachEntry( vStart, pObj, k ) }
Vec_PtrPush( vCands, pObj ); else
{
if ( pVertex->nEdges >= NWK_MAX_LIST )
Nwk_ManGraphListAdd( p, p->pLists2 + NWK_MAX_LIST, pVertex );
else
Nwk_ManGraphListAdd( p, p->pLists2 + pVertex->nEdges, pVertex );
} }
}
// mark the TFI/TFO nodes /**Function*************************************************************
Nwk_ManIncrementTravId( pLut->pMan );
if ( pPars->fUseTfiTfo ) Synopsis [Extracts the edge from one of the linked lists.]
Nwk_ObjSetTravIdCurrent( pLut );
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Nwk_ManGraphListExtract( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex )
{
Nwk_Vrt_t * pNext;
assert( pVertex->nEdges > 0 );
if ( pVertex->nEdges == 1 )
{
pNext = p->pVerts[ pVertex->pEdges[0] ];
if ( pNext->nEdges >= NWK_MAX_LIST )
Nwk_ManGraphListDelete( p, p->pLists1 + NWK_MAX_LIST, pVertex );
else
Nwk_ManGraphListDelete( p, p->pLists1 + pNext->nEdges, pVertex );
}
else else
{ {
Nwk_ObjSetTravIdPrevious( pLut ); if ( pVertex->nEdges >= NWK_MAX_LIST )
Nwk_ManMarkFanins_rec( pLut, Nwk_ObjLevel(pLut) - pPars->nMaxDistance ); Nwk_ManGraphListDelete( p, p->pLists2 + NWK_MAX_LIST, pVertex );
Nwk_ObjSetTravIdPrevious( pLut ); else
Nwk_ManMarkFanouts_rec( pLut, Nwk_ObjLevel(pLut) + pPars->nMaxDistance, pPars->nMaxFanout ); Nwk_ManGraphListDelete( p, p->pLists2 + pVertex->nEdges, pVertex );
} }
}
// collect nodes satisfying the following conditions: /**Function*************************************************************
// - they are close enough in terms of distance
// - they are not in the TFI/TFO of the LUT Synopsis [Prepares the graph for solving the problem.]
// - they have no more than the given number of fanins
// - they have no more than the given diff in delay Description []
k = 0;
Vec_PtrForEachEntry( vCands, pObj, i ) SideEffects []
SeeAlso []
***********************************************************************/
void Nwk_ManGraphPrepare( Nwk_Grf_t * p )
{
Nwk_Edg_t * pEntry;
Nwk_Vrt_t * pVertex;
int * pnEdges, nBytes, i;
// allocate memory for the present objects
p->pMapLut2Id = ALLOC( int, p->nObjs+1 );
p->pMapId2Lut = ALLOC( int, p->nVertsMax+1 );
memset( p->pMapLut2Id, 0xff, sizeof(int) * (p->nObjs+1) );
memset( p->pMapId2Lut, 0xff, sizeof(int) * (p->nVertsMax+1) );
// mark present objects
Nwk_GraphForEachEdge( p, pEntry, i )
{ {
if ( Nwk_ObjIsTravIdCurrent(pObj) ) assert( pEntry->iNode1 <= p->nObjs );
continue; assert( pEntry->iNode2 <= p->nObjs );
if ( Nwk_ObjFaninNum(pLut) + Nwk_ObjFaninNum(pObj) > pPars->nMaxSuppSize ) p->pMapLut2Id[ pEntry->iNode1 ] = 0;
continue; p->pMapLut2Id[ pEntry->iNode2 ] = 0;
if ( Nwk_ObjLevel(pLut) - Nwk_ObjLevel(pObj) > pPars->nMaxLevelDiff ||
Nwk_ObjLevel(pObj) - Nwk_ObjLevel(pLut) > pPars->nMaxLevelDiff )
continue;
Vec_PtrWriteEntry( vCands, k++, pObj );
} }
Vec_PtrShrink( vCands, k ); // map objects
p->nVerts = 0;
for ( i = 0; i <= p->nObjs; i++ )
{
if ( p->pMapLut2Id[i] == 0 )
{
p->pMapLut2Id[i] = ++p->nVerts;
p->pMapId2Lut[p->nVerts] = i;
}
}
// count the edges and mark present objects
pnEdges = CALLOC( int, p->nVerts+1 );
Nwk_GraphForEachEdge( p, pEntry, i )
{
// translate into vertices
assert( pEntry->iNode1 <= p->nObjs );
assert( pEntry->iNode2 <= p->nObjs );
pEntry->iNode1 = p->pMapLut2Id[pEntry->iNode1];
pEntry->iNode2 = p->pMapLut2Id[pEntry->iNode2];
// count the edges
assert( pEntry->iNode1 <= p->nVerts );
assert( pEntry->iNode2 <= p->nVerts );
pnEdges[pEntry->iNode1]++;
pnEdges[pEntry->iNode2]++;
}
// allocate the real graph
p->pMemVerts = Aig_MmFlexStart();
p->pVerts = ALLOC( Nwk_Vrt_t *, p->nVerts + 1 );
p->pVerts[0] = NULL;
for ( i = 1; i <= p->nVerts; i++ )
{
assert( pnEdges[i] > 0 );
nBytes = sizeof(Nwk_Vrt_t) + sizeof(int) * pnEdges[i];
p->pVerts[i] = (Nwk_Vrt_t *)Aig_MmFlexEntryFetch( p->pMemVerts, nBytes );
memset( p->pVerts[i], 0, nBytes );
p->pVerts[i]->Id = i;
}
// add edges to the real graph
Nwk_GraphForEachEdge( p, pEntry, i )
{
pVertex = p->pVerts[pEntry->iNode1];
pVertex->pEdges[ pVertex->nEdges++ ] = pEntry->iNode2;
pVertex = p->pVerts[pEntry->iNode2];
pVertex->pEdges[ pVertex->nEdges++ ] = pEntry->iNode1;
}
// put vertices into the data structure
for ( i = 1; i <= p->nVerts; i++ )
{
assert( p->pVerts[i]->nEdges == pnEdges[i] );
Nwk_ManGraphListInsert( p, p->pVerts[i] );
}
// clean up
Aig_MmFixedStop( p->pMemEdges, 0 ); p->pMemEdges = NULL;
FREE( p->pEdgeHash );
// p->nEdgeHash = 0;
free( pnEdges );
} }
/**Function*************************************************************
Synopsis [Updates the problem after pulling out one edge.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Nwk_ManGraphCheckLists( Nwk_Grf_t * p )
{
Nwk_Vrt_t * pVertex, * pNext;
int i, j;
assert( p->pLists1[0] == 0 );
for ( i = 1; i <= NWK_MAX_LIST; i++ )
if ( p->pLists1[i] )
{
pVertex = p->pVerts[ p->pLists1[i] ];
assert( pVertex->nEdges == 1 );
pNext = p->pVerts[ pVertex->pEdges[0] ];
assert( pNext->nEdges == i || pNext->nEdges > NWK_MAX_LIST );
}
// find the next vertext to extract
assert( p->pLists2[0] == 0 );
assert( p->pLists2[1] == 0 );
for ( j = 2; j <= NWK_MAX_LIST; j++ )
if ( p->pLists2[j] )
{
pVertex = p->pVerts[ p->pLists2[j] ];
assert( pVertex->nEdges == j || pVertex->nEdges > NWK_MAX_LIST );
}
}
/**Function************************************************************* /**Function*************************************************************
Synopsis [Count the total number of fanins.] Synopsis [Extracts the edge from one of the linked lists.]
Description [] Description []
...@@ -204,18 +392,21 @@ void Nwk_ManCollectNonOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vStart, Vec_Pt ...@@ -204,18 +392,21 @@ void Nwk_ManCollectNonOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vStart, Vec_Pt
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
int Nwk_ManCountTotalFanins( Nwk_Obj_t * pLut, Nwk_Obj_t * pCand ) static inline void Nwk_ManGraphVertexRemoveEdge( Nwk_Vrt_t * pThis, Nwk_Vrt_t * pNext )
{ {
Nwk_Obj_t * pFanin; int k;
int i, nCounter = Nwk_ObjFaninNum(pLut); for ( k = 0; k < pThis->nEdges; k++ )
Nwk_ObjForEachFanin( pCand, pFanin, i ) if ( pThis->pEdges[k] == pNext->Id )
nCounter += !pFanin->MarkC; break;
return nCounter; assert( k < pThis->nEdges );
pThis->nEdges--;
for ( ; k < pThis->nEdges; k++ )
pThis->pEdges[k] = pThis->pEdges[k+1];
} }
/**Function************************************************************* /**Function*************************************************************
Synopsis [Collects overlapping candidates.] Synopsis [Updates the problem after pulling out one edge.]
Description [] Description []
...@@ -224,97 +415,105 @@ int Nwk_ManCountTotalFanins( Nwk_Obj_t * pLut, Nwk_Obj_t * pCand ) ...@@ -224,97 +415,105 @@ int Nwk_ManCountTotalFanins( Nwk_Obj_t * pLut, Nwk_Obj_t * pCand )
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
void Nwl_ManCollectOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) void Nwk_ManGraphUpdate( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex, Nwk_Vrt_t * pNext )
{ {
Nwk_Obj_t * pFanin, * pObj; Nwk_Vrt_t * pChanged, * pOther;
int i, k; int i, k;
// mark fanins of pLut // Nwk_ManGraphCheckLists( p );
Nwk_ObjForEachFanin( pLut, pFanin, i ) Nwk_ManGraphListExtract( p, pVertex );
pFanin->MarkC = 1; Nwk_ManGraphListExtract( p, pNext );
// collect the matching fanouts of each fanin of the node // update neihbors of pVertex
Vec_PtrClear( vCands ); Nwk_VertexForEachAdjacent( p, pVertex, pChanged, i )
Nwk_ManIncrementTravId( pLut->pMan );
Nwk_ObjSetTravIdCurrent( pLut );
Nwk_ObjForEachFanin( pLut, pFanin, i )
{ {
if ( !Nwk_ObjIsNode(pFanin) ) if ( pChanged == pNext )
continue;
if ( Nwk_ObjFanoutNum(pFanin) > pPars->nMaxFanout )
continue; continue;
Nwk_ObjForEachFanout( pFanin, pObj, k ) Nwk_ManGraphListExtract( p, pChanged );
// move those that use this one
if ( pChanged->nEdges > 1 )
Nwk_VertexForEachAdjacent( p, pChanged, pOther, k )
{ {
if ( !Nwk_ObjIsNode(pObj) ) if ( pOther == pVertex || pOther->nEdges > 1 )
continue; continue;
if ( Nwk_ObjIsTravIdCurrent( pObj ) ) assert( pOther->nEdges == 1 );
continue; Nwk_ManGraphListExtract( p, pOther );
Nwk_ObjSetTravIdCurrent( pObj ); pChanged->nEdges--;
// check the difference in delay Nwk_ManGraphListInsert( p, pOther );
if ( Nwk_ObjLevel(pLut) - Nwk_ObjLevel(pObj) > pPars->nMaxLevelDiff || pChanged->nEdges++;
Nwk_ObjLevel(pObj) - Nwk_ObjLevel(pLut) > pPars->nMaxLevelDiff ) }
continue; // remove the edge
// check the total number of fanins of the node Nwk_ManGraphVertexRemoveEdge( pChanged, pVertex );
if ( Nwk_ManCountTotalFanins(pLut, pObj) > pPars->nMaxSuppSize ) // add the changed vertex back
if ( pChanged->nEdges > 0 )
Nwk_ManGraphListInsert( p, pChanged );
}
// update neihbors of pNext
Nwk_VertexForEachAdjacent( p, pNext, pChanged, i )
{
if ( pChanged == pVertex )
continue;
Nwk_ManGraphListExtract( p, pChanged );
// move those that use this one
if ( pChanged->nEdges > 1 )
Nwk_VertexForEachAdjacent( p, pChanged, pOther, k )
{
if ( pOther == pNext || pOther->nEdges > 1 )
continue; continue;
Vec_PtrPush( vCands, pObj ); assert( pOther->nEdges == 1 );
Nwk_ManGraphListExtract( p, pOther );
pChanged->nEdges--;
Nwk_ManGraphListInsert( p, pOther );
pChanged->nEdges++;
} }
// remove the edge
Nwk_ManGraphVertexRemoveEdge( pChanged, pNext );
// add the changed vertex back
if ( pChanged->nEdges > 0 )
Nwk_ManGraphListInsert( p, pChanged );
} }
// unmark fanins of pLut // add to the result
Nwk_ObjForEachFanin( pLut, pFanin, i ) if ( pVertex->Id < pNext->Id )
pFanin->MarkC = 0; {
Vec_IntPush( p->vPairs, p->pMapId2Lut[pVertex->Id] );
Vec_IntPush( p->vPairs, p->pMapId2Lut[pNext->Id] );
}
else
{
Vec_IntPush( p->vPairs, p->pMapId2Lut[pNext->Id] );
Vec_IntPush( p->vPairs, p->pMapId2Lut[pVertex->Id] );
}
// Nwk_ManGraphCheckLists( p );
} }
/**Function*************************************************************
Synopsis [Counts the number of entries in the list.]
#define MAX_LIST 16 Description []
SideEffects []
// edge of the graph SeeAlso []
typedef struct Nwk_Edg_t_ Nwk_Edg_t;
struct Nwk_Edg_t_ ***********************************************************************/
{ int Nwk_ManGraphListLength( Nwk_Grf_t * p, int List )
int iNode1; // the first node
int iNode2; // the second node
Nwk_Edg_t * pNext; // the next edge
};
// vertex of the graph
typedef struct Nwk_Vrt_t_ Nwk_Vrt_t;
struct Nwk_Vrt_t_
{
int Id; // the vertex number
int iPrev; // the previous vertex in the list
int iNext; // the next vertex in the list
int nEdges; // the number of edges
int pEdges[0]; // the array of edges
};
// the connectivity graph
typedef struct Nwk_Grf_t_ Nwk_Grf_t;
struct Nwk_Grf_t_
{ {
// preliminary graph representation Nwk_Vrt_t * pThis;
int nObjs; // the number of objects int fVerbose = 0;
int nVertsPre; // the upper bound on the number of vertices int Counter = 0;
int nEdgeHash; // approximate number of edges Nwk_ListForEachVertex( p, List, pThis )
Nwk_Edg_t ** pEdgeHash; // hash table for edges {
Aig_MmFixed_t * pMemEdges; // memory for edges if ( fVerbose && Counter < 20 )
// graph representation printf( "%d ", p->pVerts[pThis->pEdges[0]]->nEdges );
int nEdges; // the number of edges Counter++;
int nVerts; // the number of vertices }
Nwk_Vrt_t ** pVerts; // the array of vertices if ( fVerbose )
Aig_MmFlex_t * pMemVerts; // memory for vertices printf( "\n" );
// intermediate data return Counter;
int pLists1[MAX_LIST+1]; }
int pLists2[MAX_LIST+1];
// the results of matching
Vec_Int_t * vPairs;
// mappings graph into LUTs and back
int * pMapLut2Id;
int * pMapId2Lut;
};
/**Function************************************************************* /**Function*************************************************************
Synopsis [Deallocates the graph.] Synopsis [Returns the adjacent vertex with the mininum number of edges.]
Description [] Description []
...@@ -323,21 +522,21 @@ struct Nwk_Grf_t_ ...@@ -323,21 +522,21 @@ struct Nwk_Grf_t_
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
void Nwk_ManGraphFree( Nwk_Grf_t * p ) Nwk_Vrt_t * Nwk_ManGraphListFindMinEdge( Nwk_Grf_t * p, Nwk_Vrt_t * pVert )
{ {
if ( p->vPairs ) Vec_IntFree( p->vPairs ); Nwk_Vrt_t * pThis, * pMinCost = NULL;
if ( p->pMemEdges ) Aig_MmFixedStop( p->pMemEdges, 0 ); int k;
if ( p->pMemVerts ) Aig_MmFlexStop( p->pMemVerts, 0 ); Nwk_VertexForEachAdjacent( p, pVert, pThis, k )
FREE( p->pEdgeHash ); {
FREE( p->pVerts ); if ( pMinCost == NULL || pMinCost->nEdges > pThis->nEdges )
FREE( p->pMapLut2Id ); pMinCost = pThis;
FREE( p->pMapId2Lut ); }
free( p ); return pMinCost;
} }
/**Function************************************************************* /**Function*************************************************************
Synopsis [Allocates the graph.] Synopsis [Finds the best vertext in the list.]
Description [] Description []
...@@ -346,27 +545,29 @@ void Nwk_ManGraphFree( Nwk_Grf_t * p ) ...@@ -346,27 +545,29 @@ void Nwk_ManGraphFree( Nwk_Grf_t * p )
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
Nwk_Grf_t * Nwk_ManGraphAlloc( int nObjs, int nVertsPre ) Nwk_Vrt_t * Nwk_ManGraphListFindMin( Nwk_Grf_t * p, int List )
{ {
Nwk_Grf_t * p; Nwk_Vrt_t * pThis, * pMinCost = NULL;
p = ALLOC( Nwk_Grf_t, 1 ); int k, Counter = 10000, BestCost = 1000000;
memset( p, 0, sizeof(Nwk_Grf_t) ); Nwk_ListForEachVertex( p, List, pThis )
p->nObjs = nObjs; {
p->nVertsPre = nVertsPre; for ( k = 0; k < pThis->nEdges; k++ )
p->nEdgeHash = Aig_PrimeCudd(10 * nVertsPre); {
p->pEdgeHash = CALLOC( Nwk_Edg_t *, p->nEdgeHash ); if ( pMinCost == NULL || BestCost > p->pVerts[pThis->pEdges[k]]->nEdges )
p->pMemEdges = Aig_MmFixedStart( sizeof(Nwk_Edg_t), p->nEdgeHash ); {
p->pMapLut2Id = ALLOC( int, nObjs ); BestCost = p->pVerts[pThis->pEdges[k]]->nEdges;
p->pMapId2Lut = ALLOC( int, nVertsPre ); pMinCost = pThis;
p->vPairs = Vec_IntAlloc( 1000 ); }
memset( p->pMapLut2Id, 0xff, sizeof(int) * nObjs ); }
memset( p->pMapId2Lut, 0xff, sizeof(int) * nVertsPre ); if ( --Counter == 0 )
return p; break;
}
return pMinCost;
} }
/**Function************************************************************* /**Function*************************************************************
Synopsis [Finds or adds the edge to the graph.] Synopsis [Solves the problem by extracting one edge at a time.]
Description [] Description []
...@@ -375,16 +576,50 @@ Nwk_Grf_t * Nwk_ManGraphAlloc( int nObjs, int nVertsPre ) ...@@ -375,16 +576,50 @@ Nwk_Grf_t * Nwk_ManGraphAlloc( int nObjs, int nVertsPre )
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
static inline void Nwk_ManGraphSetMapping( Nwk_Grf_t * p, int iLut ) void Nwk_ManGraphSolve( Nwk_Grf_t * p )
{ {
p->nVerts++; Nwk_Vrt_t * pVertex, * pNext;
p->pMapId2Lut[p->nVerts] = iLut; int i, j;
p->pMapLut2Id[iLut] = p->nVerts; Nwk_ManGraphPrepare( p );
while ( 1 )
{
// find the next vertex to extract
assert( p->pLists1[0] == 0 );
for ( i = 1; i <= NWK_MAX_LIST; i++ )
if ( p->pLists1[i] )
{
// printf( "%d ", i );
// printf( "ListA = %2d. Length = %5d.\n", i, Nwk_ManGraphListLength(p,p->pLists1[i]) );
pVertex = p->pVerts[ p->pLists1[i] ];
assert( pVertex->nEdges == 1 );
pNext = p->pVerts[ pVertex->pEdges[0] ];
Nwk_ManGraphUpdate( p, pVertex, pNext );
break;
}
if ( i < NWK_MAX_LIST + 1 )
continue;
// find the next vertex to extract
assert( p->pLists2[0] == 0 );
assert( p->pLists2[1] == 0 );
for ( j = 2; j <= NWK_MAX_LIST; j++ )
if ( p->pLists2[j] )
{
// printf( "***%d ", j );
// printf( "ListB = %2d. Length = %5d.\n", j, Nwk_ManGraphListLength(p,p->pLists2[j]) );
pVertex = Nwk_ManGraphListFindMin( p, p->pLists2[j] );
assert( pVertex->nEdges == j || j == NWK_MAX_LIST );
pNext = Nwk_ManGraphListFindMinEdge( p, pVertex );
Nwk_ManGraphUpdate( p, pVertex, pNext );
break;
}
if ( j == NWK_MAX_LIST + 1 )
break;
}
} }
/**Function************************************************************* /**Function*************************************************************
Synopsis [Finds or adds the edge to the graph.] Synopsis [Reads graph from file.]
Description [] Description []
...@@ -393,34 +628,26 @@ static inline void Nwk_ManGraphSetMapping( Nwk_Grf_t * p, int iLut ) ...@@ -393,34 +628,26 @@ static inline void Nwk_ManGraphSetMapping( Nwk_Grf_t * p, int iLut )
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
static inline void Nwk_ManGraphHashEdge( Nwk_Grf_t * p, int iLut1, int iLut2 ) Nwk_Grf_t * Nwk_ManLutMergeReadGraph( char * pFileName )
{ {
Nwk_Edg_t * pEntry; Nwk_Grf_t * p;
int Key; FILE * pFile;
if ( iLut1 == iLut2 ) char Buffer[100];
return; int nNodes, nEdges, iNode1, iNode2;
if ( iLut1 > iLut2 ) pFile = fopen( pFileName, "r" );
{ fscanf( pFile, "%s %d", Buffer, &nNodes );
Key = iLut1; fscanf( pFile, "%s %d", Buffer, &nEdges );
iLut1 = iLut2; p = Nwk_ManGraphAlloc( nNodes );
iLut2 = Key; while ( fscanf( pFile, "%s %d %d", Buffer, &iNode1, &iNode2 ) == 3 )
} Nwk_ManGraphHashEdge( p, iNode1, iNode2 );
assert( iLut1 < iLut2 ); assert( p->nEdges == nEdges );
Key = (741457 * iLut1 + 4256249 * iLut2) % p->nEdgeHash; fclose( pFile );
for ( pEntry = p->pEdgeHash[Key]; pEntry; pEntry = pEntry->pNext ) return p;
if ( pEntry->iNode1 == iLut1 && pEntry->iNode2 == iLut2 )
return;
pEntry = (Nwk_Edg_t *)Aig_MmFixedEntryFetch( p->pMemEdges );
pEntry->iNode1 = iLut1;
pEntry->iNode2 = iLut2;
pEntry->pNext = p->pEdgeHash[Key];
p->pEdgeHash[Key] = pEntry;
p->nEdges++;
} }
/**Function************************************************************* /**Function*************************************************************
Synopsis [Prepares the graph for solving the problem.] Synopsis [Solves the graph coming from file.]
Description [] Description []
...@@ -429,22 +656,30 @@ static inline void Nwk_ManGraphHashEdge( Nwk_Grf_t * p, int iLut1, int iLut2 ) ...@@ -429,22 +656,30 @@ static inline void Nwk_ManGraphHashEdge( Nwk_Grf_t * p, int iLut1, int iLut2 )
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
static inline void Nwk_ManGraphListAdd( Nwk_Grf_t * p, int * pList, Nwk_Vrt_t * pVertex ) int Nwk_ManLutMergeGraphTest( char * pFileName )
{ {
if ( *pList ) int nPairs;
{ Nwk_Grf_t * p;
Nwk_Vrt_t * pHead; int clk = clock();
pHead = p->pVerts[*pList]; p = Nwk_ManLutMergeReadGraph( pFileName );
pVertex->iPrev = 0; PRT( "Reading", clock() - clk );
pVertex->iNext = pHead->Id; clk = clock();
pHead->iPrev = pVertex->Id; Nwk_ManGraphSolve( p );
} printf( "GRAPH: Nodes = %6d. Edges = %6d. Pairs = %6d. ",
*pList = pVertex->Id; p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 );
PRT( "Solving", clock() - clk );
nPairs = Vec_IntSize(p->vPairs)/2;
Nwk_ManGraphReportMemoryUsage( p );
Nwk_ManGraphFree( p );
return nPairs;
} }
/**Function************************************************************* /**Function*************************************************************
Synopsis [Prepares the graph for solving the problem.] Synopsis [Marks the fanins of the node with the current trav ID.]
Description [] Description []
...@@ -453,21 +688,24 @@ static inline void Nwk_ManGraphListAdd( Nwk_Grf_t * p, int * pList, Nwk_Vrt_t * ...@@ -453,21 +688,24 @@ static inline void Nwk_ManGraphListAdd( Nwk_Grf_t * p, int * pList, Nwk_Vrt_t *
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
static inline void Nwk_ManGraphListDelete( Nwk_Grf_t * p, int * pList, Nwk_Vrt_t * pVertex ) void Nwk_ManMarkFanins_rec( Nwk_Obj_t * pLut, int nLevMin )
{ {
assert( *pList ); Nwk_Obj_t * pNext;
if ( pVertex->iPrev ) int i;
p->pVerts[pVertex->iPrev]->iNext = pVertex->iNext; if ( !Nwk_ObjIsNode(pLut) )
if ( pVertex->iNext ) return;
p->pVerts[pVertex->iNext]->iNext = pVertex->iPrev; if ( Nwk_ObjIsTravIdCurrent( pLut ) )
if ( *pList == pVertex->Id ) return;
*pList = pVertex->iNext; Nwk_ObjSetTravIdCurrent( pLut );
pVertex->iPrev = pVertex->iNext = 0; if ( Nwk_ObjLevel(pLut) < nLevMin )
return;
Nwk_ObjForEachFanin( pLut, pNext, i )
Nwk_ManMarkFanins_rec( pNext, nLevMin );
} }
/**Function************************************************************* /**Function*************************************************************
Synopsis [Inserts the edge into one of the linked lists.] Synopsis [Marks the fanouts of the node with the current trav ID.]
Description [] Description []
...@@ -476,30 +714,26 @@ static inline void Nwk_ManGraphListDelete( Nwk_Grf_t * p, int * pList, Nwk_Vrt_t ...@@ -476,30 +714,26 @@ static inline void Nwk_ManGraphListDelete( Nwk_Grf_t * p, int * pList, Nwk_Vrt_t
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
static inline void Nwk_ManGraphListInsert( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex ) void Nwk_ManMarkFanouts_rec( Nwk_Obj_t * pLut, int nLevMax, int nFanMax )
{ {
Nwk_Vrt_t * pNext; Nwk_Obj_t * pNext;
assert( pVertex->nEdges > 0 ); int i;
if ( pVertex->nEdges == 1 ) if ( !Nwk_ObjIsNode(pLut) )
{ return;
pNext = p->pVerts[ pVertex->pEdges[0] ]; if ( Nwk_ObjIsTravIdCurrent( pLut ) )
if ( pNext->nEdges >= MAX_LIST ) return;
Nwk_ManGraphListAdd( p, p->pLists1 + MAX_LIST, pVertex ); Nwk_ObjSetTravIdCurrent( pLut );
else if ( Nwk_ObjLevel(pLut) > nLevMax )
Nwk_ManGraphListAdd( p, p->pLists1 + pNext->nEdges, pVertex ); return;
} if ( Nwk_ObjFanoutNum(pLut) > nFanMax )
else return;
{ Nwk_ObjForEachFanout( pLut, pNext, i )
if ( pVertex->nEdges >= MAX_LIST ) Nwk_ManMarkFanouts_rec( pNext, nLevMax, nFanMax );
Nwk_ManGraphListAdd( p, p->pLists1 + MAX_LIST, pVertex );
else
Nwk_ManGraphListAdd( p, p->pLists1 + pVertex->nEdges, pVertex );
}
} }
/**Function************************************************************* /**Function*************************************************************
Synopsis [Extracts the edge from one of the linked lists.] Synopsis [Collects the circle of nodes around the given set.]
Description [] Description []
...@@ -508,30 +742,39 @@ static inline void Nwk_ManGraphListInsert( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex ) ...@@ -508,30 +742,39 @@ static inline void Nwk_ManGraphListInsert( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex )
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
static inline void Nwk_ManGraphListExtract( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex ) void Nwk_ManCollectCircle( Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, int nFanMax )
{ {
Nwk_Vrt_t * pNext; Nwk_Obj_t * pObj, * pNext;
assert( pVertex->nEdges > 0 ); int i, k;
if ( pVertex->nEdges == 1 ) Vec_PtrClear( vNext );
{ Vec_PtrForEachEntry( vStart, pObj, i )
pNext = p->pVerts[ pVertex->pEdges[0] ];
if ( pNext->nEdges >= MAX_LIST )
Nwk_ManGraphListDelete( p, p->pLists1 + MAX_LIST, pVertex );
else
Nwk_ManGraphListDelete( p, p->pLists1 + pNext->nEdges, pVertex );
}
else
{ {
if ( pVertex->nEdges >= MAX_LIST ) Nwk_ObjForEachFanin( pObj, pNext, k )
Nwk_ManGraphListDelete( p, p->pLists1 + MAX_LIST, pVertex ); {
else if ( !Nwk_ObjIsNode(pNext) )
Nwk_ManGraphListDelete( p, p->pLists1 + pVertex->nEdges, pVertex ); continue;
if ( Nwk_ObjIsTravIdCurrent( pNext ) )
continue;
Nwk_ObjSetTravIdCurrent( pNext );
Vec_PtrPush( vNext, pNext );
}
Nwk_ObjForEachFanout( pObj, pNext, k )
{
if ( !Nwk_ObjIsNode(pNext) )
continue;
if ( Nwk_ObjIsTravIdCurrent( pNext ) )
continue;
Nwk_ObjSetTravIdCurrent( pNext );
if ( Nwk_ObjFanoutNum(pNext) > nFanMax )
continue;
Vec_PtrPush( vNext, pNext );
}
} }
} }
/**Function************************************************************* /**Function*************************************************************
Synopsis [Prepares the graph for solving the problem.] Synopsis [Collects the circle of nodes removes from the given one.]
Description [] Description []
...@@ -540,64 +783,68 @@ static inline void Nwk_ManGraphListExtract( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex ) ...@@ -540,64 +783,68 @@ static inline void Nwk_ManGraphListExtract( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex )
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
void Nwk_ManGraphPrepare( Nwk_Grf_t * p ) void Nwk_ManCollectNonOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars )
{ {
Nwk_Edg_t * pEntry; Vec_Ptr_t * vTemp;
Nwk_Vrt_t * pVertex; Nwk_Obj_t * pObj;
int * pnEdges, Key, nBytes, i; int i, k;
// count the edges Vec_PtrClear( vCands );
pnEdges = CALLOC( int, p->nVerts ); if ( pPars->nMaxSuppSize - Nwk_ObjFaninNum(pLut) <= 1 )
for ( Key = 0; Key < p->nEdgeHash; Key++ ) return;
for ( pEntry = p->pEdgeHash[Key]; pEntry; pEntry = pEntry->pNext )
{ // collect nodes removed by this distance
// translate into vertices assert( pPars->nMaxDistance > 0 );
assert( pEntry->iNode1 < p->nObjs ); Vec_PtrClear( vStart );
assert( pEntry->iNode2 < p->nObjs ); Vec_PtrPush( vStart, pLut );
pEntry->iNode1 = p->pMapLut2Id[pEntry->iNode1]; Nwk_ManIncrementTravId( pLut->pMan );
pEntry->iNode2 = p->pMapLut2Id[pEntry->iNode2]; Nwk_ObjSetTravIdCurrent( pLut );
// count the edges for ( i = 1; i <= pPars->nMaxDistance; i++ )
assert( pEntry->iNode1 < p->nVerts );
assert( pEntry->iNode2 < p->nVerts );
pnEdges[pEntry->iNode1]++;
pnEdges[pEntry->iNode2]++;
}
// allocate the real graph
p->pMemVerts = Aig_MmFlexStart();
p->pVerts = ALLOC( Nwk_Vrt_t *, p->nVerts + 1 );
p->pVerts[0] = NULL;
for ( i = 1; i <= p->nVerts; i++ )
{ {
assert( pnEdges[i] > 0 ); Nwk_ManCollectCircle( vStart, vNext, pPars->nMaxFanout );
nBytes = sizeof(Nwk_Vrt_t) + sizeof(int) * pnEdges[i]; vTemp = vStart;
p->pVerts[i] = (Nwk_Vrt_t *)Aig_MmFlexEntryFetch( p->pMemVerts, nBytes ); vStart = vNext;
memset( p->pVerts[i], 0, nBytes ); vNext = vTemp;
p->pVerts[i]->Id = i; // collect the nodes in vStart
Vec_PtrForEachEntry( vStart, pObj, k )
Vec_PtrPush( vCands, pObj );
} }
// add edges to the real graph
for ( Key = 0; Key < p->nEdgeHash; Key++ ) // mark the TFI/TFO nodes
for ( pEntry = p->pEdgeHash[Key]; pEntry; pEntry = pEntry->pNext ) Nwk_ManIncrementTravId( pLut->pMan );
{ if ( pPars->fUseTfiTfo )
pVertex = p->pVerts[pEntry->iNode1]; Nwk_ObjSetTravIdCurrent( pLut );
pVertex->pEdges[ pVertex->nEdges++ ] = pEntry->iNode2; else
pVertex = p->pVerts[pEntry->iNode2];
pVertex->pEdges[ pVertex->nEdges++ ] = pEntry->iNode1;
}
// put vertices into the data structure
for ( i = 1; i <= p->nVerts; i++ )
{ {
assert( p->pVerts[i]->nEdges == pnEdges[i] ); Nwk_ObjSetTravIdPrevious( pLut );
Nwk_ManGraphListInsert( p, p->pVerts[i] ); Nwk_ManMarkFanins_rec( pLut, Nwk_ObjLevel(pLut) - pPars->nMaxDistance );
Nwk_ObjSetTravIdPrevious( pLut );
Nwk_ManMarkFanouts_rec( pLut, Nwk_ObjLevel(pLut) + pPars->nMaxDistance, pPars->nMaxFanout );
} }
// clean up
Aig_MmFixedStop( p->pMemEdges, 0 ); p->pMemEdges = NULL; // collect nodes satisfying the following conditions:
FREE( p->pEdgeHash ); // - they are close enough in terms of distance
p->nEdgeHash = 0; // - they are not in the TFI/TFO of the LUT
free( pnEdges ); // - they have no more than the given number of fanins
// - they have no more than the given diff in delay
k = 0;
Vec_PtrForEachEntry( vCands, pObj, i )
{
if ( Nwk_ObjIsTravIdCurrent(pObj) )
continue;
if ( Nwk_ObjFaninNum(pLut) + Nwk_ObjFaninNum(pObj) > pPars->nMaxSuppSize )
continue;
if ( Nwk_ObjLevel(pLut) - Nwk_ObjLevel(pObj) > pPars->nMaxLevelDiff ||
Nwk_ObjLevel(pObj) - Nwk_ObjLevel(pLut) > pPars->nMaxLevelDiff )
continue;
Vec_PtrWriteEntry( vCands, k++, pObj );
}
Vec_PtrShrink( vCands, k );
} }
/**Function************************************************************* /**Function*************************************************************
Synopsis [Updates the problem after pulling out one edge.] Synopsis [Count the total number of fanins.]
Description [] Description []
...@@ -606,56 +853,18 @@ void Nwk_ManGraphPrepare( Nwk_Grf_t * p ) ...@@ -606,56 +853,18 @@ void Nwk_ManGraphPrepare( Nwk_Grf_t * p )
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
void Nwk_ManGraphUpdate( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex, Nwk_Vrt_t * pNext ) int Nwk_ManCountTotalFanins( Nwk_Obj_t * pLut, Nwk_Obj_t * pCand )
{ {
Nwk_Vrt_t * pChanged; Nwk_Obj_t * pFanin;
int i, k; int i, nCounter = Nwk_ObjFaninNum(pLut);
// update neibors of pVertex Nwk_ObjForEachFanin( pCand, pFanin, i )
for ( i = 0; i < pVertex->nEdges; i++ ) nCounter += !pFanin->MarkC;
{ return nCounter;
pChanged = p->pVerts[ pVertex->pEdges[i] ];
Nwk_ManGraphListExtract( p, pChanged );
for ( k = 0; k < pChanged->nEdges; k++ )
if ( pChanged->pEdges[k] == pVertex->Id )
break;
assert( k < pChanged->nEdges );
pChanged->nEdges--;
for ( ; k < pChanged->nEdges; k++ )
pChanged->pEdges[k] = pChanged->pEdges[k+1];
if ( pChanged->nEdges > 0 )
Nwk_ManGraphListInsert( p, pChanged );
}
// update neibors of pNext
for ( i = 0; i < pNext->nEdges; i++ )
{
pChanged = p->pVerts[ pNext->pEdges[i] ];
Nwk_ManGraphListExtract( p, pChanged );
for ( k = 0; k < pChanged->nEdges; k++ )
if ( pChanged->pEdges[k] == pNext->Id )
break;
assert( k < pChanged->nEdges );
pChanged->nEdges--;
for ( ; k < pChanged->nEdges; k++ )
pChanged->pEdges[k] = pChanged->pEdges[k+1];
if ( pChanged->nEdges > 0 )
Nwk_ManGraphListInsert( p, pChanged );
}
// add to the result
if ( pVertex->Id < pNext->Id )
{
Vec_IntPush( p->vPairs, p->pMapId2Lut[pVertex->Id] );
Vec_IntPush( p->vPairs, p->pMapId2Lut[pNext->Id] );
}
else
{
Vec_IntPush( p->vPairs, p->pMapId2Lut[pNext->Id] );
Vec_IntPush( p->vPairs, p->pMapId2Lut[pVertex->Id] );
}
} }
/**Function************************************************************* /**Function*************************************************************
Synopsis [Solves the problem.] Synopsis [Collects overlapping candidates.]
Description [] Description []
...@@ -664,39 +873,45 @@ void Nwk_ManGraphUpdate( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex, Nwk_Vrt_t * pNext ) ...@@ -664,39 +873,45 @@ void Nwk_ManGraphUpdate( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex, Nwk_Vrt_t * pNext )
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
void Nwk_ManGraphSolve( Nwk_Grf_t * p ) void Nwl_ManCollectOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars )
{ {
Nwk_Vrt_t * pVertex, * pNext; Nwk_Obj_t * pFanin, * pObj;
int i, j; int i, k;
while ( 1 ) // mark fanins of pLut
Nwk_ObjForEachFanin( pLut, pFanin, i )
pFanin->MarkC = 1;
// collect the matching fanouts of each fanin of the node
Vec_PtrClear( vCands );
Nwk_ManIncrementTravId( pLut->pMan );
Nwk_ObjSetTravIdCurrent( pLut );
Nwk_ObjForEachFanin( pLut, pFanin, i )
{ {
// find the next vertext to extract if ( !Nwk_ObjIsNode(pFanin) )
for ( i = 1; i <= MAX_LIST; i++ ) continue;
if ( p->pLists1[i] ) if ( Nwk_ObjFanoutNum(pFanin) > pPars->nMaxFanout )
{ continue;
pVertex = p->pVerts[ p->pLists1[i] ]; Nwk_ObjForEachFanout( pFanin, pObj, k )
assert( pVertex->nEdges == 1 ); {
pNext = p->pVerts[ pVertex->pEdges[0] ]; if ( !Nwk_ObjIsNode(pObj) )
// update the data-structures continue;
Nwk_ManGraphUpdate( p, pVertex, pNext ); if ( Nwk_ObjIsTravIdCurrent( pObj ) )
break; continue;
} Nwk_ObjSetTravIdCurrent( pObj );
// find the next vertext to extract // check the difference in delay
for ( j = 2; j <= MAX_LIST; j++ ) if ( Nwk_ObjLevel(pLut) - Nwk_ObjLevel(pObj) > pPars->nMaxLevelDiff ||
if ( p->pLists2[j] ) Nwk_ObjLevel(pObj) - Nwk_ObjLevel(pLut) > pPars->nMaxLevelDiff )
{ continue;
pVertex = p->pVerts[ p->pLists2[j] ]; // check the total number of fanins of the node
assert( pVertex->nEdges == j || j == MAX_LIST ); if ( Nwk_ManCountTotalFanins(pLut, pObj) > pPars->nMaxSuppSize )
// update the data-structures continue;
Nwk_ManGraphUpdate( p, pVertex, pNext ); Vec_PtrPush( vCands, pObj );
break; }
}
if ( i == MAX_LIST + 1 && j == MAX_LIST + 1 )
break;
} }
// unmark fanins of pLut
Nwk_ObjForEachFanin( pLut, pFanin, i )
pFanin->MarkC = 0;
} }
/**Function************************************************************* /**Function*************************************************************
Synopsis [Performs LUT merging with parameters.] Synopsis [Performs LUT merging with parameters.]
...@@ -714,32 +929,35 @@ Vec_Int_t * Nwk_ManLutMerge( Nwk_Man_t * pNtk, Nwk_LMPars_t * pPars ) ...@@ -714,32 +929,35 @@ Vec_Int_t * Nwk_ManLutMerge( Nwk_Man_t * pNtk, Nwk_LMPars_t * pPars )
Vec_Int_t * vResult; Vec_Int_t * vResult;
Vec_Ptr_t * vStart, * vNext, * vCands1, * vCands2; Vec_Ptr_t * vStart, * vNext, * vCands1, * vCands2;
Nwk_Obj_t * pLut, * pCand; Nwk_Obj_t * pLut, * pCand;
int i, k, nVertsPre; int i, k, nVertsMax, nCands, clk = clock();
// count the number of vertices // count the number of vertices
nVertsPre = 0; nVertsMax = 0;
Nwk_ManForEachNode( pNtk, pLut, i ) Nwk_ManForEachNode( pNtk, pLut, i )
nVertsPre += (int)(Nwk_ObjFaninNum(pLut) <= pPars->nMaxLutSize); nVertsMax += (int)(Nwk_ObjFaninNum(pLut) <= pPars->nMaxLutSize);
p = Nwk_ManGraphAlloc( Nwk_ManObjNumMax(pNtk), nVertsPre ); p = Nwk_ManGraphAlloc( nVertsMax );
// create graph // create graph
vStart = Vec_PtrAlloc( 1000 ); vStart = Vec_PtrAlloc( 1000 );
vNext = Vec_PtrAlloc( 1000 ); vNext = Vec_PtrAlloc( 1000 );
vCands1 = Vec_PtrAlloc( 1000 ); vCands1 = Vec_PtrAlloc( 1000 );
vCands2 = Vec_PtrAlloc( 1000 ); vCands2 = Vec_PtrAlloc( 1000 );
nCands = 0;
Nwk_ManForEachNode( pNtk, pLut, i ) Nwk_ManForEachNode( pNtk, pLut, i )
{ {
if ( Nwk_ObjFaninNum(pLut) > pPars->nMaxLutSize ) if ( Nwk_ObjFaninNum(pLut) > pPars->nMaxLutSize )
continue; continue;
Nwl_ManCollectOverlapCands( pLut, vCands1, pPars ); Nwl_ManCollectOverlapCands( pLut, vCands1, pPars );
Nwk_ManCollectNonOverlapCands( pLut, vStart, vNext, vCands2, pPars ); if ( pPars->fUseDiffSupp )
Nwk_ManCollectNonOverlapCands( pLut, vStart, vNext, vCands2, pPars );
if ( Vec_PtrSize(vCands1) == 0 && Vec_PtrSize(vCands2) == 0 ) if ( Vec_PtrSize(vCands1) == 0 && Vec_PtrSize(vCands2) == 0 )
continue; continue;
nCands += Vec_PtrSize(vCands1) + Vec_PtrSize(vCands2);
// save candidates // save candidates
Nwk_ManGraphSetMapping( p, Nwk_ObjId(pLut) );
Vec_PtrForEachEntry( vCands1, pCand, k ) Vec_PtrForEachEntry( vCands1, pCand, k )
Nwk_ManGraphHashEdge( p, Nwk_ObjId(pLut), Nwk_ObjId(pCand) ); Nwk_ManGraphHashEdge( p, Nwk_ObjId(pLut), Nwk_ObjId(pCand) );
Vec_PtrForEachEntry( vCands2, pCand, k ) Vec_PtrForEachEntry( vCands2, pCand, k )
Nwk_ManGraphHashEdge( p, Nwk_ObjId(pLut), Nwk_ObjId(pCand) ); Nwk_ManGraphHashEdge( p, Nwk_ObjId(pLut), Nwk_ObjId(pCand) );
// print statistics about this node // print statistics about this node
if ( pPars->fVeryVerbose )
printf( "Node %6d : Fanins = %d. Fanouts = %3d. Cand1 = %3d. Cand2 = %3d.\n", printf( "Node %6d : Fanins = %d. Fanouts = %3d. Cand1 = %3d. Cand2 = %3d.\n",
Nwk_ObjId(pLut), Nwk_ObjFaninNum(pLut), Nwk_ObjFaninNum(pLut), Nwk_ObjId(pLut), Nwk_ObjFaninNum(pLut), Nwk_ObjFaninNum(pLut),
Vec_PtrSize(vCands1), Vec_PtrSize(vCands2) ); Vec_PtrSize(vCands1), Vec_PtrSize(vCands2) );
...@@ -748,9 +966,21 @@ Vec_Int_t * Nwk_ManLutMerge( Nwk_Man_t * pNtk, Nwk_LMPars_t * pPars ) ...@@ -748,9 +966,21 @@ Vec_Int_t * Nwk_ManLutMerge( Nwk_Man_t * pNtk, Nwk_LMPars_t * pPars )
Vec_PtrFree( vNext ); Vec_PtrFree( vNext );
Vec_PtrFree( vCands1 ); Vec_PtrFree( vCands1 );
Vec_PtrFree( vCands2 ); Vec_PtrFree( vCands2 );
if ( pPars->fVerbose )
{
printf( "Mergable LUTs = %6d. Total cands = %6d. ", p->nVertsMax, nCands );
PRT( "Deriving graph", clock() - clk );
}
// solve the graph problem // solve the graph problem
Nwk_ManGraphPrepare( p ); clk = clock();
Nwk_ManGraphSolve( p ); Nwk_ManGraphSolve( p );
if ( pPars->fVerbose )
{
printf( "GRAPH: Nodes = %6d. Edges = %6d. Pairs = %6d. ",
p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 );
PRT( "Solving", clock() - clk );
Nwk_ManGraphReportMemoryUsage( p );
}
vResult = p->vPairs; p->vPairs = NULL; vResult = p->vPairs; p->vPairs = NULL;
Nwk_ManGraphFree( p ); Nwk_ManGraphFree( p );
return vResult; return vResult;
......
/**CFile****************************************************************
FileName [nwkMerge.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Logic network representation.]
Synopsis [External declarations.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: nwkMerge.h,v 1.1 2008/05/14 22:13:09 wudenni Exp $]
***********************************************************************/
#ifndef __NWK_MERGE_H__
#define __NWK_MERGE_H__
#ifdef __cplusplus
extern "C" {
#endif
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
#define NWK_MAX_LIST 16
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
// the LUT merging parameters
typedef struct Nwk_LMPars_t_ Nwk_LMPars_t;
struct Nwk_LMPars_t_
{
int nMaxLutSize; // the max LUT size for merging (N=5)
int nMaxSuppSize; // the max total support size after merging (S=5)
int nMaxDistance; // the max number of nodes separating LUTs
int nMaxLevelDiff; // the max difference in levels
int nMaxFanout; // the max number of fanouts to traverse
int fUseDiffSupp; // enables the use of nodes with different support
int fUseTfiTfo; // enables the use of TFO/TFO nodes as candidates
int fVeryVerbose; // enables additional verbose output
int fVerbose; // enables verbose output
};
// edge of the graph
typedef struct Nwk_Edg_t_ Nwk_Edg_t;
struct Nwk_Edg_t_
{
int iNode1; // the first node
int iNode2; // the second node
Nwk_Edg_t * pNext; // the next edge
};
// vertex of the graph
typedef struct Nwk_Vrt_t_ Nwk_Vrt_t;
struct Nwk_Vrt_t_
{
int Id; // the vertex number
int iPrev; // the previous vertex in the list
int iNext; // the next vertex in the list
int nEdges; // the number of edges
int pEdges[0]; // the array of edges
};
// the connectivity graph
typedef struct Nwk_Grf_t_ Nwk_Grf_t;
struct Nwk_Grf_t_
{
// preliminary graph representation
int nObjs; // the number of objects
int nVertsMax; // the upper bound on the number of vertices
int nEdgeHash; // an approximate number of edges
Nwk_Edg_t ** pEdgeHash; // hash table for edges
Aig_MmFixed_t * pMemEdges; // memory for edges
// graph representation
int nEdges; // the number of edges
int nVerts; // the number of vertices
Nwk_Vrt_t ** pVerts; // the array of vertices
Aig_MmFlex_t * pMemVerts; // memory for vertices
// intermediate data
int pLists1[NWK_MAX_LIST+1]; // lists of nodes with one edge
int pLists2[NWK_MAX_LIST+1]; // lists of nodes with more than one edge
// the results of matching
Vec_Int_t * vPairs; // pairs matched in the graph
// object mappings
int * pMapLut2Id; // LUT numbers into vertex IDs
int * pMapId2Lut; // vertex IDs into LUT numbers
// other things
int nMemBytes1; // memory usage in bytes
int nMemBytes2; // memory usage in bytes
};
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
#define Nwk_GraphForEachEdge( p, pEdge, k ) \
for ( k = 0; k < p->nEdgeHash; k++ ) \
for ( pEdge = p->pEdgeHash[k]; pEdge; pEdge = pEdge->pNext )
#define Nwk_ListForEachVertex( p, List, pVrt ) \
for ( pVrt = List? p->pVerts[List] : NULL; pVrt; \
pVrt = pVrt->iNext? p->pVerts[pVrt->iNext] : NULL )
#define Nwk_VertexForEachAdjacent( p, pVrt, pNext, k ) \
for ( k = 0; (k < pVrt->nEdges) && (((pNext) = p->pVerts[pVrt->pEdges[k]]), 1); k++ )
////////////////////////////////////////////////////////////////////////
/// INLINED FUNCTIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// ITERATORS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
/*=== nwkMerge.c ==========================================================*/
extern ABC_DLL Nwk_Grf_t * Nwk_ManGraphAlloc( int nVertsMax );
extern ABC_DLL void Nwk_ManGraphFree( Nwk_Grf_t * p );
extern ABC_DLL void Nwk_ManGraphReportMemoryUsage( Nwk_Grf_t * p );
extern ABC_DLL void Nwk_ManGraphHashEdge( Nwk_Grf_t * p, int iLut1, int iLut2 );
extern ABC_DLL void Nwk_ManGraphSolve( Nwk_Grf_t * p );
extern ABC_DLL int Nwk_ManLutMergeGraphTest( char * pFileName );
#ifdef __cplusplus
}
#endif
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "mfx.h" #include "mfx.h"
#include "fra.h" #include "fra.h"
#include "saig.h" #include "saig.h"
#include "nwkMerge.h"
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
/// DECLARATIONS /// /// DECLARATIONS ///
...@@ -7578,13 +7579,15 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) ...@@ -7578,13 +7579,15 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
{ {
FILE * pOut, * pErr; FILE * pOut, * pErr;
Abc_Ntk_t * pNtk; Abc_Ntk_t * pNtk;
Abc_Ntk_t * pNtkRes; // Abc_Ntk_t * pNtkRes;
int c; int c;
int fBmc; int fBmc;
int nFrames; int nFrames;
int nLevels; int nLevels;
int fVerbose; int fVerbose;
int fVeryVerbose; int fVeryVerbose;
char * pFileName;
// extern Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk ); // extern Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk );
// extern Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk ); // extern Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk );
// extern void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk ); // extern void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk );
...@@ -7605,13 +7608,12 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) ...@@ -7605,13 +7608,12 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
extern void Abc_NtkDarTest( Abc_Ntk_t * pNtk ); extern void Abc_NtkDarTest( Abc_Ntk_t * pNtk );
pNtk = Abc_FrameReadNtk(pAbc); pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc); pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc); pErr = Abc_FrameReadErr(pAbc);
printf( "This command is temporarily disabled.\n" ); // printf( "This command is temporarily disabled.\n" );
return 0; // return 0;
// set defaults // set defaults
fVeryVerbose = 0; fVeryVerbose = 0;
...@@ -7789,6 +7791,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) ...@@ -7789,6 +7791,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
// Abc_NtkDarPartition( pNtk ); // Abc_NtkDarPartition( pNtk );
//Abc_NtkDarTest( pNtk ); //Abc_NtkDarTest( pNtk );
/*
// pNtkRes = Abc_NtkDarRetimeStep( pNtk, 0 ); // pNtkRes = Abc_NtkDarRetimeStep( pNtk, 0 );
pNtkRes = Abc_NtkDarHaigRecord( pNtk, 3, 3000, 0, 0, 0, 0 ); pNtkRes = Abc_NtkDarHaigRecord( pNtk, 3, 3000, 0, 0, 0, 0 );
if ( pNtkRes == NULL ) if ( pNtkRes == NULL )
...@@ -7798,12 +7801,17 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) ...@@ -7798,12 +7801,17 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
} }
// replace the current network // replace the current network
Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
*/
if ( argc != globalUtilOptind + 1 )
goto usage;
pFileName = argv[globalUtilOptind];
Nwk_ManLutMergeGraphTest( pFileName );
return 0; return 0;
usage: usage:
fprintf( pErr, "usage: test [-bvwh]\n" ); fprintf( pErr, "usage: test [-h] <file_name>\n" );
fprintf( pErr, "\t testbench for new procedures\n" ); fprintf( pErr, "\t testbench for new procedures\n" );
fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); // fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-w : toggle printing very verbose information [default = %s]\n", fVeryVerbose? "yes": "no" ); // fprintf( pErr, "\t-w : toggle printing very verbose information [default = %s]\n", fVeryVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n"); fprintf( pErr, "\t-h : print the command usage\n");
return 1; return 1;
} }
...@@ -17321,21 +17329,6 @@ usage: ...@@ -17321,21 +17329,6 @@ usage:
} }
//#include "nwk.h"
// the LUT merging parameters
typedef struct Nwk_LMPars_t_ Nwk_LMPars_t;
struct Nwk_LMPars_t_
{
int nMaxLutSize; // the max LUT size for merging (N=5)
int nMaxSuppSize; // the max total support size after merging (S=5)
int nMaxDistance; // the max number of nodes separating LUTs
int nMaxLevelDiff; // the max difference in levels
int nMaxFanout; // the max number of fanouts to traverse
int fUseTfiTfo; // enables the use of TFO/TFO nodes as candidates
int fVeryVerbose; // enables additional verbose output
int fVerbose; // enables verbose output
};
/**Function************************************************************* /**Function*************************************************************
...@@ -17353,11 +17346,6 @@ int Abc_CommandAbc8Merge( Abc_Frame_t * pAbc, int argc, char ** argv ) ...@@ -17353,11 +17346,6 @@ int Abc_CommandAbc8Merge( Abc_Frame_t * pAbc, int argc, char ** argv )
Nwk_LMPars_t Pars, * pPars = &Pars; Nwk_LMPars_t Pars, * pPars = &Pars;
Vec_Int_t * vResult; Vec_Int_t * vResult;
int c; int c;
int fUseLutLib = 0;
int Percentage = 100;
int Degree = 5;
int fVerbose = 0;
int fVeryVerbose = 0;
extern Vec_Int_t * Nwk_ManLutMerge( void * pNtk, Nwk_LMPars_t * pPars ); extern Vec_Int_t * Nwk_ManLutMerge( void * pNtk, Nwk_LMPars_t * pPars );
// set defaults // set defaults
...@@ -17367,11 +17355,12 @@ int Abc_CommandAbc8Merge( Abc_Frame_t * pAbc, int argc, char ** argv ) ...@@ -17367,11 +17355,12 @@ int Abc_CommandAbc8Merge( Abc_Frame_t * pAbc, int argc, char ** argv )
pPars->nMaxDistance = 3; // the max number of nodes separating LUTs pPars->nMaxDistance = 3; // the max number of nodes separating LUTs
pPars->nMaxLevelDiff = 2; // the max difference in levels pPars->nMaxLevelDiff = 2; // the max difference in levels
pPars->nMaxFanout = 100; // the max number of fanouts to traverse pPars->nMaxFanout = 100; // the max number of fanouts to traverse
pPars->fUseDiffSupp = 0; // enables the use of nodes with different support
pPars->fUseTfiTfo = 0; // enables the use of TFO/TFO nodes as candidates pPars->fUseTfiTfo = 0; // enables the use of TFO/TFO nodes as candidates
pPars->fVeryVerbose = 0; // enables additional verbose output pPars->fVeryVerbose = 0; // enables additional verbose output
pPars->fVerbose = 1; // enables verbose output pPars->fVerbose = 1; // enables verbose output
Extra_UtilGetoptReset(); Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "NSDLFcvwh" ) ) != EOF ) while ( ( c = Extra_UtilGetopt( argc, argv, "NSDLFscvwh" ) ) != EOF )
{ {
switch ( c ) switch ( c )
{ {
...@@ -17430,6 +17419,9 @@ int Abc_CommandAbc8Merge( Abc_Frame_t * pAbc, int argc, char ** argv ) ...@@ -17430,6 +17419,9 @@ int Abc_CommandAbc8Merge( Abc_Frame_t * pAbc, int argc, char ** argv )
if ( pPars->nMaxFanout < 2 ) if ( pPars->nMaxFanout < 2 )
goto usage; goto usage;
break; break;
case 's':
pPars->fUseDiffSupp ^= 1;
break;
case 'c': case 'c':
pPars->fUseTfiTfo ^= 1; pPars->fUseTfiTfo ^= 1;
break; break;
...@@ -17456,13 +17448,14 @@ int Abc_CommandAbc8Merge( Abc_Frame_t * pAbc, int argc, char ** argv ) ...@@ -17456,13 +17448,14 @@ int Abc_CommandAbc8Merge( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0; return 0;
usage: usage:
fprintf( stdout, "usage: *merge [-NSDLF num] [-cwvh]\n" ); fprintf( stdout, "usage: *merge [-NSDLF num] [-scwvh]\n" );
fprintf( stdout, "\t creates pairs of topologically-related LUTs\n" ); fprintf( stdout, "\t creates pairs of topologically-related LUTs\n" );
fprintf( stdout, "\t-N <num> : the max LUT size for merging (1 < num) [default = %d]\n", pPars->nMaxLutSize ); fprintf( stdout, "\t-N <num> : the max LUT size for merging (1 < num) [default = %d]\n", pPars->nMaxLutSize );
fprintf( stdout, "\t-S <num> : the max total support size after merging (1 < num) [default = %d]\n", pPars->nMaxSuppSize ); fprintf( stdout, "\t-S <num> : the max total support size after merging (1 < num) [default = %d]\n", pPars->nMaxSuppSize );
fprintf( stdout, "\t-D <num> : the max distance in terms of LUTs (0 < num) [default = %d]\n", pPars->nMaxDistance ); fprintf( stdout, "\t-D <num> : the max distance in terms of LUTs (0 < num) [default = %d]\n", pPars->nMaxDistance );
fprintf( stdout, "\t-L <num> : the max difference in levels (0 <= num) [default = %d]\n", pPars->nMaxLevelDiff ); fprintf( stdout, "\t-L <num> : the max difference in levels (0 <= num) [default = %d]\n", pPars->nMaxLevelDiff );
fprintf( stdout, "\t-F <num> : the max number of fanouts to stop traversal (0 < num) [default = %d]\n", pPars->nMaxFanout ); fprintf( stdout, "\t-F <num> : the max number of fanouts to stop traversal (0 < num) [default = %d]\n", pPars->nMaxFanout );
fprintf( stdout, "\t-s : toggle the use of nodes without support overlap [default = %s]\n", pPars->fUseDiffSupp? "yes" : "no" );
fprintf( stdout, "\t-c : toggle the use of TFI/TFO nodes as candidates [default = %s]\n", pPars->fUseTfiTfo? "yes" : "no" ); fprintf( stdout, "\t-c : toggle the use of TFI/TFO nodes as candidates [default = %s]\n", pPars->fUseTfiTfo? "yes" : "no" );
fprintf( stdout, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); fprintf( stdout, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
fprintf( stdout, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); fprintf( stdout, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" );
......
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