blob: da55eb82f57ad1c70eb8792a44f1002ea9e4c5ed [file] [log] [blame]
/**CFile****************************************************************
FileName [fxuSelect.c]
PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
Synopsis [Procedures to select the best divisor/complement pair.]
Author [MVSIS Group]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - February 1, 2003.]
Revision [$Id: fxuSelect.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
***********************************************************************/
#include "fxuInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
#define MAX_SIZE_LOOKAHEAD 20
static int Fxu_MatrixFindComplement( Fxu_Matrix * p, int iVar );
static Fxu_Double * Fxu_MatrixFindComplementSingle( Fxu_Matrix * p, Fxu_Single * pSingle );
static Fxu_Single * Fxu_MatrixFindComplementDouble2( Fxu_Matrix * p, Fxu_Double * pDouble );
static Fxu_Double * Fxu_MatrixFindComplementDouble4( Fxu_Matrix * p, Fxu_Double * pDouble );
Fxu_Double * Fxu_MatrixFindDouble( Fxu_Matrix * p,
int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 );
void Fxu_MatrixGetDoubleVars( Fxu_Matrix * p, Fxu_Double * pDouble,
int piVarsC1[], int piVarsC2[], int * pnVarsC1, int * pnVarsC2 );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Selects the best pair (Single,Double) and returns their weight.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fxu_Select( Fxu_Matrix * p, Fxu_Single ** ppSingle, Fxu_Double ** ppDouble )
{
// the top entries
Fxu_Single * pSingles[MAX_SIZE_LOOKAHEAD] = {0};
Fxu_Double * pDoubles[MAX_SIZE_LOOKAHEAD] = {0};
// the complements
Fxu_Double * pSCompl[MAX_SIZE_LOOKAHEAD] = {0};
Fxu_Single * pDComplS[MAX_SIZE_LOOKAHEAD] = {0};
Fxu_Double * pDComplD[MAX_SIZE_LOOKAHEAD] = {0};
Fxu_Pair * pPair;
int nSingles;
int nDoubles;
int i;
int WeightBest;
int WeightCur;
int iNum, fBestS;
// collect the top entries from the queues
for ( nSingles = 0; nSingles < MAX_SIZE_LOOKAHEAD; nSingles++ )
{
pSingles[nSingles] = Fxu_HeapSingleGetMax( p->pHeapSingle );
if ( pSingles[nSingles] == NULL )
break;
}
// put them back into the queue
for ( i = 0; i < nSingles; i++ )
if ( pSingles[i] )
Fxu_HeapSingleInsert( p->pHeapSingle, pSingles[i] );
// the same for doubles
// collect the top entries from the queues
for ( nDoubles = 0; nDoubles < MAX_SIZE_LOOKAHEAD; nDoubles++ )
{
pDoubles[nDoubles] = Fxu_HeapDoubleGetMax( p->pHeapDouble );
if ( pDoubles[nDoubles] == NULL )
break;
}
// put them back into the queue
for ( i = 0; i < nDoubles; i++ )
if ( pDoubles[i] )
Fxu_HeapDoubleInsert( p->pHeapDouble, pDoubles[i] );
// for each single, find the complement double (if any)
for ( i = 0; i < nSingles; i++ )
if ( pSingles[i] )
pSCompl[i] = Fxu_MatrixFindComplementSingle( p, pSingles[i] );
// for each double, find the complement single or double (if any)
for ( i = 0; i < nDoubles; i++ )
if ( pDoubles[i] )
{
pPair = pDoubles[i]->lPairs.pHead;
if ( pPair->nLits1 == 1 && pPair->nLits2 == 1 )
{
pDComplS[i] = Fxu_MatrixFindComplementDouble2( p, pDoubles[i] );
pDComplD[i] = NULL;
}
// else if ( pPair->nLits1 == 2 && pPair->nLits2 == 2 )
// {
// pDComplS[i] = NULL;
// pDComplD[i] = Fxu_MatrixFindComplementDouble4( p, pDoubles[i] );
// }
else
{
pDComplS[i] = NULL;
pDComplD[i] = NULL;
}
}
// select the best pair
WeightBest = -1;
for ( i = 0; i < nSingles; i++ )
{
WeightCur = pSingles[i]->Weight;
if ( pSCompl[i] )
{
// add the weight of the double
WeightCur += pSCompl[i]->Weight;
// there is no need to implement this double, so...
pPair = pSCompl[i]->lPairs.pHead;
WeightCur += pPair->nLits1 + pPair->nLits2;
}
if ( WeightBest < WeightCur )
{
WeightBest = WeightCur;
*ppSingle = pSingles[i];
*ppDouble = pSCompl[i];
fBestS = 1;
iNum = i;
}
}
for ( i = 0; i < nDoubles; i++ )
{
WeightCur = pDoubles[i]->Weight;
if ( pDComplS[i] )
{
// add the weight of the single
WeightCur += pDComplS[i]->Weight;
// there is no need to implement this double, so...
pPair = pDoubles[i]->lPairs.pHead;
WeightCur += pPair->nLits1 + pPair->nLits2;
}
if ( WeightBest < WeightCur )
{
WeightBest = WeightCur;
*ppSingle = pDComplS[i];
*ppDouble = pDoubles[i];
fBestS = 0;
iNum = i;
}
}
/*
// print the statistics
printf( "\n" );
for ( i = 0; i < nSingles; i++ )
{
printf( "Single #%d: Weight = %3d. ", i, pSingles[i]->Weight );
printf( "Compl: " );
if ( pSCompl[i] == NULL )
printf( "None." );
else
printf( "D Weight = %3d Sum = %3d",
pSCompl[i]->Weight, pSCompl[i]->Weight + pSingles[i]->Weight );
printf( "\n" );
}
printf( "\n" );
for ( i = 0; i < nDoubles; i++ )
{
printf( "Double #%d: Weight = %3d. ", i, pDoubles[i]->Weight );
printf( "Compl: " );
if ( pDComplS[i] == NULL && pDComplD[i] == NULL )
printf( "None." );
else if ( pDComplS[i] )
printf( "S Weight = %3d Sum = %3d",
pDComplS[i]->Weight, pDComplS[i]->Weight + pDoubles[i]->Weight );
else if ( pDComplD[i] )
printf( "D Weight = %3d Sum = %3d",
pDComplD[i]->Weight, pDComplD[i]->Weight + pDoubles[i]->Weight );
printf( "\n" );
}
if ( WeightBest == -1 )
printf( "Selected NONE\n" );
else
{
printf( "Selected = %s. ", fBestS? "S": "D" );
printf( "Number = %d. ", iNum );
printf( "Weight = %d.\n", WeightBest );
}
printf( "\n" );
*/
return WeightBest;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Fxu_Double * Fxu_MatrixFindComplementSingle( Fxu_Matrix * p, Fxu_Single * pSingle )
{
// int * pValue2Node = p->pValue2Node;
int iVar1, iVar2;
int iVar1C, iVar2C;
// get the variables of this single div
iVar1 = pSingle->pVar1->iVar;
iVar2 = pSingle->pVar2->iVar;
iVar1C = Fxu_MatrixFindComplement( p, iVar1 );
iVar2C = Fxu_MatrixFindComplement( p, iVar2 );
if ( iVar1C == -1 || iVar2C == -1 )
return NULL;
assert( iVar1C < iVar2C );
return Fxu_MatrixFindDouble( p, &iVar1C, &iVar2C, 1, 1 );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Fxu_Single * Fxu_MatrixFindComplementDouble2( Fxu_Matrix * p, Fxu_Double * pDouble )
{
// int * pValue2Node = p->pValue2Node;
int piVarsC1[10], piVarsC2[10];
int nVarsC1, nVarsC2;
int iVar1, iVar2, iVarTemp;
int iVar1C, iVar2C;
Fxu_Single * pSingle;
// get the variables of this double div
Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 );
assert( nVarsC1 == 1 );
assert( nVarsC2 == 1 );
iVar1 = piVarsC1[0];
iVar2 = piVarsC2[0];
assert( iVar1 < iVar2 );
iVar1C = Fxu_MatrixFindComplement( p, iVar1 );
iVar2C = Fxu_MatrixFindComplement( p, iVar2 );
if ( iVar1C == -1 || iVar2C == -1 )
return NULL;
// go through the queque and find this one
// assert( iVar1C < iVar2C );
if ( iVar1C > iVar2C )
{
iVarTemp = iVar1C;
iVar1C = iVar2C;
iVar2C = iVarTemp;
}
Fxu_MatrixForEachSingle( p, pSingle )
if ( pSingle->pVar1->iVar == iVar1C && pSingle->pVar2->iVar == iVar2C )
return pSingle;
return NULL;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Fxu_Double * Fxu_MatrixFindComplementDouble4( Fxu_Matrix * p, Fxu_Double * pDouble )
{
// int * pValue2Node = p->pValue2Node;
int piVarsC1[10], piVarsC2[10];
int nVarsC1, nVarsC2;
int iVar11, iVar12, iVar21, iVar22;
int iVar11C, iVar12C, iVar21C, iVar22C;
int RetValue;
// get the variables of this double div
Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 );
assert( nVarsC1 == 2 && nVarsC2 == 2 );
iVar11 = piVarsC1[0];
iVar12 = piVarsC1[1];
iVar21 = piVarsC2[0];
iVar22 = piVarsC2[1];
assert( iVar11 < iVar21 );
iVar11C = Fxu_MatrixFindComplement( p, iVar11 );
iVar12C = Fxu_MatrixFindComplement( p, iVar12 );
iVar21C = Fxu_MatrixFindComplement( p, iVar21 );
iVar22C = Fxu_MatrixFindComplement( p, iVar22 );
if ( iVar11C == -1 || iVar12C == -1 || iVar21C == -1 || iVar22C == -1 )
return NULL;
if ( iVar11C != iVar21 || iVar12C != iVar22 ||
iVar21C != iVar11 || iVar22C != iVar12 )
return NULL;
// a'b' + ab => a'b + ab'
// a'b + ab' => a'b' + ab
// swap the second pair in each cube
RetValue = piVarsC1[1];
piVarsC1[1] = piVarsC2[1];
piVarsC2[1] = RetValue;
return Fxu_MatrixFindDouble( p, piVarsC1, piVarsC2, 2, 2 );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fxu_MatrixFindComplement( Fxu_Matrix * p, int iVar )
{
return iVar ^ 1;
/*
// int * pValue2Node = p->pValue2Node;
int iVarC;
int iNode;
int Beg, End;
// get the nodes
iNode = pValue2Node[iVar];
// get the first node with the same var
for ( Beg = iVar; Beg >= 0; Beg-- )
if ( pValue2Node[Beg] != iNode )
{
Beg++;
break;
}
// get the last node with the same var
for ( End = iVar; ; End++ )
if ( pValue2Node[End] != iNode )
{
End--;
break;
}
// if one of the vars is not binary, quit
if ( End - Beg > 1 )
return -1;
// get the complements
if ( iVar == Beg )
iVarC = End;
else if ( iVar == End )
iVarC = Beg;
else
{
assert( 0 );
}
return iVarC;
*/
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fxu_MatrixGetDoubleVars( Fxu_Matrix * p, Fxu_Double * pDouble,
int piVarsC1[], int piVarsC2[], int * pnVarsC1, int * pnVarsC2 )
{
Fxu_Pair * pPair;
Fxu_Lit * pLit1, * pLit2;
int nLits1, nLits2;
// get the first pair
pPair = pDouble->lPairs.pHead;
// init the parameters
nLits1 = 0;
nLits2 = 0;
pLit1 = pPair->pCube1->lLits.pHead;
pLit2 = pPair->pCube2->lLits.pHead;
while ( 1 )
{
if ( pLit1 && pLit2 )
{
if ( pLit1->iVar == pLit2->iVar )
{ // ensure cube-free
pLit1 = pLit1->pHNext;
pLit2 = pLit2->pHNext;
}
else if ( pLit1->iVar < pLit2->iVar )
{
piVarsC1[nLits1++] = pLit1->iVar;
pLit1 = pLit1->pHNext;
}
else
{
piVarsC2[nLits2++] = pLit2->iVar;
pLit2 = pLit2->pHNext;
}
}
else if ( pLit1 && !pLit2 )
{
piVarsC1[nLits1++] = pLit1->iVar;
pLit1 = pLit1->pHNext;
}
else if ( !pLit1 && pLit2 )
{
piVarsC2[nLits2++] = pLit2->iVar;
pLit2 = pLit2->pHNext;
}
else
break;
}
*pnVarsC1 = nLits1;
*pnVarsC2 = nLits2;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Fxu_Double * Fxu_MatrixFindDouble( Fxu_Matrix * p,
int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 )
{
int piVarsC1_[100], piVarsC2_[100];
int nVarsC1_, nVarsC2_, i;
Fxu_Double * pDouble;
Fxu_Pair * pPair;
unsigned Key;
assert( nVarsC1 > 0 );
assert( nVarsC2 > 0 );
assert( piVarsC1[0] < piVarsC2[0] );
// get the hash key
Key = Fxu_PairHashKeyArray( p, piVarsC1, piVarsC2, nVarsC1, nVarsC2 );
// check if the divisor for this pair already exists
Key %= p->nTableSize;
Fxu_TableForEachDouble( p, Key, pDouble )
{
pPair = pDouble->lPairs.pHead;
if ( pPair->nLits1 != nVarsC1 )
continue;
if ( pPair->nLits2 != nVarsC2 )
continue;
// get the cubes of this divisor
Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1_, piVarsC2_, &nVarsC1_, &nVarsC2_ );
// compare lits of the first cube
for ( i = 0; i < nVarsC1; i++ )
if ( piVarsC1[i] != piVarsC1_[i] )
break;
if ( i != nVarsC1 )
continue;
// compare lits of the second cube
for ( i = 0; i < nVarsC2; i++ )
if ( piVarsC2[i] != piVarsC2_[i] )
break;
if ( i != nVarsC2 )
continue;
return pDouble;
}
return NULL;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fxu_SelectSCD( Fxu_Matrix * p, int WeightLimit, Fxu_Var ** ppVar1, Fxu_Var ** ppVar2 )
{
// int * pValue2Node = p->pValue2Node;
Fxu_Var * pVar1;
Fxu_Var * pVar2, * pVarTemp;
Fxu_Lit * pLitV, * pLitH;
int Coin;
int CounterAll;
int CounterTest;
int WeightCur;
int WeightBest;
CounterAll = 0;
CounterTest = 0;
WeightBest = -10;
// iterate through the columns in the matrix
Fxu_MatrixForEachVariable( p, pVar1 )
{
// start collecting the affected vars
Fxu_MatrixRingVarsStart( p );
// go through all the literals of this variable
for ( pLitV = pVar1->lLits.pHead; pLitV; pLitV = pLitV->pVNext )
{
// for this literal, go through all the horizontal literals
for ( pLitH = pLitV->pHNext; pLitH; pLitH = pLitH->pHNext )
{
// get another variable
pVar2 = pLitH->pVar;
CounterAll++;
// skip the var if it is already used
if ( pVar2->pOrder )
continue;
// skip the var if it belongs to the same node
// if ( pValue2Node[pVar1->iVar] == pValue2Node[pVar2->iVar] )
// continue;
// collect the var
Fxu_MatrixRingVarsAdd( p, pVar2 );
}
}
// stop collecting the selected vars
Fxu_MatrixRingVarsStop( p );
// iterate through the selected vars
Fxu_MatrixForEachVarInRing( p, pVar2 )
{
CounterTest++;
// count the coincidence
Coin = Fxu_SingleCountCoincidence( p, pVar1, pVar2 );
assert( Coin > 0 );
// get the new weight
WeightCur = Coin - 2;
// compare the weights
if ( WeightBest < WeightCur )
{
WeightBest = WeightCur;
*ppVar1 = pVar1;
*ppVar2 = pVar2;
}
}
// unmark the vars
Fxu_MatrixForEachVarInRingSafe( p, pVar2, pVarTemp )
pVar2->pOrder = NULL;
Fxu_MatrixRingVarsReset( p );
}
// if ( WeightBest == WeightLimit )
// return -1;
return WeightBest;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END