| /**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 |
| |