| /**CFile**************************************************************** |
| |
| FileName [dauNonDsd.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [DAG-aware unmapping.] |
| |
| Synopsis [] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: dauNonDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "dauInt.h" |
| #include "misc/util/utilTruth.h" |
| #include "misc/extra/extra.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Checks decomposability with given variable set.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Dau_DecCheckSetTop5( word * p, int nVars, int nVarsF, int nVarsB, int nVarsS, int uMaskS, int * pSched, word * pDec, word * pComp ) |
| { |
| word Cof[2][64], Value; |
| word MaskFF = (((word)1) << (1 << nVarsF)) - 1; |
| int ShiftF = 6 - nVarsF, MaskF = (1 << ShiftF) - 1; |
| int pVarsS[16], pVarsB[16]; |
| int nMints = (1 << nVarsB); |
| int nMintsB = (1 <<(nVarsB-nVarsS)); |
| int nMintsS = (1 << nVarsS); |
| int s, b, v, m, Mint, MintB, MintS; |
| assert( nVars == nVarsB + nVarsF ); |
| assert( nVars <= 16 ); |
| assert( nVarsS <= 6 ); |
| assert( nVarsF >= 1 && nVarsF <= 5 ); |
| // collect bound/shared variables |
| for ( s = b = v = 0; v < nVarsB; v++ ) |
| if ( (uMaskS >> v) & 1 ) |
| pVarsB[v] = -1, pVarsS[v] = s++; |
| else |
| pVarsS[v] = -1, pVarsB[v] = b++; |
| assert( s == nVarsS ); |
| assert( b == nVarsB-nVarsS ); |
| // clean minterm storage |
| for ( s = 0; s < nMintsS; s++ ) |
| Cof[0][s] = Cof[1][s] = ~(word)0; |
| // iterate through bound set minters |
| for ( MintS = MintB = Mint = m = 0; m < nMints; m++ ) |
| { |
| // find minterm value |
| Value = (p[Mint>>ShiftF] >> ((Mint&MaskF)<<nVarsF)) & MaskFF; |
| // check if this cof already appeared |
| if ( !~Cof[0][MintS] || Cof[0][MintS] == Value ) |
| Cof[0][MintS] = Value; |
| else if ( !~Cof[1][MintS] || Cof[1][MintS] == Value ) |
| { |
| Cof[1][MintS] = Value; |
| if ( pDec ) |
| { |
| int iMintB = MintS * nMintsB + MintB; |
| pDec[iMintB>>6] |= (((word)1)<<(iMintB & 63)); |
| } |
| } |
| else |
| return 0; |
| // find next minterm |
| v = pSched[m]; |
| Mint ^= (1 << v); |
| if ( (uMaskS >> v) & 1 ) // shared variable |
| MintS ^= (1 << pVarsS[v]); |
| else |
| MintB ^= (1 << pVarsB[v]); |
| } |
| // create composition function |
| if ( pComp ) |
| { |
| for ( s = 0; s < nMintsS; s++ ) |
| { |
| pComp[s>>ShiftF] |= (Cof[0][s] << ((s&MaskF) << nVarsF)); |
| if ( ~Cof[1][s] ) |
| pComp[(s+nMintsS)>>ShiftF] |= (Cof[1][s] << (((s+nMintsS)&MaskF) << nVarsF)); |
| else |
| pComp[(s+nMintsS)>>ShiftF] |= (Cof[0][s] << (((s+nMintsS)&MaskF) << nVarsF)); |
| } |
| if ( nVarsF + nVarsS + 1 < 6 ) |
| pComp[0] = Abc_Tt6Stretch( pComp[0], nVarsF + nVarsS + 1 ); |
| } |
| if ( pDec && nVarsB < 6 ) |
| pDec[0] = Abc_Tt6Stretch( pDec[0], nVarsB ); |
| return 1; |
| } |
| int Dau_DecCheckSetTop6( word * p, int nVars, int nVarsF, int nVarsB, int nVarsS, int uMaskS, int * pSched, word * pDec, word * pComp ) |
| { |
| word * Cof[2][64]; |
| int nWordsF = Abc_TtWordNum(nVarsF); |
| int pVarsS[16], pVarsB[16]; |
| int nMints = (1 << nVarsB); |
| int nMintsB = (1 <<(nVarsB-nVarsS)); |
| int nMintsS = (1 << nVarsS); |
| int s, b, v, m, Mint, MintB, MintS; |
| assert( nVars == nVarsB + nVarsF ); |
| assert( nVars <= 16 ); |
| assert( nVarsS <= 6 ); |
| assert( nVarsF >= 6 ); |
| // collect bound/shared variables |
| for ( s = b = v = 0; v < nVarsB; v++ ) |
| if ( (uMaskS >> v) & 1 ) |
| pVarsB[v] = -1, pVarsS[v] = s++; |
| else |
| pVarsS[v] = -1, pVarsB[v] = b++; |
| assert( s == nVarsS ); |
| assert( b == nVarsB-nVarsS ); |
| // clean minterm storage |
| for ( s = 0; s < nMintsS; s++ ) |
| Cof[0][s] = Cof[1][s] = NULL; |
| // iterate through bound set minters |
| for ( MintS = MintB = Mint = m = 0; m < nMints; m++ ) |
| { |
| // check if this cof already appeared |
| if ( !Cof[0][MintS] || !memcmp(Cof[0][MintS], p + Mint * nWordsF, sizeof(word) * nWordsF) ) |
| Cof[0][MintS] = p + Mint * nWordsF; |
| else if ( !Cof[1][MintS] || !memcmp(Cof[1][MintS], p + Mint * nWordsF, sizeof(word) * nWordsF) ) |
| { |
| Cof[1][MintS] = p + Mint * nWordsF; |
| if ( pDec ) |
| { |
| int iMintB = MintS * nMintsB + MintB; |
| pDec[iMintB>>6] |= (((word)1)<<(iMintB & 63)); |
| } |
| } |
| else |
| return 0; |
| // find next minterm |
| v = pSched[m]; |
| Mint ^= (1 << v); |
| if ( (uMaskS >> v) & 1 ) // shared variable |
| MintS ^= (1 << pVarsS[v]); |
| else |
| MintB ^= (1 << pVarsB[v]); |
| } |
| // create composition function |
| if ( pComp ) |
| { |
| for ( s = 0; s < nMintsS; s++ ) |
| { |
| memcpy( pComp + s * nWordsF, Cof[0][s], sizeof(word) * nWordsF ); |
| if ( Cof[1][s] ) |
| memcpy( pComp + (s+nMintsS) * nWordsF, Cof[1][s], sizeof(word) * nWordsF ); |
| else |
| memcpy( pComp + (s+nMintsS) * nWordsF, Cof[0][s], sizeof(word) * nWordsF ); |
| } |
| } |
| if ( pDec && nVarsB < 6 ) |
| pDec[0] = Abc_Tt6Stretch( pDec[0], nVarsB ); |
| return 1; |
| } |
| static inline int Dau_DecCheckSetTop( word * p, int nVars, int nVarsF, int nVarsB, int nVarsS, int uMaskS, int * pSched, word * pDec, word * pComp ) |
| { |
| if ( nVarsF < 6 ) |
| return Dau_DecCheckSetTop5( p, nVars, nVarsF, nVarsB, nVarsS, uMaskS, pSched, pDec, pComp ); |
| else |
| return Dau_DecCheckSetTop6( p, nVars, nVarsF, nVarsB, nVarsS, uMaskS, pSched, pDec, pComp ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Checks decomposability with given BS variables.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline void Dau_DecGetMinterm( word * p, int g, int nVarsS, int uMaskAll ) |
| { |
| int m, c, v; |
| for ( m = c = v = 0; v < nVarsS; v++ ) |
| if ( !((uMaskAll >> v) & 1) ) // not shared bound set variable |
| { |
| if ( (g >> v) & 1 ) |
| m |= (1 << c); |
| c++; |
| } |
| assert( c >= 2 ); |
| p[m>>6] |= (((word)1)<<(m & 63)); |
| } |
| static inline int Dau_DecCheckSet5( word * p, int nVars, int nVarsF, int uMaskAll, int uMaskValue, word * pCof0, word * pCof1, word * pDec ) |
| { |
| int fFound0 = 0, fFound1 = 0; |
| int g, gMax = (1 << (nVars - nVarsF)); |
| int Shift = 6 - nVarsF, Mask = (1 << Shift) - 1; |
| word Mask2 = (((word)1) << (1 << nVarsF)) - 1; |
| word Cof0 = 0, Cof1 = 0, Value; |
| assert( nVarsF >= 1 && nVarsF <= 5 ); |
| if ( pDec ) *pDec = 0; |
| for ( g = 0; g < gMax; g++ ) |
| if ( (g & uMaskAll) == uMaskValue ) // this minterm g matches shared variable minterm uMaskValue |
| { |
| Value = (p[g>>Shift] >> ((g&Mask)<<nVarsF)) & Mask2; |
| if ( !fFound0 ) |
| Cof0 = Value, fFound0 = 1; |
| else if ( Cof0 == Value ) |
| continue; |
| else if ( !fFound1 ) |
| { |
| Cof1 = Value, fFound1 = 1; |
| if ( pDec ) Dau_DecGetMinterm( pDec, g, nVars-nVarsF, uMaskAll ); |
| } |
| else if ( Cof1 == Value ) |
| { |
| if ( pDec ) Dau_DecGetMinterm( pDec, g, nVars-nVarsF, uMaskAll ); |
| continue; |
| } |
| else |
| return 0; |
| } |
| if ( pCof0 ) |
| { |
| assert( fFound0 ); |
| Cof1 = fFound1 ? Cof1 : Cof0; |
| *pCof0 = Abc_Tt6Stretch( Cof0, nVarsF ); |
| *pCof1 = Abc_Tt6Stretch( Cof1, nVarsF ); |
| } |
| return 1; |
| } |
| static inline int Dau_DecCheckSet6( word * p, int nVars, int nVarsF, int uMaskAll, int uMaskValue, word * pCof0, word * pCof1, word * pDec ) |
| { |
| int fFound0 = 0, fFound1 = 0; |
| int g, gMax = (1 << (nVars - nVarsF)); |
| int nWords = Abc_TtWordNum(nVarsF); |
| word * Cof0 = NULL, * Cof1 = NULL; |
| assert( nVarsF >= 6 && nVarsF <= nVars - 2 ); |
| if ( pDec ) *pDec = 0; |
| for ( g = 0; g < gMax; g++ ) |
| if ( (g & uMaskAll) == uMaskValue ) |
| { |
| if ( !fFound0 ) |
| Cof0 = p + g * nWords, fFound0 = 1; |
| else if ( !memcmp(Cof0, p + g * nWords, sizeof(word) * nWords) ) |
| continue; |
| else if ( !fFound1 ) |
| { |
| Cof1 = p + g * nWords, fFound1 = 1; |
| if ( pDec ) Dau_DecGetMinterm( pDec, g, nVars-nVarsF, uMaskAll ); |
| } |
| else if ( !memcmp(Cof1, p + g * nWords, sizeof(word) * nWords) ) |
| { |
| if ( pDec ) Dau_DecGetMinterm( pDec, g, nVars-nVarsF, uMaskAll ); |
| continue; |
| } |
| else |
| return 0; |
| } |
| if ( pCof0 ) |
| { |
| assert( fFound0 ); |
| Cof1 = fFound1 ? Cof1 : Cof0; |
| memcpy( pCof0, Cof0, sizeof(word) * nWords ); |
| memcpy( pCof1, Cof1, sizeof(word) * nWords ); |
| } |
| return 1; |
| } |
| static inline int Dau_DecCheckSetAny( word * p, int nVars, int nVarsF, int uMaskAll, int uMaskValue, word * pCof0, word * pCof1, word * pDec ) |
| { |
| assert( nVarsF >= 1 && nVarsF <= nVars - 2 ); |
| if ( nVarsF < 6 ) |
| return Dau_DecCheckSet5( p, nVars, nVarsF, uMaskAll, uMaskValue, pCof0, pCof1, pDec ); |
| else |
| return Dau_DecCheckSet6( p, nVars, nVarsF, uMaskAll, uMaskValue, pCof0, pCof1, pDec ); |
| } |
| int Dau_DecCheckSetTopOld( word * p, int nVars, int nVarsF, int nVarsB, int nVarsS, int maskS, word ** pCof0, word ** pCof1, word ** pDec ) |
| { |
| int i, pVarsS[16]; |
| int v, m, mMax = (1 << nVarsS), uMaskValue; |
| assert( nVars >= 3 && nVars <= 16 ); |
| assert( nVars == nVarsF + nVarsB ); |
| assert( nVarsF >= 1 && nVarsF <= nVars - 2 ); |
| assert( nVarsB >= 2 && nVarsB <= nVars - 1 ); |
| assert( nVarsS >= 0 && nVarsS <= nVarsB - 2 ); |
| if ( nVarsS == 0 ) |
| return Dau_DecCheckSetAny( p, nVars, nVarsF, 0, 0, pCof0? pCof0[0] : 0, pCof1? pCof1[0] : 0, pDec? pDec[0] : 0 ); |
| // collect shared variables |
| assert( maskS > 0 && maskS < (1 << nVarsB) ); |
| for ( i = 0, v = 0; v < nVarsB; v++ ) |
| if ( (maskS >> v) & 1 ) |
| pVarsS[i++] = v; |
| assert( i == nVarsS ); |
| // go through shared set minterms |
| for ( m = 0; m < mMax; m++ ) |
| { |
| // generate share set mask |
| uMaskValue = 0; |
| for ( v = 0; v < nVarsS; v++ ) |
| if ( (m >> v) & 1 ) |
| uMaskValue |= (1 << pVarsS[v]); |
| assert( (maskS & uMaskValue) == uMaskValue ); |
| // check decomposition |
| if ( !Dau_DecCheckSetAny( p, nVars, nVarsF, maskS, uMaskValue, pCof0? pCof0[m] : 0, pCof1? pCof1[m] : 0, pDec? pDec[m] : 0 ) ) |
| return 0; |
| } |
| return 1; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Variable sets.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline unsigned Dau_DecCreateSet( int * pVarsB, int sizeB, int maskS ) |
| { |
| unsigned uSet = 0; int v; |
| for ( v = 0; v < sizeB; v++ ) |
| { |
| uSet |= (1 << (pVarsB[v] << 1)); |
| if ( (maskS >> v) & 1 ) |
| uSet |= (1 << ((pVarsB[v] << 1)+1)); |
| } |
| return uSet; |
| } |
| static inline int Dau_DecSetHas01( unsigned Mask ) |
| { |
| return (Mask & ((~Mask) >> 1) & 0x55555555); |
| } |
| static inline int Dau_DecSetIsContained( Vec_Int_t * vSets, unsigned New ) |
| // Old=abcD contains New=abcDE |
| // Old=abcD contains New=abCD |
| { |
| unsigned Old; |
| int i, Entry; |
| Vec_IntForEachEntry( vSets, Entry, i ) |
| { |
| Old = (unsigned)Entry; |
| if ( (Old & ~New) == 0 && !Dau_DecSetHas01(~Old & New)) |
| return 1; |
| } |
| return 0; |
| } |
| void Dau_DecSortSet( unsigned set, int nVars, int * pnUnique, int * pnShared, int * pnFree ) |
| { |
| int v; |
| int nUnique = 0, nShared = 0, nFree = 0; |
| for ( v = 0; v < nVars; v++ ) |
| { |
| int Value = ((set >> (v << 1)) & 3); |
| if ( Value == 1 ) |
| nUnique++; |
| else if ( Value == 3 ) |
| nShared++; |
| else if ( Value == 0 ) |
| nFree++; |
| else assert( 0 ); |
| } |
| *pnUnique = nUnique; |
| *pnShared = nShared; |
| *pnFree = nFree; |
| } |
| void Dau_DecPrintSet( unsigned set, int nVars, int fNewLine ) |
| { |
| int v, Counter = 0; |
| int nUnique = 0, nShared = 0, nFree = 0; |
| Dau_DecSortSet( set, nVars, &nUnique, &nShared, &nFree ); |
| printf( "S =%2d D =%2d C =%2d ", nShared, nUnique+nShared, nShared+nFree+1 ); |
| |
| printf( "x=" ); |
| for ( v = 0; v < nVars; v++ ) |
| { |
| int Value = ((set >> (v << 1)) & 3); |
| if ( Value == 1 ) |
| printf( "%c", 'a' + v ), Counter++; |
| else if ( Value == 3 ) |
| printf( "%c", 'A' + v ), Counter++; |
| else assert( Value == 0 ); |
| } |
| printf( " y=x" ); |
| for ( v = 0; v < nVars; v++ ) |
| { |
| int Value = ((set >> (v << 1)) & 3); |
| if ( Value == 0 ) |
| printf( "%c", 'a' + v ), Counter++; |
| else if ( Value == 3 ) |
| printf( "%c", 'A' + v ), Counter++; |
| } |
| for ( ; Counter < 15; Counter++ ) |
| printf( " " ); |
| if ( fNewLine ) |
| printf( "\n" ); |
| } |
| unsigned Dau_DecReadSet( char * pStr ) |
| { |
| unsigned uSet = 0; int v; |
| for ( v = 0; pStr[v]; v++ ) |
| { |
| if ( pStr[v] >= 'a' && pStr[v] <= 'z' ) |
| uSet |= (1 << ((pStr[v] - 'a') << 1)); |
| else if ( pStr[v] >= 'A' && pStr[v] <= 'Z' ) |
| uSet |= (1 << ((pStr[v] - 'a') << 1)) | (1 << (((pStr[v] - 'a') << 1)+1)); |
| else break; |
| } |
| return uSet; |
| } |
| void Dau_DecPrintSets( Vec_Int_t * vSets, int nVars ) |
| { |
| int i, Entry; |
| printf( "The %d-variable set family contains %d sets:\n", nVars, Vec_IntSize(vSets) ); |
| Vec_IntForEachEntry( vSets, Entry, i ) |
| Dau_DecPrintSet( (unsigned)Entry, nVars, 1 ); |
| printf( "\n" ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Find decomposable bound-sets of the given function.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Dau_DecMoveFreeToLSB( word * p, int nVars, int * V2P, int * P2V, int maskB, int sizeB ) |
| { |
| int v, c = 0; |
| for ( v = 0; v < nVars; v++ ) |
| if ( !((maskB >> v) & 1) ) |
| Abc_TtMoveVar( p, nVars, V2P, P2V, v, c++ ); |
| assert( c == nVars - sizeB ); |
| } |
| Vec_Int_t * Dau_DecFindSets_int( word * pInit, int nVars, int * pSched[16] ) |
| { |
| Vec_Int_t * vSets = Vec_IntAlloc( 32 ); |
| int V2P[16], P2V[16], pVarsB[16]; |
| int Limit = (1 << nVars); |
| int c, v, sizeB, sizeS, maskB, maskS; |
| unsigned setMixed; |
| word p[1<<10]; |
| memcpy( p, pInit, sizeof(word) * Abc_TtWordNum(nVars) ); |
| for ( v = 0; v < nVars; v++ ) |
| assert( Abc_TtHasVar( p, nVars, v ) ); |
| // initialize permutation |
| for ( v = 0; v < nVars; v++ ) |
| V2P[v] = P2V[v] = v; |
| // iterate through bound sets of each size in increasing order |
| for ( sizeB = 2; sizeB < nVars; sizeB++ ) // bound set size |
| for ( maskB = 0; maskB < Limit; maskB++ ) // bound set |
| if ( Abc_TtBitCount16(maskB) == sizeB ) |
| { |
| // permute variables to have bound set on top |
| Dau_DecMoveFreeToLSB( p, nVars, V2P, P2V, maskB, sizeB ); |
| // collect bound set vars on levels nVars-sizeB to nVars-1 |
| for ( c = 0; c < sizeB; c++ ) |
| pVarsB[c] = P2V[nVars-sizeB+c]; |
| // check disjoint |
| // if ( Dau_DecCheckSetTopOld(p, nVars, nVars-sizeB, sizeB, 0, 0, NULL, NULL, NULL) ) |
| if ( Dau_DecCheckSetTop(p, nVars, nVars-sizeB, sizeB, 0, 0, pSched[sizeB], NULL, NULL) ) |
| { |
| Vec_IntPush( vSets, Dau_DecCreateSet(pVarsB, sizeB, 0) ); |
| continue; |
| } |
| if ( sizeB == 2 ) |
| continue; |
| // iterate through shared sets of each size in the increasing order |
| for ( sizeS = 1; sizeS <= sizeB - 2; sizeS++ ) // shared set size |
| if ( sizeS <= 3 ) |
| // sizeS = 1; |
| for ( maskS = 0; maskS < (1 << sizeB); maskS++ ) // shared set |
| if ( Abc_TtBitCount16(maskS) == sizeS ) |
| { |
| setMixed = Dau_DecCreateSet( pVarsB, sizeB, maskS ); |
| // printf( "Considering %10d ", setMixed ); |
| // Dau_DecPrintSet( setMixed, nVars ); |
| // check if it exists |
| if ( Dau_DecSetIsContained(vSets, setMixed) ) |
| continue; |
| // check if it can be added |
| // if ( Dau_DecCheckSetTopOld(p, nVars, nVars-sizeB, sizeB, sizeS, maskS, NULL, NULL, NULL) ) |
| if ( Dau_DecCheckSetTop(p, nVars, nVars-sizeB, sizeB, sizeS, maskS, pSched[sizeB], NULL, NULL) ) |
| Vec_IntPush( vSets, setMixed ); |
| } |
| } |
| return vSets; |
| } |
| Vec_Int_t * Dau_DecFindSets( word * pInit, int nVars ) |
| { |
| Vec_Int_t * vSets; |
| int v, * pSched[16] = {NULL}; |
| for ( v = 2; v < nVars; v++ ) |
| pSched[v] = Extra_GreyCodeSchedule( v ); |
| vSets = Dau_DecFindSets_int( pInit, nVars, pSched ); |
| for ( v = 2; v < nVars; v++ ) |
| ABC_FREE( pSched[v] ); |
| return vSets; |
| } |
| void Dau_DecFindSetsTest2() |
| { |
| Vec_Int_t * vSets; |
| word a0 = (~s_Truths6[1] & s_Truths6[2]) | (s_Truths6[1] & s_Truths6[3]); |
| word a1 = (~s_Truths6[1] & s_Truths6[4]) | (s_Truths6[1] & s_Truths6[5]); |
| word t = (~s_Truths6[0] & a0) | (s_Truths6[0] & a1); |
| // word t = ABC_CONST(0x7EFFFFFFFFFFFF7E); // and(gam1,gam2) |
| // word t = ABC_CONST(0xB0F0BBFFB0F0BAFE); // some funct |
| // word t = ABC_CONST(0x2B0228022B022802); // 5-var non-dec0x0F7700000F770000 |
| // word t = ABC_CONST(0x0F7700000F770000); // (!<(ab)cd>e) |
| // word t = ABC_CONST(0x7F00000000000000); // (!(abc)def) |
| int nVars = 5; |
| |
| vSets = Dau_DecFindSets( &t, nVars ); |
| Dau_DecPrintSets( vSets, nVars ); |
| Vec_IntFree( vSets ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Replaces variables in the string.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Dau_DecVarReplace( char * pStr, int * pPerm, int nVars ) |
| { |
| int v; |
| for ( v = 0; pStr[v]; v++ ) |
| if ( pStr[v] >= 'a' && pStr[v] <= 'z' ) |
| { |
| assert( pStr[v] - 'a' < nVars ); |
| pStr[v] = 'a' + pPerm[pStr[v] - 'a']; |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Decomposes with the given bound-set.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Dau_DecDecomposeSet( word * pInit, int nVars, unsigned uSet, word * pComp, word * pDec, int * pPermC, int * pPermD, int * pnVarsC, int * pnVarsD, int * pnVarsS ) |
| { |
| word p[1<<13], Cof[64], Cof0[64], Cof1[64], Decs[64]; |
| word * pCof0[64], * pCof1[64], * pDecs[64], MintC, MintD; |
| int V2P[16], P2V[16], pVarsU[16], pVarsS[16], pVarsF[16]; |
| int nVarsU = 0, nVarsS = 0, nVarsF = 0; |
| int nWords = Abc_TtWordNum(nVars); |
| int v, d, c, Status, nDecs; |
| assert( nVars <= 16 ); |
| for ( v = 0; v < nVars; v++ ) |
| V2P[v] = P2V[v] = v; |
| memcpy( p, pInit, sizeof(word) * nWords ); |
| // sort variables |
| for ( v = 0; v < nVars; v++ ) |
| { |
| int Value = (uSet >> (v<<1)) & 3; |
| if ( Value == 0 ) |
| pVarsF[nVarsF++] = v; |
| else if ( Value == 1 ) |
| pVarsU[nVarsU++] = v; |
| else if ( Value == 3 ) |
| pVarsS[nVarsS++] = v; |
| else assert(0); |
| } |
| assert( nVarsS >= 0 && nVarsS <= 6 ); |
| assert( nVarsF + nVarsS + 1 <= 6 ); |
| assert( nVarsU + nVarsS <= 6 ); |
| // init space for decomposition functions |
| nDecs = (1 << nVarsS); |
| for ( d = 0; d < nDecs; d++ ) |
| { |
| pCof0[d] = Cof0 + d; |
| pCof1[d] = Cof1 + d; |
| pDecs[d] = Decs + d; |
| } |
| // permute variables |
| c = 0; |
| for ( v = 0; v < nVarsF; v++ ) |
| Abc_TtMoveVar( p, nVars, V2P, P2V, pVarsF[v], c++ ); |
| for ( v = 0; v < nVarsS; v++ ) |
| Abc_TtMoveVar( p, nVars, V2P, P2V, pVarsS[v], c++ ); |
| for ( v = 0; v < nVarsU; v++ ) |
| Abc_TtMoveVar( p, nVars, V2P, P2V, pVarsU[v], c++ ); |
| assert( c == nVars ); |
| // check decomposition |
| Status = Dau_DecCheckSetTopOld( p, nVars, nVarsF, nVarsS+nVarsU, nVarsS, Abc_InfoMask(nVarsS), pCof0, pCof1, pDecs ); |
| if ( !Status ) |
| return 0; |
| // compute cofactors |
| assert( nVarsF + nVarsS < 6 ); |
| for ( d = 0; d < nDecs; d++ ) |
| { |
| Cof[d] = (pCof1[d][0] & s_Truths6[nVarsF + nVarsS]) | (pCof0[d][0] & ~s_Truths6[nVarsF + nVarsS]); |
| pDecs[d][0] = Abc_Tt6Stretch( pDecs[d][0], nVarsU ); |
| } |
| // compute the resulting functions |
| pComp[0] = 0; |
| pDec[0] = 0; |
| for ( d = 0; d < nDecs; d++ ) |
| { |
| // compute minterms for composition/decomposition function |
| MintC = MintD = ~((word)0); |
| for ( v = 0; v < nVarsS; v++ ) |
| { |
| MintC &= ((d >> v) & 1) ? s_Truths6[nVarsF+v] : ~s_Truths6[nVarsF+v]; |
| MintD &= ((d >> v) & 1) ? s_Truths6[nVarsU+v] : ~s_Truths6[nVarsU+v]; |
| } |
| // derive functions |
| pComp[0] |= MintC & Cof[d]; |
| pDec[0] |= MintD & pDecs[d][0]; |
| } |
| // derive variable permutations |
| if ( pPermC ) |
| { |
| for ( v = 0; v < nVarsF; v++ ) |
| pPermC[v] = pVarsF[v]; |
| for ( v = 0; v < nVarsS; v++ ) |
| pPermC[nVarsF+v] = pVarsS[v]; |
| pPermC[nVarsF + nVarsS] = nVars; |
| } |
| if ( pPermD ) |
| { |
| for ( v = 0; v < nVarsU; v++ ) |
| pPermD[v] = pVarsU[v]; |
| for ( v = 0; v < nVarsS; v++ ) |
| pPermD[nVarsU+v] = pVarsS[v]; |
| } |
| if ( pnVarsC ) |
| *pnVarsC = nVarsF + nVarsS + 1; |
| if ( pnVarsD ) |
| *pnVarsD = nVarsU + nVarsS; |
| if ( pnVarsS ) |
| *pnVarsS = nVarsS; |
| return 1; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Testing procedures.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Dau_DecVerify( word * pInit, int nVars, char * pDsdC, char * pDsdD ) |
| { |
| word pC[1<<13], pD[1<<13], pRes[1<<13]; // max = 16 |
| int nWordsC = Abc_TtWordNum(nVars+1); |
| int nWordsD = Abc_TtWordNum(nVars); |
| assert( nVars < 16 ); |
| memcpy( pC, Dau_DsdToTruth(pDsdC, nVars+1), sizeof(word) * nWordsC ); |
| memcpy( pD, Dau_DsdToTruth(pDsdD, nVars), sizeof(word) * nWordsD ); |
| if ( nVars >= 6 ) |
| { |
| assert( nWordsD >= 1 ); |
| assert( nWordsC > 1 ); |
| Abc_TtMux( pRes, pD, pC + nWordsD, pC, nWordsD ); |
| } |
| else |
| { |
| word pC0 = Abc_Tt6Stretch( pC[0], nVars ); |
| word pC1 = Abc_Tt6Stretch( (pC[0] >> (1 << nVars)), nVars ); |
| Abc_TtMux( pRes, pD, &pC1, &pC0, nWordsD ); |
| } |
| if ( !Abc_TtEqual(pInit, pRes, nWordsD) ) |
| printf( " Verification failed" ); |
| // else |
| // printf( " Verification successful" ); |
| printf( "\n" ); |
| return 1; |
| } |
| int Dau_DecPerform6( word * p, int nVars, unsigned uSet ) |
| { |
| word tComp = 0, tDec = 0, tDec0, tComp0, tComp1, FuncC, FuncD; |
| char pDsdC[1000], pDsdD[1000]; |
| int pPermC[16], pPermD[16]; |
| int nVarsC, nVarsD, nVarsS, nVarsU, nVarsF, nPairs; |
| int i, m, v, status, ResC, ResD, Counter = 0; |
| status = Dau_DecDecomposeSet( p, nVars, uSet, &tComp, &tDec0, pPermC, pPermD, &nVarsC, &nVarsD, &nVarsS ); |
| if ( !status ) |
| { |
| printf( " Decomposition does not exist\n" ); |
| return 0; |
| } |
| nVarsU = nVarsD - nVarsS; |
| nVarsF = nVarsC - nVarsS - 1; |
| tComp0 = Abc_Tt6Cofactor0( tComp, nVarsF + nVarsS ); |
| tComp1 = Abc_Tt6Cofactor1( tComp, nVarsF + nVarsS ); |
| nPairs = 1 << (1 << nVarsS); |
| for ( i = 0; i < nPairs; i++ ) |
| { |
| if ( i & 1 ) |
| continue; |
| // create miterms with this polarity |
| FuncC = FuncD = 0; |
| for ( m = 0; m < (1 << nVarsS); m++ ) |
| { |
| word MintC, MintD; |
| if ( !((i >> m) & 1) ) |
| continue; |
| MintC = MintD = ~(word)0; |
| for ( v = 0; v < nVarsS; v++ ) |
| { |
| MintC &= ((m >> v) & 1) ? s_Truths6[nVarsF+v] : ~s_Truths6[nVarsF+v]; |
| MintD &= ((m >> v) & 1) ? s_Truths6[nVarsU+v] : ~s_Truths6[nVarsU+v]; |
| } |
| FuncC |= MintC; |
| FuncD |= MintD; |
| } |
| // uncomplement given variables |
| tComp = (~s_Truths6[nVarsF + nVarsS] & ((tComp0 & ~FuncC) | (tComp1 & FuncC))) | (s_Truths6[nVarsF + nVarsS] & ((tComp1 & ~FuncC) | (tComp0 & FuncC))); |
| tDec = tDec0 ^ FuncD; |
| // decompose |
| ResC = Dau_DsdDecompose( &tComp, nVarsC, 0, 1, pDsdC ); |
| ResD = Dau_DsdDecompose( &tDec, nVarsD, 0, 1, pDsdD ); |
| // replace variables |
| Dau_DecVarReplace( pDsdD, pPermD, nVarsD ); |
| Dau_DecVarReplace( pDsdC, pPermC, nVarsC ); |
| // report |
| // printf( " " ); |
| printf( "%3d : ", Counter++ ); |
| printf( "%24s ", pDsdD ); |
| printf( "%24s ", pDsdC ); |
| Dau_DecVerify( p, nVars, pDsdC, pDsdD ); |
| } |
| return 1; |
| } |
| |
| int Dau_DecPerform( word * pInit, int nVars, unsigned uSet ) |
| { |
| word p[1<<10], pDec[1<<10], pComp[1<<10]; // at most 2^10 words |
| char pDsdC[5000], pDsdD[5000]; // at most 2^12 hex digits |
| int nVarsU, nVarsS, nVarsF, nVarsC = 0, nVarsD = 0; |
| int V2P[16], P2V[16], pPermC[16], pPermD[16], * pSched; |
| int v, i, status, ResC, ResD; |
| int nWords = Abc_TtWordNum(nVars); |
| assert( nVars <= 16 ); |
| // backup the function |
| memcpy( p, pInit, sizeof(word) * nWords ); |
| // get variable numbers |
| Dau_DecSortSet( uSet, nVars, &nVarsU, &nVarsS, &nVarsF ); |
| // permute function and order variables |
| for ( v = 0; v < nVars; v++ ) |
| V2P[v] = P2V[v] = v; |
| for ( i = v = 0; v < nVars; v++ ) |
| if ( ((uSet >> (v<<1)) & 3) == 0 ) // free first |
| Abc_TtMoveVar( p, nVars, V2P, P2V, v, i++ ), pPermC[nVarsC++] = v; |
| for ( v = 0; v < nVars; v++ ) |
| if ( ((uSet >> (v<<1)) & 3) == 3 ) // share second |
| Abc_TtMoveVar( p, nVars, V2P, P2V, v, i++ ), pPermC[nVarsC++] = v; |
| pPermC[nVarsC++] = nVars; |
| for ( v = 0; v < nVars; v++ ) |
| if ( ((uSet >> (v<<1)) & 3) == 1 ) // unique last |
| Abc_TtMoveVar( p, nVars, V2P, P2V, v, i++ ), pPermD[nVarsD++] = v; |
| for ( v = 0; v < nVarsS; v++ ) |
| pPermD[nVarsD++] = pPermC[nVarsF+v]; |
| assert( nVarsD == nVarsU + nVarsS ); |
| assert( nVarsC == nVarsF + nVarsS + 1 ); |
| assert( i == nVars ); |
| // decompose |
| pSched = Extra_GreyCodeSchedule( nVarsU + nVarsS ); |
| memset( pDec, 0, sizeof(word) * Abc_TtWordNum(nVarsD) ); |
| memset( pComp, 0, sizeof(word) * Abc_TtWordNum(nVarsC) ); |
| status = Dau_DecCheckSetTop( p, nVars, nVarsF, nVarsU + nVarsS, nVarsS, nVarsS ? Abc_InfoMask(nVarsS) : 0, pSched, pDec, pComp ); |
| ABC_FREE( pSched ); |
| if ( !status ) |
| { |
| printf( " Decomposition does not exist\n" ); |
| return 0; |
| } |
| // Dau_DsdPrintFromTruth( stdout, pC, nVars+1 ); //printf( "\n" ); |
| // Dau_DsdPrintFromTruth( stdout, pD, nVars ); //printf( "\n" ); |
| // Kit_DsdPrintFromTruth( (unsigned *)pComp, 6 ); printf( "\n" ); |
| // Kit_DsdPrintFromTruth( (unsigned *)pDec, 6 ); printf( "\n" ); |
| // decompose |
| ResC = Dau_DsdDecompose( pComp, nVarsC, 0, 1, pDsdC ); |
| ResD = Dau_DsdDecompose( pDec, nVarsD, 0, 1, pDsdD ); |
| // replace variables |
| Dau_DecVarReplace( pDsdD, pPermD, nVarsD ); |
| Dau_DecVarReplace( pDsdC, pPermC, nVarsC ); |
| // report |
| printf( " " ); |
| printf( "%3d : ", 0 ); |
| printf( "%24s ", pDsdD ); |
| printf( "%24s ", pDsdC ); |
| Dau_DecVerify( pInit, nVars, pDsdC, pDsdD ); |
| return 1; |
| } |
| void Dau_DecTrySets( word * pInit, int nVars, int fVerbose ) |
| { |
| Vec_Int_t * vSets; |
| int i, Entry; |
| assert( nVars <= 16 ); |
| vSets = Dau_DecFindSets( pInit, nVars ); |
| if ( !fVerbose ) |
| { |
| Vec_IntFree( vSets ); |
| return; |
| } |
| Dau_DsdPrintFromTruth( pInit, nVars ); |
| printf( "This %d-variable function has %d decomposable variable sets:\n", nVars, Vec_IntSize(vSets) ); |
| Vec_IntForEachEntry( vSets, Entry, i ) |
| { |
| unsigned uSet = (unsigned)Entry; |
| printf( "Set %4d : ", i ); |
| if ( nVars > 6 ) |
| { |
| Dau_DecPrintSet( uSet, nVars, 0 ); |
| Dau_DecPerform( pInit, nVars, uSet ); |
| } |
| else |
| { |
| Dau_DecPrintSet( uSet, nVars, 1 ); |
| Dau_DecPerform6( pInit, nVars, uSet ); |
| } |
| } |
| Vec_IntFree( vSets ); |
| // printf( "\n" ); |
| } |
| |
| void Dau_DecFindSetsTest3() |
| { |
| word a0 = (~s_Truths6[1] & s_Truths6[2]) | (s_Truths6[1] & s_Truths6[3]); |
| word a1 = (~s_Truths6[1] & s_Truths6[4]) | (s_Truths6[1] & s_Truths6[5]); |
| word t = (~s_Truths6[0] & a0) | (s_Truths6[0] & a1); |
| // word t = ABC_CONST(0x0F7700000F770000); // (!<(ab)cd>e) |
| int nVars = 6; |
| char * pStr = "Bcd"; |
| // char * pStr = "Abcd"; |
| // char * pStr = "ab"; |
| unsigned uSet = Dau_DecReadSet( pStr ); |
| Dau_DecPerform6( &t, nVars, uSet ); |
| } |
| |
| void Dau_DecFindSetsTest() |
| { |
| int nVars = 6; |
| // word a0 = (~s_Truths6[1] & s_Truths6[2]) | (s_Truths6[1] & s_Truths6[3]); |
| // word a1 = (~s_Truths6[1] & s_Truths6[4]) | (s_Truths6[1] & s_Truths6[5]); |
| // word t = (~s_Truths6[0] & a0) | (s_Truths6[0] & a1); |
| // word t = ABC_CONST(0x7EFFFFFFFFFFFF7E); // and(gam1,gam2) |
| // word t = ABC_CONST(0xB0F0BBFFB0F0BAFE); // some funct |
| // word t = ABC_CONST(0x00000000901FFFFF); // some funct |
| word t = ABC_CONST(0x000030F00D0D3FFF); // some funct |
| // word t = ABC_CONST(0x00000000690006FF); // some funct |
| // word t = ABC_CONST(0x7000F80007FF0FFF); // some funct |
| // word t = ABC_CONST(0x4133CB334133CB33); // some funct 5 var |
| // word t = ABC_CONST(0x2B0228022B022802); // 5-var non-dec0x0F7700000F770000 |
| // word t = ABC_CONST(0x0F7700000F770000); // (!<(ab)cd>e) |
| // word t = ABC_CONST(0x7F00000000000000); // (!(abc)def) |
| Dau_DecTrySets( &t, nVars, 1 ); |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |