mirror of https://github.com/YosysHQ/abc.git
609 lines
17 KiB
C
609 lines
17 KiB
C
/**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
|
|
|