blob: 681625aca6bc913c510fb5c63de2076a6280a53d [file] [log] [blame]
/**CFile****************************************************************
FileName [mapperCut.c]
PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
Synopsis [Generic technology mapping engine.]
Author [MVSIS Group]
Affiliation [UC Berkeley]
Date [Ver. 2.0. Started - June 1, 2004.]
Revision [$Id: mapperCut.c,v 1.12 2005/02/28 05:34:27 alanmi Exp $]
***********************************************************************/
#include "mapperInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// the largest number of cuts considered
#define MAP_CUTS_MAX_COMPUTE 1000
// the largest number of cuts used
#define MAP_CUTS_MAX_USE 250
// temporary hash table to store the cuts
typedef struct Map_CutTableStrutct_t Map_CutTable_t;
struct Map_CutTableStrutct_t
{
Map_Cut_t ** pBins; // the table used for linear probing
int nBins; // the size of the table
int * pCuts; // the array of cuts currently stored
int nCuts; // the number of cuts currently stored
Map_Cut_t ** pArray; // the temporary array of cuts
Map_Cut_t ** pCuts1; // the temporary array of cuts
Map_Cut_t ** pCuts2; // the temporary array of cuts
};
// primes used to compute the hash key
static int s_HashPrimes[10] = { 109, 499, 557, 619, 631, 709, 797, 881, 907, 991 };
static Map_Cut_t * Map_CutCompute( Map_Man_t * p, Map_CutTable_t * pTable, Map_Node_t * pNode );
static void Map_CutFilter( Map_Man_t * p, Map_Node_t * pNode );
static Map_Cut_t * Map_CutMergeLists( Map_Man_t * p, Map_CutTable_t * pTable, Map_Cut_t * pList1, Map_Cut_t * pList2, int fComp1, int fComp2 );
static int Map_CutMergeTwo( Map_Cut_t * pCut1, Map_Cut_t * pCut2, Map_Node_t * ppNodes[], int nNodesMax );
static Map_Cut_t * Map_CutUnionLists( Map_Cut_t * pList1, Map_Cut_t * pList2 );
static int Map_CutBelongsToList( Map_Cut_t * pList, Map_Node_t * ppNodes[], int nNodes );
static void Map_CutListPrint( Map_Man_t * pMan, Map_Node_t * pRoot );
static void Map_CutListPrint2( Map_Man_t * pMan, Map_Node_t * pRoot );
static void Map_CutPrint_( Map_Man_t * pMan, Map_Cut_t * pCut, Map_Node_t * pRoot );
static Map_CutTable_t * Map_CutTableStart( Map_Man_t * pMan );
static void Map_CutTableStop( Map_CutTable_t * p );
static unsigned Map_CutTableHash( Map_Node_t * ppNodes[], int nNodes );
static int Map_CutTableLookup( Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes );
static Map_Cut_t * Map_CutTableConsider( Map_Man_t * pMan, Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes );
static void Map_CutTableRestart( Map_CutTable_t * p );
static Map_Cut_t * Map_CutSortCuts( Map_Man_t * pMan, Map_CutTable_t * p, Map_Cut_t * pList );
static int Map_CutList2Array( Map_Cut_t ** pArray, Map_Cut_t * pList );
static Map_Cut_t * Map_CutArray2List( Map_Cut_t ** pArray, int nCuts );
static unsigned Map_CutComputeTruth( Map_Man_t * p, Map_Cut_t * pCut, Map_Cut_t * pTemp0, Map_Cut_t * pTemp1, int fComp0, int fComp1 );
// iterator through all the cuts of the list
#define Map_ListForEachCut( pList, pCut ) \
for ( pCut = pList; \
pCut; \
pCut = pCut->pNext )
#define Map_ListForEachCutSafe( pList, pCut, pCut2 ) \
for ( pCut = pList, \
pCut2 = pCut? pCut->pNext: NULL; \
pCut; \
pCut = pCut2, \
pCut2 = pCut? pCut->pNext: NULL )
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Counts all the cuts.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Map_MappingCountAllCuts( Map_Man_t * pMan )
{
Map_Node_t * pNode;
Map_Cut_t * pCut;
int i, nCuts;
// int nCuts55 = 0, nCuts5x = 0, nCuts4x = 0, nCuts3x = 0;
// int pCounts[7] = {0};
nCuts = 0;
for ( i = 0; i < pMan->nBins; i++ )
for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext )
for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext )
if ( pCut->nLeaves > 1 ) // skip the elementary cuts
{
nCuts++;
/*
if ( Map_CutRegular(pCut->pOne)->nLeaves == 5 && Map_CutRegular(pCut->pTwo)->nLeaves == 5 )
nCuts55++;
if ( Map_CutRegular(pCut->pOne)->nLeaves == 5 || Map_CutRegular(pCut->pTwo)->nLeaves == 5 )
nCuts5x++;
else if ( Map_CutRegular(pCut->pOne)->nLeaves == 4 || Map_CutRegular(pCut->pTwo)->nLeaves == 4 )
nCuts4x++;
else if ( Map_CutRegular(pCut->pOne)->nLeaves == 3 || Map_CutRegular(pCut->pTwo)->nLeaves == 3 )
nCuts3x++;
*/
// pCounts[ Map_CutRegular(pCut->pOne)->nLeaves ]++;
// pCounts[ Map_CutRegular(pCut->pTwo)->nLeaves ]++;
}
// printf( "Total cuts = %6d. 55 = %6d. 5x = %6d. 4x = %6d. 3x = %6d.\n", nCuts, nCuts55, nCuts5x, nCuts4x, nCuts3x );
// printf( "Total cuts = %6d. 6= %6d. 5= %6d. 4= %6d. 3= %6d. 2= %6d. 1= %6d.\n",
// nCuts, pCounts[6], pCounts[5], pCounts[4], pCounts[3], pCounts[2], pCounts[1] );
return nCuts;
}
/**Function*************************************************************
Synopsis [Computes the cuts for each node in the object graph.]
Description [The cuts are computed in one sweep over the mapping graph.
First, the elementary cuts, which include the node itself, are assigned
to the PI nodes. The internal nodes are considered in the DFS order.
Each node is two-input AND-gate. So to compute the cuts at a node, we
need to merge the sets of cuts of its two predecessors. The merged set
contains only unique cuts with the number of inputs equal to k or less.
Finally, the elementary cut, composed of the node itself, is added to
the set of cuts for the node.
This procedure is pretty fast for 5-feasible cuts, but it dramatically
slows down on some "dense" networks when computing 6-feasible cuts.
The problem is that there are too many cuts in this case. We should
think how to heuristically trim the number of cuts in such cases,
to have reasonable runtime.]
SideEffects []
SeeAlso []
***********************************************************************/
void Map_MappingCutsInput( Map_Man_t * p, Map_Node_t * pNode )
{
Map_Cut_t * pCut;
assert( Map_NodeIsVar(pNode) || Map_NodeIsBuf(pNode) );
pCut = Map_CutAlloc( p );
pCut->nLeaves = 1;
pCut->ppLeaves[0] = pNode;
pNode->pCuts = pCut;
pNode->pCutBest[0] = NULL; // negative polarity is not mapped
pNode->pCutBest[1] = pCut; // positive polarity is a trivial cut
pCut->uTruth = 0xAAAAAAAA; // the first variable "1010"
pCut->M[0].AreaFlow = 0.0;
pCut->M[1].AreaFlow = 0.0;
}
void Map_MappingCuts( Map_Man_t * p )
{
ProgressBar * pProgress;
Map_CutTable_t * pTable;
Map_Node_t * pNode;
int nCuts, nNodes, i;
abctime clk = Abc_Clock();
// set the elementary cuts for the PI variables
assert( p->nVarsMax > 1 && p->nVarsMax < 7 );
for ( i = 0; i < p->nInputs; i++ )
Map_MappingCutsInput( p, p->pInputs[i] );
// compute the cuts for the internal nodes
nNodes = p->vMapObjs->nSize;
pProgress = Extra_ProgressBarStart( stdout, nNodes );
pTable = Map_CutTableStart( p );
for ( i = 0; i < nNodes; i++ )
{
pNode = p->vMapObjs->pArray[i];
if ( Map_NodeIsBuf(pNode) )
Map_MappingCutsInput( p, pNode );
else if ( Map_NodeIsAnd(pNode) )
Map_CutCompute( p, pTable, pNode );
else continue;
Extra_ProgressBarUpdate( pProgress, i, "Cuts ..." );
}
Extra_ProgressBarStop( pProgress );
Map_CutTableStop( pTable );
// report the stats
if ( p->fVerbose )
{
nCuts = Map_MappingCountAllCuts(p);
printf( "Nodes = %6d. Total %d-feasible cuts = %10d. Per node = %.1f. ",
p->nNodes, p->nVarsMax, nCuts, ((float)nCuts)/p->nNodes );
ABC_PRT( "Time", Abc_Clock() - clk );
}
// print the cuts for the first primary output
// Map_CutListPrint( p, Map_Regular(p->pOutputs[0]) );
}
/**Function*************************************************************
Synopsis [Computes the cuts for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Map_Cut_t * Map_CutCompute( Map_Man_t * p, Map_CutTable_t * pTable, Map_Node_t * pNode )
{
Map_Node_t * pTemp;
Map_Cut_t * pList, * pList1, * pList2;
Map_Cut_t * pCut;
// if the cuts are computed return them
if ( pNode->pCuts )
return pNode->pCuts;
// compute the cuts for the children
pList1 = Map_Regular(pNode->p1)->pCuts;
pList2 = Map_Regular(pNode->p2)->pCuts;
// merge the lists
pList = Map_CutMergeLists( p, pTable, pList1, pList2,
Map_IsComplement(pNode->p1), Map_IsComplement(pNode->p2) );
// if there are functionally equivalent nodes, union them with this list
assert( pList );
// only add to the list of cuts if the node is a representative one
if ( pNode->pRepr == NULL )
{
for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE )
{
assert( pTemp->pCuts );
pList = Map_CutUnionLists( pList, pTemp->pCuts );
assert( pTemp->pCuts );
pList = Map_CutSortCuts( p, pTable, pList );
}
}
// add the new cut
pCut = Map_CutAlloc( p );
pCut->nLeaves = 1;
pCut->ppLeaves[0] = pNode;
pCut->uTruth = 0xAAAAAAAA;
// append (it is important that the elementary cut is appended first)
pCut->pNext = pList;
// set at the node
pNode->pCuts = pCut;
// remove the dominated cuts
Map_CutFilter( p, pNode );
// set the phase correctly
if ( pNode->pRepr && Map_NodeComparePhase(pNode, pNode->pRepr) )
{
Map_ListForEachCut( pNode->pCuts, pCut )
pCut->Phase = 1;
}
/*
{
int i, Counter = 0;;
for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
for ( i = 0; i < pCut->nLeaves; i++ )
Counter += (pCut->ppLeaves[i]->Level >= pNode->Level);
// if ( Counter )
// printf( " %d", Counter );
}
*/
return pCut;
}
/**Function*************************************************************
Synopsis [Filter the cuts using dominance.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Map_CutFilter( Map_Man_t * p, Map_Node_t * pNode )
{
Map_Cut_t * pTemp, * pPrev, * pCut, * pCut2;
int i, k, Counter;
Counter = 0;
pPrev = pNode->pCuts;
Map_ListForEachCutSafe( pNode->pCuts->pNext, pCut, pCut2 )
{
// go through all the previous cuts up to pCut
for ( pTemp = pNode->pCuts->pNext; pTemp != pCut; pTemp = pTemp->pNext )
{
// check if every node in pTemp is contained in pCut
for ( i = 0; i < pTemp->nLeaves; i++ )
{
for ( k = 0; k < pCut->nLeaves; k++ )
if ( pTemp->ppLeaves[i] == pCut->ppLeaves[k] )
break;
if ( k == pCut->nLeaves ) // node i in pTemp is not contained in pCut
break;
}
if ( i == pTemp->nLeaves ) // every node in pTemp is contained in pCut
{
Counter++;
break;
}
}
if ( pTemp != pCut ) // pTemp contain pCut
{
pPrev->pNext = pCut->pNext; // skip pCut
// recycle pCut
Map_CutFree( p, pCut );
}
else
pPrev = pCut;
}
// printf( "Dominated = %3d. \n", Counter );
}
/**Function*************************************************************
Synopsis [Merges two lists of cuts.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Map_Cut_t * Map_CutMergeLists( Map_Man_t * p, Map_CutTable_t * pTable,
Map_Cut_t * pList1, Map_Cut_t * pList2, int fComp1, int fComp2 )
{
Map_Node_t * ppNodes[6];
Map_Cut_t * pListNew, ** ppListNew, * pLists[7] = { NULL };
Map_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2;
int nNodes, Counter, i;
Map_Cut_t ** ppArray1, ** ppArray2, ** ppArray3;
int nCuts1, nCuts2, nCuts3, k, fComp3;
ppArray1 = pTable->pCuts1;
ppArray2 = pTable->pCuts2;
nCuts1 = Map_CutList2Array( ppArray1, pList1 );
nCuts2 = Map_CutList2Array( ppArray2, pList2 );
// swap the lists based on their length
if ( nCuts1 > nCuts2 )
{
ppArray3 = ppArray1;
ppArray1 = ppArray2;
ppArray2 = ppArray3;
nCuts3 = nCuts1;
nCuts1 = nCuts2;
nCuts2 = nCuts3;
fComp3 = fComp1;
fComp1 = fComp2;
fComp2 = fComp3;
}
// pList1 is shorter or equal length compared to pList2
// prepare the manager for the cut computation
Map_CutTableRestart( pTable );
// go through the cut pairs
Counter = 0;
// for ( pTemp1 = pList1; pTemp1; pTemp1 = fPivot1? NULL: pTemp1->pNext )
// for ( pTemp2 = pList2; pTemp2; pTemp2 = fPivot2? NULL: pTemp2->pNext )
for ( i = 0; i < nCuts1; i++ )
{
for ( k = 0; k <= i; k++ )
{
pTemp1 = ppArray1[i];
pTemp2 = ppArray2[k];
if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax )
{
if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] )
continue;
if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] )
continue;
}
// check if k-feasible cut exists
nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
if ( nNodes == 0 )
continue;
// consider the cut for possible addition to the set of new cuts
pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes );
if ( pCut == NULL )
continue;
// add data to the cut
pCut->pOne = Map_CutNotCond( pTemp1, fComp1 );
pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 );
// if ( p->nVarsMax == 5 )
// pCut->uTruth = Map_CutComputeTruth( p, pCut, pTemp1, pTemp2, fComp1, fComp2 );
// add it to the corresponding list
pCut->pNext = pLists[(int)pCut->nLeaves];
pLists[(int)pCut->nLeaves] = pCut;
// count this cut and quit if limit is reached
Counter++;
if ( Counter == MAP_CUTS_MAX_COMPUTE )
goto QUITS;
}
for ( k = 0; k < i; k++ )
{
pTemp1 = ppArray1[k];
pTemp2 = ppArray2[i];
if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax )
{
if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] )
continue;
if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] )
continue;
}
// check if k-feasible cut exists
nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
if ( nNodes == 0 )
continue;
// consider the cut for possible addition to the set of new cuts
pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes );
if ( pCut == NULL )
continue;
// add data to the cut
pCut->pOne = Map_CutNotCond( pTemp1, fComp1 );
pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 );
// if ( p->nVarsMax == 5 )
// pCut->uTruth = Map_CutComputeTruth( p, pCut, pTemp1, pTemp2, fComp1, fComp2 );
// add it to the corresponding list
pCut->pNext = pLists[(int)pCut->nLeaves];
pLists[(int)pCut->nLeaves] = pCut;
// count this cut and quit if limit is reached
Counter++;
if ( Counter == MAP_CUTS_MAX_COMPUTE )
goto QUITS;
}
}
// consider the rest of them
for ( i = nCuts1; i < nCuts2; i++ )
for ( k = 0; k < nCuts1; k++ )
{
pTemp1 = ppArray1[k];
pTemp2 = ppArray2[i];
if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax )
{
if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] )
continue;
if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] )
continue;
}
// check if k-feasible cut exists
nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
if ( nNodes == 0 )
continue;
// consider the cut for possible addition to the set of new cuts
pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes );
if ( pCut == NULL )
continue;
// add data to the cut
pCut->pOne = Map_CutNotCond( pTemp1, fComp1 );
pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 );
// if ( p->nVarsMax == 5 )
// pCut->uTruth = Map_CutComputeTruth( p, pCut, pTemp1, pTemp2, fComp1, fComp2 );
// add it to the corresponding list
pCut->pNext = pLists[(int)pCut->nLeaves];
pLists[(int)pCut->nLeaves] = pCut;
// count this cut and quit if limit is reached
Counter++;
if ( Counter == MAP_CUTS_MAX_COMPUTE )
goto QUITS;
}
QUITS :
// combine all the lists into one
pListNew = NULL;
ppListNew = &pListNew;
for ( i = 1; i <= p->nVarsMax; i++ )
{
if ( pLists[i] == NULL )
continue;
// find the last entry
for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut;
pPrev = pCut, pCut = pCut->pNext );
// connect these lists
*ppListNew = pLists[i];
ppListNew = &pPrev->pNext;
}
*ppListNew = NULL;
// soft the cuts by arrival times and use only the first MAP_CUTS_MAX_USE
pListNew = Map_CutSortCuts( p, pTable, pListNew );
return pListNew;
}
/**Function*************************************************************
Synopsis [Merges two lists of cuts.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Map_Cut_t * Map_CutMergeLists2( Map_Man_t * p, Map_CutTable_t * pTable,
Map_Cut_t * pList1, Map_Cut_t * pList2, int fComp1, int fComp2 )
{
Map_Node_t * ppNodes[6];
Map_Cut_t * pListNew, ** ppListNew, * pLists[7] = { NULL };
Map_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2;
int nNodes, Counter, i;
// prepare the manager for the cut computation
Map_CutTableRestart( pTable );
// go through the cut pairs
Counter = 0;
for ( pTemp1 = pList1; pTemp1; pTemp1 = pTemp1->pNext )
for ( pTemp2 = pList2; pTemp2; pTemp2 = pTemp2->pNext )
{
// check if k-feasible cut exists
nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
if ( nNodes == 0 )
continue;
// consider the cut for possible addition to the set of new cuts
pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes );
if ( pCut == NULL )
continue;
// add data to the cut
pCut->pOne = Map_CutNotCond( pTemp1, fComp1 );
pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 );
// add it to the corresponding list
pCut->pNext = pLists[(int)pCut->nLeaves];
pLists[(int)pCut->nLeaves] = pCut;
// count this cut and quit if limit is reached
Counter++;
if ( Counter == MAP_CUTS_MAX_COMPUTE )
goto QUITS;
}
QUITS :
// combine all the lists into one
pListNew = NULL;
ppListNew = &pListNew;
for ( i = 1; i <= p->nVarsMax; i++ )
{
if ( pLists[i] == NULL )
continue;
// find the last entry
for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut;
pPrev = pCut, pCut = pCut->pNext );
// connect these lists
*ppListNew = pLists[i];
ppListNew = &pPrev->pNext;
}
*ppListNew = NULL;
// soft the cuts by arrival times and use only the first MAP_CUTS_MAX_USE
pListNew = Map_CutSortCuts( p, pTable, pListNew );
return pListNew;
}
/**Function*************************************************************
Synopsis [Merges two cuts.]
Description [Returns the number of nodes in the resulting cut, or 0 if the
cut is infeasible. Returns the resulting nodes in the array ppNodes[].]
SideEffects []
SeeAlso []
***********************************************************************/
int Map_CutMergeTwo( Map_Cut_t * pCut1, Map_Cut_t * pCut2, Map_Node_t * ppNodes[], int nNodesMax )
{
Map_Node_t * pNodeTemp;
int nTotal, i, k, min, fMismatch;
// check the special case when at least of the cuts is the largest
if ( pCut1->nLeaves == nNodesMax )
{
if ( pCut2->nLeaves == nNodesMax )
{
// return 0 if the cuts are different
for ( i = 0; i < nNodesMax; i++ )
if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i] )
return 0;
// return nNodesMax if they are the same
for ( i = 0; i < nNodesMax; i++ )
ppNodes[i] = pCut1->ppLeaves[i];
return nNodesMax;
}
else if ( pCut2->nLeaves == nNodesMax - 1 )
{
// return 0 if the cuts are different
fMismatch = 0;
for ( i = 0; i < nNodesMax; i++ )
if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i - fMismatch] )
{
if ( fMismatch == 1 )
return 0;
fMismatch = 1;
}
// return nNodesMax if they are the same
for ( i = 0; i < nNodesMax; i++ )
ppNodes[i] = pCut1->ppLeaves[i];
return nNodesMax;
}
}
else if ( pCut1->nLeaves == nNodesMax - 1 && pCut2->nLeaves == nNodesMax )
{
// return 0 if the cuts are different
fMismatch = 0;
for ( i = 0; i < nNodesMax; i++ )
if ( pCut1->ppLeaves[i - fMismatch] != pCut2->ppLeaves[i] )
{
if ( fMismatch == 1 )
return 0;
fMismatch = 1;
}
// return nNodesMax if they are the same
for ( i = 0; i < nNodesMax; i++ )
ppNodes[i] = pCut2->ppLeaves[i];
return nNodesMax;
}
// count the number of unique entries in pCut2
nTotal = pCut1->nLeaves;
for ( i = 0; i < pCut2->nLeaves; i++ )
{
// try to find this entry among the leaves of pCut1
for ( k = 0; k < pCut1->nLeaves; k++ )
if ( pCut2->ppLeaves[i] == pCut1->ppLeaves[k] )
break;
if ( k < pCut1->nLeaves ) // found
continue;
// we found a new entry to add
if ( nTotal == nNodesMax )
return 0;
ppNodes[nTotal++] = pCut2->ppLeaves[i];
}
// we know that the feasible cut exists
// add the starting entries
for ( k = 0; k < pCut1->nLeaves; k++ )
ppNodes[k] = pCut1->ppLeaves[k];
// selection-sort the entries
for ( i = 0; i < nTotal - 1; i++ )
{
min = i;
for ( k = i+1; k < nTotal; k++ )
// if ( ppNodes[k] < ppNodes[min] ) // reported bug fix (non-determinism!)
if ( ppNodes[k]->Num < ppNodes[min]->Num )
min = k;
pNodeTemp = ppNodes[i];
ppNodes[i] = ppNodes[min];
ppNodes[min] = pNodeTemp;
}
return nTotal;
}
/**Function*************************************************************
Synopsis [Computes the union of the two lists of cuts.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Map_Cut_t * Map_CutUnionLists( Map_Cut_t * pList1, Map_Cut_t * pList2 )
{
Map_Cut_t * pTemp, * pRoot;
// find the last cut in the first list
pRoot = pList1;
Map_ListForEachCut( pList1, pTemp )
pRoot = pTemp;
// attach the non-trival part of the second cut to the end of the first
assert( pRoot->pNext == NULL );
pRoot->pNext = pList2->pNext;
pList2->pNext = NULL;
return pList1;
}
/**Function*************************************************************
Synopsis [Checks whether the given cut belongs to the list.]
Description [This procedure takes most of the runtime in the cut
computation.]
SideEffects []
SeeAlso []
***********************************************************************/
int Map_CutBelongsToList( Map_Cut_t * pList, Map_Node_t * ppNodes[], int nNodes )
{
Map_Cut_t * pTemp;
int i;
for ( pTemp = pList; pTemp; pTemp = pTemp->pNext )
{
for ( i = 0; i < nNodes; i++ )
if ( pTemp->ppLeaves[i] != ppNodes[i] )
break;
if ( i == nNodes )
return 1;
}
return 0;
}
/**Function*************************************************************
Synopsis [Prints the cuts in the list.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Map_CutListPrint( Map_Man_t * pMan, Map_Node_t * pRoot )
{
Map_Cut_t * pTemp;
int Counter;
for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ )
{
printf( "%2d : ", Counter + 1 );
Map_CutPrint_( pMan, pTemp, pRoot );
}
}
/**Function*************************************************************
Synopsis [Prints the cuts in the list.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Map_CutListPrint2( Map_Man_t * pMan, Map_Node_t * pRoot )
{
Map_Cut_t * pTemp;
int Counter;
for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ )
{
printf( "%2d : ", Counter + 1 );
Map_CutPrint_( pMan, pTemp, pRoot );
}
}
/**Function*************************************************************
Synopsis [Prints the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Map_CutPrint_( Map_Man_t * pMan, Map_Cut_t * pCut, Map_Node_t * pRoot )
{
int i;
printf( "(%3d) {", pRoot->Num );
for ( i = 0; i < pMan->nVarsMax; i++ )
if ( pCut->ppLeaves[i] )
printf( " %3d", pCut->ppLeaves[i]->Num );
printf( " }\n" );
}
/**Function*************************************************************
Synopsis [Starts the hash table to canonicize cuts.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Map_CutTable_t * Map_CutTableStart( Map_Man_t * pMan )
{
Map_CutTable_t * p;
// allocate the table
p = ABC_ALLOC( Map_CutTable_t, 1 );
memset( p, 0, sizeof(Map_CutTable_t) );
p->nBins = Abc_PrimeCudd( 10 * MAP_CUTS_MAX_COMPUTE );
p->pBins = ABC_ALLOC( Map_Cut_t *, p->nBins );
memset( p->pBins, 0, sizeof(Map_Cut_t *) * p->nBins );
p->pCuts = ABC_ALLOC( int, 2 * MAP_CUTS_MAX_COMPUTE );
p->pArray = ABC_ALLOC( Map_Cut_t *, 2 * MAP_CUTS_MAX_COMPUTE );
p->pCuts1 = ABC_ALLOC( Map_Cut_t *, 2 * MAP_CUTS_MAX_COMPUTE );
p->pCuts2 = ABC_ALLOC( Map_Cut_t *, 2 * MAP_CUTS_MAX_COMPUTE );
return p;
}
/**Function*************************************************************
Synopsis [Stops the hash table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Map_CutTableStop( Map_CutTable_t * p )
{
ABC_FREE( p->pCuts1 );
ABC_FREE( p->pCuts2 );
ABC_FREE( p->pArray );
ABC_FREE( p->pBins );
ABC_FREE( p->pCuts );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Computes the hash value of the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
unsigned Map_CutTableHash( Map_Node_t * ppNodes[], int nNodes )
{
unsigned uRes;
int i;
uRes = 0;
for ( i = 0; i < nNodes; i++ )
uRes += s_HashPrimes[i] * ppNodes[i]->Num;
return uRes;
}
/**Function*************************************************************
Synopsis [Looks up the table for the available cut.]
Description [Returns -1 if the same cut is found. Returns the index
of the cell where the cut should be added, if it does not exist.]
SideEffects []
SeeAlso []
***********************************************************************/
int Map_CutTableLookup( Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes )
{
Map_Cut_t * pCut;
unsigned Key;
int b, i;
Key = Map_CutTableHash(ppNodes, nNodes) % p->nBins;
for ( b = Key; p->pBins[b]; b = (b+1) % p->nBins )
{
pCut = p->pBins[b];
if ( pCut->nLeaves != nNodes )
continue;
for ( i = 0; i < nNodes; i++ )
if ( pCut->ppLeaves[i] != ppNodes[i] )
break;
if ( i == nNodes )
return -1;
}
return b;
}
/**Function*************************************************************
Synopsis [Starts the hash table to canonicize cuts.]
Description [Considers addition of the cut to the hash table.]
SideEffects []
SeeAlso []
***********************************************************************/
Map_Cut_t * Map_CutTableConsider( Map_Man_t * pMan, Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes )
{
Map_Cut_t * pCut;
int Place, i;
// abctime clk;
// check the cut
Place = Map_CutTableLookup( p, ppNodes, nNodes );
if ( Place == -1 )
return NULL;
assert( nNodes > 0 );
// create the new cut
//clk = Abc_Clock();
pCut = Map_CutAlloc( pMan );
//pMan->time1 += Abc_Clock() - clk;
pCut->nLeaves = nNodes;
for ( i = 0; i < nNodes; i++ )
pCut->ppLeaves[i] = ppNodes[i];
// add the cut to the table
assert( p->pBins[Place] == NULL );
p->pBins[Place] = pCut;
// add the cut to the new list
p->pCuts[ p->nCuts++ ] = Place;
return pCut;
}
/**Function*************************************************************
Synopsis [Prepares the table to be used with other cuts.]
Description [Restarts the table by cleaning the info about cuts stored
when the previous node was considered.]
SideEffects []
SeeAlso []
***********************************************************************/
void Map_CutTableRestart( Map_CutTable_t * p )
{
int i;
for ( i = 0; i < p->nCuts; i++ )
{
assert( p->pBins[ p->pCuts[i] ] );
p->pBins[ p->pCuts[i] ] = NULL;
}
p->nCuts = 0;
}
/**Function*************************************************************
Synopsis [Compares the cuts by the number of leaves and then by delay.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Map_CutSortCutsCompare( Map_Cut_t ** pC1, Map_Cut_t ** pC2 )
{
if ( (*pC1)->nLeaves < (*pC2)->nLeaves )
return -1;
if ( (*pC1)->nLeaves > (*pC2)->nLeaves )
return 1;
return 0;
}
/**Function*************************************************************
Synopsis [Sorts the cuts by average arrival time.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Map_Cut_t * Map_CutSortCuts( Map_Man_t * pMan, Map_CutTable_t * p, Map_Cut_t * pList )
{
Map_Cut_t * pListNew;
int nCuts, i;
// abctime clk;
// move the cuts from the list into the array
nCuts = Map_CutList2Array( p->pCuts1, pList );
assert( nCuts <= MAP_CUTS_MAX_COMPUTE );
// sort the cuts
//clk = Abc_Clock();
qsort( (void *)p->pCuts1, nCuts, sizeof(Map_Cut_t *),
(int (*)(const void *, const void *)) Map_CutSortCutsCompare );
//pMan->time2 += Abc_Clock() - clk;
// move them back into the list
if ( nCuts > MAP_CUTS_MAX_USE - 1 )
{
// free the remaining cuts
for ( i = MAP_CUTS_MAX_USE - 1; i < nCuts; i++ )
Extra_MmFixedEntryRecycle( pMan->mmCuts, (char *)p->pCuts1[i] );
// update the number of cuts
nCuts = MAP_CUTS_MAX_USE - 1;
}
pListNew = Map_CutArray2List( p->pCuts1, nCuts );
return pListNew;
}
/**Function*************************************************************
Synopsis [Moves the nodes from the list into the array.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Map_CutList2Array( Map_Cut_t ** pArray, Map_Cut_t * pList )
{
int i;
for ( i = 0; pList; pList = pList->pNext, i++ )
pArray[i] = pList;
return i;
}
/**Function*************************************************************
Synopsis [Moves the nodes from the array into the list.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Map_Cut_t * Map_CutArray2List( Map_Cut_t ** pArray, int nCuts )
{
Map_Cut_t * pListNew, ** ppListNew;
int i;
pListNew = NULL;
ppListNew = &pListNew;
for ( i = 0; i < nCuts; i++ )
{
// connect these lists
*ppListNew = pArray[i];
ppListNew = &pArray[i]->pNext;
}
//printf( "\n" );
*ppListNew = NULL;
return pListNew;
}
/**Function*************************************************************
Synopsis [Computes the truth table of the 5-input cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
unsigned Map_CutComputeTruth( Map_Man_t * p, Map_Cut_t * pCut, Map_Cut_t * pTemp0, Map_Cut_t * pTemp1, int fComp0, int fComp1 )
{
static unsigned ** pPerms53 = NULL;
static unsigned ** pPerms54 = NULL;
unsigned uPhase, uTruth, uTruth0, uTruth1;
int i, k;
if ( pPerms53 == NULL )
{
pPerms53 = (unsigned **)Extra_TruthPerm53();
pPerms54 = (unsigned **)Extra_TruthPerm54();
}
// find the mapping from the old nodes to the new
if ( pTemp0->nLeaves == pCut->nLeaves )
uTruth0 = pTemp0->uTruth;
else
{
assert( pTemp0->nLeaves < pCut->nLeaves );
uPhase = 0;
for ( i = 0; i < (int)pTemp0->nLeaves; i++ )
{
for ( k = 0; k < pCut->nLeaves; k++ )
if ( pTemp0->ppLeaves[i] == pCut->ppLeaves[k] )
break;
uPhase |= (1 << k);
}
assert( uPhase < 32 );
if ( pTemp0->nLeaves == 4 )
{
if ( uPhase == 31-16 ) // 01111
uTruth0 = pTemp0->uTruth;
else if ( uPhase == 31-8 ) // 10111
uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][0];
else if ( uPhase == 31-4 ) // 11011
uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][1];
else if ( uPhase == 31-2 ) // 11101
uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][2];
else if ( uPhase == 31-1 ) // 11110
uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][3];
else
assert( 0 );
}
else
uTruth0 = pPerms53[pTemp0->uTruth & 0xFF][uPhase];
}
uTruth0 = fComp0? ~uTruth0: uTruth0;
// find the mapping from the old nodes to the new
if ( pTemp1->nLeaves == pCut->nLeaves )
uTruth1 = pTemp1->uTruth;
else
{
assert( pTemp1->nLeaves < pCut->nLeaves );
uPhase = 0;
for ( i = 0; i < (int)pTemp1->nLeaves; i++ )
{
for ( k = 0; k < pCut->nLeaves; k++ )
if ( pTemp1->ppLeaves[i] == pCut->ppLeaves[k] )
break;
uPhase |= (1 << k);
}
assert( uPhase < 32 );
if ( pTemp1->nLeaves == 4 )
{
if ( uPhase == 31-16 ) // 01111
uTruth1 = pTemp1->uTruth;
else if ( uPhase == 31-8 ) // 10111
uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][0];
else if ( uPhase == 31-4 ) // 11011
uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][1];
else if ( uPhase == 31-2 ) // 11101
uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][2];
else if ( uPhase == 31-1 ) // 11110
uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][3];
else
assert( 0 );
}
else
uTruth1 = pPerms53[pTemp1->uTruth & 0xFF][uPhase];
}
uTruth1 = fComp1? ~uTruth1: uTruth1;
uTruth = uTruth0 & uTruth1;
return uTruth;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END