/**CFile**************************************************************** FileName [dauDsd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware unmapping.] Synopsis [Disjoint-support decomposition.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: dauDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dau.h" #include "dauInt.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /* This code performs truth-table-based decomposition for 6-variable functions. Representation of operations: ! = not; (ab) = a and b; [ab] = a xor b; = ITE( a, b, c ) FUNCTION{abc} = FUNCTION( a, b, c ) */ //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [DSD formula manipulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Dau_DsdComputeMatches( char * p ) { static int pMatches[DAU_MAX_STR]; int pNested[DAU_MAX_VAR]; int v, nNested = 0; for ( v = 0; p[v]; v++ ) { pMatches[v] = 0; if ( p[v] == '(' || p[v] == '[' || p[v] == '<' || p[v] == '{' ) pNested[nNested++] = v; else if ( p[v] == ')' || p[v] == ']' || p[v] == '>' || p[v] == '}' ) pMatches[pNested[--nNested]] = v; assert( nNested < DAU_MAX_VAR ); } assert( nNested == 0 ); return pMatches; } /**Function************************************************************* Synopsis [Generate random permutation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dau_DsdFindVarNum( char * pDsd ) { int vMax = 0; pDsd--; while ( *++pDsd ) if ( *pDsd >= 'a' && *pDsd <= 'z' ) vMax = Abc_MaxInt( vMax, *pDsd - 'a' ); return vMax + 1; } void Dau_DsdGenRandPerm( int * pPerm, int nVars ) { int v, vNew; for ( v = 0; v < nVars; v++ ) pPerm[v] = v; for ( v = 0; v < nVars; v++ ) { vNew = rand() % nVars; ABC_SWAP( int, pPerm[v], pPerm[vNew] ); } } void Dau_DsdPermute( char * pDsd ) { int pPerm[16]; int nVars = Dau_DsdFindVarNum( pDsd ); Dau_DsdGenRandPerm( pPerm, nVars ); pDsd--; while ( *++pDsd ) if ( *pDsd >= 'a' && *pDsd < 'a' + nVars ) *pDsd = 'a' + pPerm[*pDsd - 'a']; } /**Function************************************************************* Synopsis [Normalize the ordering of components.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Dau_DsdNormalizeCopy( char * pDest, char * pSour, int * pMarks, int i ) { int s; for ( s = pMarks[i]; s < pMarks[i+1]; s++ ) *pDest++ = pSour[s]; return pDest; } int Dau_DsdNormalizeCompare( char * pStr, int * pMarks, int i, int j ) { char * pStr1 = pStr + pMarks[i]; char * pStr2 = pStr + pMarks[j]; char * pLimit1 = pStr + pMarks[i+1]; char * pLimit2 = pStr + pMarks[j+1]; for ( ; pStr1 < pLimit1 && pStr2 < pLimit2; pStr1++, pStr2++ ) { if ( !(*pStr1 >= 'a' && *pStr1 <= 'z') ) { pStr2--; continue; } if ( !(*pStr2 >= 'a' && *pStr2 <= 'z') ) { pStr1--; continue; } if ( *pStr1 < *pStr2 ) return -1; if ( *pStr1 > *pStr2 ) return 1; } assert( pStr1 < pLimit1 || pStr2 < pLimit2 ); if ( pStr1 == pLimit1 ) return -1; if ( pStr2 == pLimit2 ) return 1; assert( 0 ); return 0; } int * Dau_DsdNormalizePerm( char * pStr, int * pMarks, int nMarks ) { static int pPerm[DAU_MAX_VAR]; int i, k; for ( i = 0; i < nMarks; i++ ) pPerm[i] = i; for ( i = 0; i < nMarks; i++ ) { int iBest = i; for ( k = i + 1; k < nMarks; k++ ) if ( Dau_DsdNormalizeCompare( pStr, pMarks, pPerm[iBest], pPerm[k] ) == 1 ) iBest = k; ABC_SWAP( int, pPerm[i], pPerm[iBest] ); } return pPerm; } void Dau_DsdNormalize_rec( char * pStr, char ** p, int * pMatches ) { static char pBuffer[DAU_MAX_STR]; if ( **p == '!' ) (*p)++; if ( **p >= 'a' && **p <= 'f' ) // var return; if ( **p == '(' || **p == '[' ) // and/or/xor { char * pStore, * pOld = *p + 1; char * q = pStr + pMatches[ *p - pStr ]; int i, * pPerm, nMarks = 0, pMarks[DAU_MAX_VAR+1]; assert( *q == **p + 1 + (**p != '(') ); for ( (*p)++; *p < q; (*p)++ ) { pMarks[nMarks++] = *p - pStr; Dau_DsdNormalize_rec( pStr, p, pMatches ); } pMarks[nMarks] = *p - pStr; assert( *p == q ); // add to buffer in good order pPerm = Dau_DsdNormalizePerm( pStr, pMarks, nMarks ); // copy to the buffer pStore = pBuffer; for ( i = 0; i < nMarks; i++ ) pStore = Dau_DsdNormalizeCopy( pStore, pStr, pMarks, pPerm[i] ); assert( pStore - pBuffer == *p - pOld ); memcpy( pOld, pBuffer, pStore - pBuffer ); return; } if ( **p == '<' || **p == '{' ) // mux { char * q = pStr + pMatches[ *p - pStr ]; assert( *q == **p + 1 + (**p != '(') ); if ( (**p == '<') && (*(q+1) == '{') ) { *p = q+1; Dau_DsdNormalize_rec( pStr, p, pMatches ); return; } for ( (*p)++; *p < q; (*p)++ ) Dau_DsdNormalize_rec( pStr, p, pMatches ); assert( *p == q ); return; } if ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') ) { (*p)++; return; } assert( 0 ); } void Dau_DsdNormalize( char * pDsd ) { if ( pDsd[1] != 0 ) Dau_DsdNormalize_rec( pDsd, &pDsd, Dau_DsdComputeMatches(pDsd) ); } /**Function************************************************************* Synopsis [Computes truth table for the DSD formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word Dau_Dsd6TruthCompose_rec( word Func, word * pFanins, int nVars ) { word t0, t1; if ( Func == 0 ) return 0; if ( Func == ~(word)0 ) return ~(word)0; assert( nVars > 0 ); if ( --nVars == 0 ) { assert( Func == s_Truths6[0] || Func == s_Truths6Neg[0] ); return (Func == s_Truths6[0]) ? pFanins[0] : ~pFanins[0]; } if ( !Abc_Tt6HasVar(Func, nVars) ) return Dau_Dsd6TruthCompose_rec( Func, pFanins, nVars ); t0 = Dau_Dsd6TruthCompose_rec( Abc_Tt6Cofactor0(Func, nVars), pFanins, nVars ); t1 = Dau_Dsd6TruthCompose_rec( Abc_Tt6Cofactor1(Func, nVars), pFanins, nVars ); return (~pFanins[nVars] & t0) | (pFanins[nVars] & t1); } word Dau_Dsd6ToTruth_rec( char * pStr, char ** p, int * pMatches, word * pTruths ) { int fCompl = 0; if ( **p == '!' ) (*p)++, fCompl = 1; if ( **p >= 'a' && **p <= 'f' ) // var { assert( **p - 'a' >= 0 && **p - 'a' < 6 ); return fCompl ? ~pTruths[**p - 'a'] : pTruths[**p - 'a']; } if ( **p == '(' ) // and/or { char * q = pStr + pMatches[ *p - pStr ]; word Res = ~(word)0; assert( **p == '(' && *q == ')' ); for ( (*p)++; *p < q; (*p)++ ) Res &= Dau_Dsd6ToTruth_rec( pStr, p, pMatches, pTruths ); assert( *p == q ); return fCompl ? ~Res : Res; } if ( **p == '[' ) // xor { char * q = pStr + pMatches[ *p - pStr ]; word Res = 0; assert( **p == '[' && *q == ']' ); for ( (*p)++; *p < q; (*p)++ ) Res ^= Dau_Dsd6ToTruth_rec( pStr, p, pMatches, pTruths ); assert( *p == q ); return fCompl ? ~Res : Res; } if ( **p == '<' ) // mux { int nVars = 0; word Temp[3], * pTemp = Temp, Res; word Fanins[6], * pTruths2; char * pOld = *p; char * q = pStr + pMatches[ *p - pStr ]; // read fanins if ( *(q+1) == '{' ) { char * q2; *p = q+1; q2 = pStr + pMatches[ *p - pStr ]; assert( **p == '{' && *q2 == '}' ); for ( nVars = 0, (*p)++; *p < q2; (*p)++, nVars++ ) Fanins[nVars] = Dau_Dsd6ToTruth_rec( pStr, p, pMatches, pTruths ); assert( *p == q2 ); pTruths2 = Fanins; } else pTruths2 = pTruths; // read MUX *p = pOld; q = pStr + pMatches[ *p - pStr ]; assert( **p == '<' && *q == '>' ); // verify internal variables if ( nVars ) for ( ; pOld < q; pOld++ ) if ( *pOld >= 'a' && *pOld <= 'z' ) assert( *pOld - 'a' < nVars ); // derive MAX components for ( (*p)++; *p < q; (*p)++ ) *pTemp++ = Dau_Dsd6ToTruth_rec( pStr, p, pMatches, pTruths2 ); assert( pTemp == Temp + 3 ); assert( *p == q ); if ( *(q+1) == '{' ) // and/or { char * q = pStr + pMatches[ ++(*p) - pStr ]; assert( **p == '{' && *q == '}' ); *p = q; } Res = (Temp[0] & Temp[1]) | (~Temp[0] & Temp[2]); return fCompl ? ~Res : Res; } if ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') ) { word Func, Fanins[6], Res; char * q; int i, nVars = Abc_TtReadHex( &Func, *p ); *p += Abc_TtHexDigitNum( nVars ); q = pStr + pMatches[ *p - pStr ]; assert( **p == '{' && *q == '}' ); for ( i = 0, (*p)++; *p < q; (*p)++, i++ ) Fanins[i] = Dau_Dsd6ToTruth_rec( pStr, p, pMatches, pTruths ); assert( i == nVars ); assert( *p == q ); Res = Dau_Dsd6TruthCompose_rec( Func, Fanins, nVars ); return fCompl ? ~Res : Res; } assert( 0 ); return 0; } word Dau_Dsd6ToTruth( char * p ) { word Res; if ( *p == '0' && *(p+1) == 0 ) Res = 0; else if ( *p == '1' && *(p+1) == 0 ) Res = ~(word)0; else Res = Dau_Dsd6ToTruth_rec( p, &p, Dau_DsdComputeMatches(p), s_Truths6 ); assert( *++p == 0 ); return Res; } /**Function************************************************************* Synopsis [Computes truth table for the DSD formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dau_DsdTruth6Compose_rec( word Func, word pFanins[DAU_MAX_VAR][DAU_MAX_WORD], word * pRes, int nVars ) { if ( Func == 0 ) { Abc_TtConst0( pRes, Abc_TtWordNum(nVars) ); return; } if ( Func == ~(word)0 ) { Abc_TtConst1( pRes, Abc_TtWordNum(nVars) ); return; } assert( nVars > 0 ); if ( --nVars == 0 ) { assert( Func == s_Truths6[0] || Func == s_Truths6Neg[0] ); Abc_TtCopy( pRes, pFanins[0], Abc_TtWordNum(nVars), Func == s_Truths6Neg[0] ); return; } if ( !Abc_Tt6HasVar(Func, nVars) ) { Dau_DsdTruth6Compose_rec( Func, pFanins, pRes, nVars ); return; } { word pTtTemp[2][DAU_MAX_WORD]; Dau_DsdTruth6Compose_rec( Abc_Tt6Cofactor0(Func, nVars), pFanins, pTtTemp[0], nVars ); Dau_DsdTruth6Compose_rec( Abc_Tt6Cofactor1(Func, nVars), pFanins, pTtTemp[1], nVars ); Abc_TtMux( pRes, pFanins[nVars], pTtTemp[1], pTtTemp[0], Abc_TtWordNum(nVars) ); return; } } void Dau_DsdTruthCompose_rec( word * pFunc, word pFanins[DAU_MAX_VAR][DAU_MAX_WORD], word * pRes, int nVars ) { int nWords; if ( nVars <= 6 ) { Dau_DsdTruth6Compose_rec( pFunc[0], pFanins, pRes, nVars ); return; } nWords = Abc_TtWordNum( nVars ); if ( Abc_TtIsConst0(pFunc, nWords) ) { Abc_TtConst0( pRes, nWords ); return; } if ( Abc_TtIsConst1(pFunc, nWords) ) { Abc_TtConst1( pRes, nWords ); return; } if ( !Abc_TtHasVar( pFunc, nVars, nVars-1 ) ) { Dau_DsdTruthCompose_rec( pFunc, pFanins, pRes, nVars-1 ); return; } { word pCofTemp[2][DAU_MAX_WORD]; word pTtTemp[2][DAU_MAX_WORD]; nVars--; Abc_TtCopy( pCofTemp[0], pFunc, nWords, 0 ); Abc_TtCopy( pCofTemp[1], pFunc, nWords, 0 ); Abc_TtCofactor0( pCofTemp[0], nWords, nVars ); Abc_TtCofactor1( pCofTemp[1], nWords, nVars ); Dau_DsdTruthCompose_rec( pCofTemp[0], pFanins, pTtTemp[0], nVars ); Dau_DsdTruthCompose_rec( pCofTemp[1], pFanins, pTtTemp[1], nVars ); Abc_TtMux( pRes, pFanins[nVars], pTtTemp[1], pTtTemp[0], nWords ); return; } } void Dau_DsdToTruth_rec( char * pStr, char ** p, int * pMatches, word ** pTtElems, word * pRes, int nVars ) { int nWords = Abc_TtWordNum( nVars ); int fCompl = 0; if ( **p == '!' ) (*p)++, fCompl = 1; if ( **p >= 'a' && **p <= 'f' ) // var { assert( **p - 'a' >= 0 && **p - 'a' < 6 ); Abc_TtCopy( pRes, pTtElems[**p - 'a'], nWords, fCompl ); return; } if ( **p == '(' ) // and/or { char * q = pStr + pMatches[ *p - pStr ]; word pTtTemp[DAU_MAX_WORD]; assert( **p == '(' && *q == ')' ); Abc_TtConst1( pRes, nWords ); for ( (*p)++; *p < q; (*p)++ ) { Dau_DsdToTruth_rec( pStr, p, pMatches, pTtElems, pTtTemp, nVars ); Abc_TtAnd( pRes, pRes, pTtTemp, nWords, 0 ); } assert( *p == q ); if ( fCompl ) Abc_TtNot( pRes, nWords ); return; } if ( **p == '[' ) // xor { char * q = pStr + pMatches[ *p - pStr ]; word pTtTemp[DAU_MAX_WORD]; assert( **p == '[' && *q == ']' ); Abc_TtConst0( pRes, nWords ); for ( (*p)++; *p < q; (*p)++ ) { Dau_DsdToTruth_rec( pStr, p, pMatches, pTtElems, pTtTemp, nVars ); Abc_TtXor( pRes, pRes, pTtTemp, nWords, 0 ); } assert( *p == q ); if ( fCompl ) Abc_TtNot( pRes, nWords ); return; } if ( **p == '<' ) // mux { char * q = pStr + pMatches[ *p - pStr ]; word pTtTemp[3][DAU_MAX_WORD]; int i; assert( **p == '<' && *q == '>' ); for ( i = 0, (*p)++; *p < q; (*p)++, i++ ) Dau_DsdToTruth_rec( pStr, p, pMatches, pTtElems, pTtTemp[i], nVars ); assert( i == 3 ); Abc_TtMux( pRes, pTtTemp[0], pTtTemp[1], pTtTemp[2], nWords ); assert( *p == q ); if ( fCompl ) Abc_TtNot( pRes, nWords ); return; } if ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') ) { word pFanins[DAU_MAX_VAR][DAU_MAX_WORD], pFunc[DAU_MAX_WORD]; char * q; int i, nVars = Abc_TtReadHex( pFunc, *p ); *p += Abc_TtHexDigitNum( nVars ); q = pStr + pMatches[ *p - pStr ]; assert( **p == '{' && *q == '}' ); for ( i = 0, (*p)++; *p < q; (*p)++, i++ ) Dau_DsdToTruth_rec( pStr, p, pMatches, pTtElems, pFanins[i], nVars ); assert( i == nVars ); assert( *p == q ); Dau_DsdTruthCompose_rec( pFunc, pFanins, pRes, nWords ); if ( fCompl ) Abc_TtNot( pRes, nWords ); return; } assert( 0 ); } word * Dau_DsdToTruth( char * p, int nVars ) { static word TtElems[DAU_MAX_VAR+1][DAU_MAX_WORD], * pTtElems[DAU_MAX_VAR] = {NULL}; int v, nWords = Abc_TtWordNum( nVars ); word * pRes; if ( pTtElems[0] == NULL ) { for ( v = 0; v < DAU_MAX_VAR; v++ ) pTtElems[v] = TtElems[v]; Abc_TtElemInit( pTtElems, DAU_MAX_VAR ); } pRes = pTtElems[DAU_MAX_VAR]; if ( p[0] == '0' && p[1] == 0 ) Abc_TtConst0( pRes, nWords ); else if ( p[0] == '1' && p[1] == 0 ) Abc_TtConst1( pRes, nWords ); else Dau_DsdToTruth_rec( p, &p, Dau_DsdComputeMatches(p), pTtElems, pRes, nVars ); assert( *++p == 0 ); return pRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dau_DsdTest2() { // char * p = Abc_UtilStrsav( "!(ab!(de[cf]))" ); // char * p = Abc_UtilStrsav( "!(a![d]b)" ); // word t = Dau_Dsd6ToTruth( p ); } /**Function************************************************************* Synopsis [Performs DSD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dau_DsdPerformReplace( char * pBuffer, int PosStart, int Pos, int Symb, char * pNext ) { static char pTemp[DAU_MAX_STR]; char * pCur = pTemp; int i, k, RetValue; for ( i = PosStart; i < Pos; i++ ) if ( pBuffer[i] != Symb ) *pCur++ = pBuffer[i]; else for ( k = 0; pNext[k]; k++ ) *pCur++ = pNext[k]; RetValue = PosStart + (pCur - pTemp); for ( i = PosStart; i < RetValue; i++ ) pBuffer[i] = pTemp[i-PosStart]; return RetValue; } int Dau_DsdPerform_rec( word t, char * pBuffer, int Pos, int * pVars, int nVars ) { char pNest[10]; word Cof0[6], Cof1[6], Cof[4]; int pVarsNew[6], nVarsNew, PosStart; int v, u, vBest, CountBest; assert( Pos < DAU_MAX_STR ); // perform support minimization nVarsNew = 0; for ( v = 0; v < nVars; v++ ) if ( Abc_Tt6HasVar( t, pVars[v] ) ) pVarsNew[ nVarsNew++ ] = pVars[v]; assert( nVarsNew > 0 ); // special case when function is a var if ( nVarsNew == 1 ) { if ( t == s_Truths6[ pVarsNew[0] ] ) { pBuffer[Pos++] = 'a' + pVarsNew[0]; return Pos; } if ( t == ~s_Truths6[ pVarsNew[0] ] ) { pBuffer[Pos++] = '!'; pBuffer[Pos++] = 'a' + pVarsNew[0]; return Pos; } assert( 0 ); return Pos; } // decompose on the output side for ( v = 0; v < nVarsNew; v++ ) { Cof0[v] = Abc_Tt6Cofactor0( t, pVarsNew[v] ); Cof1[v] = Abc_Tt6Cofactor1( t, pVarsNew[v] ); assert( Cof0[v] != Cof1[v] ); if ( Cof0[v] == 0 ) // ax { pBuffer[Pos++] = '('; pBuffer[Pos++] = 'a' + pVarsNew[v]; Pos = Dau_DsdPerform_rec( Cof1[v], pBuffer, Pos, pVarsNew, nVarsNew ); pBuffer[Pos++] = ')'; return Pos; } if ( Cof0[v] == ~(word)0 ) // !(ax) { pBuffer[Pos++] = '!'; pBuffer[Pos++] = '('; pBuffer[Pos++] = 'a' + pVarsNew[v]; Pos = Dau_DsdPerform_rec( ~Cof1[v], pBuffer, Pos, pVarsNew, nVarsNew ); pBuffer[Pos++] = ')'; return Pos; } if ( Cof1[v] == 0 ) // !ax { pBuffer[Pos++] = '('; pBuffer[Pos++] = '!'; pBuffer[Pos++] = 'a' + pVarsNew[v]; Pos = Dau_DsdPerform_rec( Cof0[v], pBuffer, Pos, pVarsNew, nVarsNew ); pBuffer[Pos++] = ')'; return Pos; } if ( Cof1[v] == ~(word)0 ) // !(!ax) { pBuffer[Pos++] = '!'; pBuffer[Pos++] = '('; pBuffer[Pos++] = '!'; pBuffer[Pos++] = 'a' + pVarsNew[v]; Pos = Dau_DsdPerform_rec( ~Cof0[v], pBuffer, Pos, pVarsNew, nVarsNew ); pBuffer[Pos++] = ')'; return Pos; } if ( Cof0[v] == ~Cof1[v] ) // a^x { pBuffer[Pos++] = '['; pBuffer[Pos++] = 'a' + pVarsNew[v]; Pos = Dau_DsdPerform_rec( Cof0[v], pBuffer, Pos, pVarsNew, nVarsNew ); pBuffer[Pos++] = ']'; return Pos; } } // decompose on the input side for ( v = 0; v < nVarsNew; v++ ) for ( u = v+1; u < nVarsNew; u++ ) { Cof[0] = Abc_Tt6Cofactor0( Cof0[v], pVarsNew[u] ); Cof[1] = Abc_Tt6Cofactor1( Cof0[v], pVarsNew[u] ); Cof[2] = Abc_Tt6Cofactor0( Cof1[v], pVarsNew[u] ); Cof[3] = Abc_Tt6Cofactor1( Cof1[v], pVarsNew[u] ); if ( Cof[0] == Cof[1] && Cof[0] == Cof[2] ) // vu { PosStart = Pos; sprintf( pNest, "(%c%c)", 'a' + pVarsNew[v], 'a' + pVarsNew[u] ); Pos = Dau_DsdPerform_rec( (s_Truths6[pVarsNew[u]] & Cof[3]) | (~s_Truths6[pVarsNew[u]] & Cof[0]), pBuffer, Pos, pVarsNew, nVarsNew ); Pos = Dau_DsdPerformReplace( pBuffer, PosStart, Pos, 'a' + pVarsNew[u], pNest ); return Pos; } if ( Cof[0] == Cof[1] && Cof[0] == Cof[3] ) // v!u { PosStart = Pos; sprintf( pNest, "(%c!%c)", 'a' + pVarsNew[v], 'a' + pVarsNew[u] ); Pos = Dau_DsdPerform_rec( (s_Truths6[pVarsNew[u]] & Cof[2]) | (~s_Truths6[pVarsNew[u]] & Cof[0]), pBuffer, Pos, pVarsNew, nVarsNew ); Pos = Dau_DsdPerformReplace( pBuffer, PosStart, Pos, 'a' + pVarsNew[u], pNest ); return Pos; } if ( Cof[0] == Cof[2] && Cof[0] == Cof[3] ) // !vu { PosStart = Pos; sprintf( pNest, "(!%c%c)", 'a' + pVarsNew[v], 'a' + pVarsNew[u] ); Pos = Dau_DsdPerform_rec( (s_Truths6[pVarsNew[u]] & Cof[1]) | (~s_Truths6[pVarsNew[u]] & Cof[0]), pBuffer, Pos, pVarsNew, nVarsNew ); Pos = Dau_DsdPerformReplace( pBuffer, PosStart, Pos, 'a' + pVarsNew[u], pNest ); return Pos; } if ( Cof[1] == Cof[2] && Cof[1] == Cof[3] ) // !v!u { PosStart = Pos; sprintf( pNest, "(!%c!%c)", 'a' + pVarsNew[v], 'a' + pVarsNew[u] ); Pos = Dau_DsdPerform_rec( (s_Truths6[pVarsNew[u]] & Cof[0]) | (~s_Truths6[pVarsNew[u]] & Cof[1]), pBuffer, Pos, pVarsNew, nVarsNew ); Pos = Dau_DsdPerformReplace( pBuffer, PosStart, Pos, 'a' + pVarsNew[u], pNest ); return Pos; } if ( Cof[0] == Cof[3] && Cof[1] == Cof[2] ) // v+u { PosStart = Pos; sprintf( pNest, "[%c%c]", 'a' + pVarsNew[v], 'a' + pVarsNew[u] ); Pos = Dau_DsdPerform_rec( (s_Truths6[pVarsNew[u]] & Cof[1]) | (~s_Truths6[pVarsNew[u]] & Cof[0]), pBuffer, Pos, pVarsNew, nVarsNew ); Pos = Dau_DsdPerformReplace( pBuffer, PosStart, Pos, 'a' + pVarsNew[u], pNest ); return Pos; } } // find best variable for MUX decomposition vBest = -1; CountBest = 10; for ( v = 0; v < nVarsNew; v++ ) { int CountCur = 0; for ( u = 0; u < nVarsNew; u++ ) if ( u != v && Abc_Tt6HasVar(Cof0[v], pVarsNew[u]) && Abc_Tt6HasVar(Cof1[v], pVarsNew[u]) ) CountCur++; if ( CountBest > CountCur ) { CountBest = CountCur; vBest = v; } if ( CountCur == 0 ) break; } // perform MUX decomposition pBuffer[Pos++] = '<'; pBuffer[Pos++] = 'a' + pVarsNew[vBest]; Pos = Dau_DsdPerform_rec( Cof1[vBest], pBuffer, Pos, pVarsNew, nVarsNew ); Pos = Dau_DsdPerform_rec( Cof0[vBest], pBuffer, Pos, pVarsNew, nVarsNew ); pBuffer[Pos++] = '>'; return Pos; } char * Dau_DsdPerform( word t ) { static char pBuffer[DAU_MAX_STR]; int pVarsNew[6] = {0, 1, 2, 3, 4, 5}; int Pos = 0; if ( t == 0 ) pBuffer[Pos++] = '0'; else if ( t == ~(word)0 ) pBuffer[Pos++] = '1'; else Pos = Dau_DsdPerform_rec( t, pBuffer, Pos, pVarsNew, 6 ); pBuffer[Pos++] = 0; // printf( "%d ", strlen(pBuffer) ); // printf( "%s ->", pBuffer ); Dau_DsdRemoveBraces( pBuffer, Dau_DsdComputeMatches(pBuffer) ); // printf( " %s\n", pBuffer ); return pBuffer; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dau_DsdTest3() { // word t = s_Truths6[0] & s_Truths6[1] & s_Truths6[2]; // word t = ~s_Truths6[0] | (s_Truths6[1] ^ ~s_Truths6[2]); // word t = (s_Truths6[1] & s_Truths6[2]) | (s_Truths6[0] & s_Truths6[3]); // word t = (~s_Truths6[1] & ~s_Truths6[2]) | (s_Truths6[0] ^ s_Truths6[3]); // word t = ((~s_Truths6[1] & ~s_Truths6[2]) | (s_Truths6[0] ^ s_Truths6[3])) ^ s_Truths6[5]; // word t = ((s_Truths6[1] & ~s_Truths6[2]) ^ (s_Truths6[0] & s_Truths6[3])) & s_Truths6[5]; // word t = (~(~s_Truths6[0] & ~s_Truths6[4]) & s_Truths6[2]) | (~s_Truths6[1] & ~s_Truths6[0] & ~s_Truths6[4]); // word t = 0x0000000000005F3F; // word t = 0xF3F5030503050305; // word t = (s_Truths6[0] & s_Truths6[1] & (s_Truths6[2] ^ s_Truths6[4])) | (~s_Truths6[0] & ~s_Truths6[1] & ~(s_Truths6[2] ^ s_Truths6[4])); // word t = 0x05050500f5f5f5f3; word t = 0x9ef7a8d9c7193a0f; char * p = Dau_DsdPerform( t ); word t2 = Dau_Dsd6ToTruth( p ); if ( t != t2 ) printf( "Verification failed.\n" ); } /**Function************************************************************* Synopsis [Find the best cofactoring variable.] Description [Return -2 if non-DSD; -1 if full DSD; otherwise, returns cofactoring variables i (i >= 0).] SideEffects [] SeeAlso [] ***********************************************************************/ int Dau_DsdCheck1Step( word * pTruth, int nVarsInit ) { word pCofTemp[DAU_MAX_WORD]; int nWords = Abc_TtWordNum(nVarsInit); int nSizeNonDec, nSizeNonDec0, nSizeNonDec1; int v, vBest = -2, nSumCofsBest = ABC_INFINITY, nSumCofs; nSizeNonDec = Dau_DsdDecompose( pTruth, nVarsInit, 0, NULL ); if ( nSizeNonDec == 0 ) return -1; assert( nSizeNonDec > 0 ); for ( v = 0; v < nVarsInit; v++ ) { // try first cofactor Abc_TtCopy( pCofTemp, pTruth, nWords, 0 ); Abc_TtCofactor0( pCofTemp, nWords, v ); nSumCofs = Abc_TtSupportSize( pCofTemp, nVarsInit ); nSizeNonDec0 = Dau_DsdDecompose( pCofTemp, nVarsInit, 0, NULL ); // try second cofactor Abc_TtCopy( pCofTemp, pTruth, nWords, 0 ); Abc_TtCofactor1( pCofTemp, nWords, v ); nSumCofs += Abc_TtSupportSize( pCofTemp, nVarsInit ); nSizeNonDec1 = Dau_DsdDecompose( pCofTemp, nVarsInit, 0, NULL ); // compare cofactors if ( nSizeNonDec0 || nSizeNonDec1 ) continue; if ( nSumCofsBest > nSumCofs ) { vBest = v; nSumCofsBest = nSumCofs; } } return vBest; } /**Function************************************************************* Synopsis [Data-structure to store DSD information.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ typedef struct Dau_Dsd_t_ Dau_Dsd_t; struct Dau_Dsd_t_ { int nVarsInit; // the initial number of variables int nVarsUsed; // the current number of variables int nPos; // writing position int nSizeNonDec; // size of the largest non-decomposable block int nConsts; // the number of constant decompositions int uConstMask; // constant decomposition mask int fSplitPrime; // represent prime function as 1-step DSD char pVarDefs[32][8]; // variable definitions char Cache[32][32]; // variable cache char pOutput[DAU_MAX_STR]; // output stream }; static clock_t s_Times[3] = {0}; /**Function************************************************************* Synopsis [Manipulation of DSD data-structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Dau_DsdInitialize( Dau_Dsd_t * p, int nVarsInit ) { int i, v, u; assert( nVarsInit >= 0 && nVarsInit <= 16 ); p->nVarsInit = nVarsInit; p->nVarsUsed = nVarsInit; p->nPos = 0; p->nSizeNonDec = 0; p->nConsts = 0; p->uConstMask = 0; for ( i = 0; i < nVarsInit; i++ ) p->pVarDefs[i][0] = 'a' + i, p->pVarDefs[i][1] = 0; for ( v = 0; v < nVarsInit; v++ ) for ( u = 0; u < nVarsInit; u++ ) p->Cache[v][u] = 0; } static inline void Dau_DsdWriteString( Dau_Dsd_t * p, char * pStr ) { while ( *pStr ) p->pOutput[ p->nPos++ ] = *pStr++; } static inline void Dau_DsdWriteVar( Dau_Dsd_t * p, int iVar, int fInv ) { char * pStr; if ( fInv ) p->pOutput[ p->nPos++ ] = '!'; for ( pStr = p->pVarDefs[iVar]; *pStr; pStr++ ) if ( *pStr >= 'a' + p->nVarsInit && *pStr < 'a' + p->nVarsUsed ) Dau_DsdWriteVar( p, *pStr - 'a', 0 ); else p->pOutput[ p->nPos++ ] = *pStr; } static inline void Dau_DsdTranslate( Dau_Dsd_t * p, int * pVars, int nVars, char * pStr ) { for ( ; *pStr; pStr++ ) if ( *pStr >= 'a' && *pStr < 'a' + nVars ) Dau_DsdWriteVar( p, pVars[*pStr - 'a'], 0 ); else p->pOutput[ p->nPos++ ] = *pStr; } static inline int Dau_DsdWritePrime( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars ) { int v, RetValue = 2; assert( nVars > 2 ); if ( p->fSplitPrime ) { word pCofTemp[DAU_MAX_WORD]; int nWords = Abc_TtWordNum(nVars); int vBest = Dau_DsdCheck1Step( pTruth, nVars ); assert( vBest != -1 ); if ( vBest == -2 ) // non-dec p->nPos += Abc_TtWriteHexRev( p->pOutput + p->nPos, pTruth, nVars ); else { char pRes[DAU_MAX_STR]; int nNonDecSize; // compose the result Dau_DsdWriteString( p, "<" ); Dau_DsdWriteVar( p, pVars[vBest], 0 ); // split decomposition Abc_TtCopy( pCofTemp, pTruth, nWords, 0 ); Abc_TtCofactor1( pCofTemp, nWords, vBest ); nNonDecSize = Dau_DsdDecompose( pCofTemp, nVars, 0, pRes ); assert( nNonDecSize == 0 ); Dau_DsdWriteString( p, pRes ); // split decomposition Abc_TtCopy( pCofTemp, pTruth, nWords, 0 ); Abc_TtCofactor0( pCofTemp, nWords, vBest ); nNonDecSize = Dau_DsdDecompose( pCofTemp, nVars, 0, pRes ); assert( nNonDecSize == 0 ); Dau_DsdWriteString( p, pRes ); Dau_DsdWriteString( p, ">" ); RetValue = 1; } } else p->nPos += Abc_TtWriteHexRev( p->pOutput + p->nPos, pTruth, nVars ); Dau_DsdWriteString( p, "{" ); for ( v = 0; v < nVars; v++ ) Dau_DsdWriteVar( p, pVars[v], 0 ); Dau_DsdWriteString( p, "}" ); p->nSizeNonDec = nVars; return RetValue; } static inline void Dau_DsdFinalize( Dau_Dsd_t * p ) { int i; for ( i = 0; i < p->nConsts; i++ ) p->pOutput[ p->nPos++ ] = ((p->uConstMask >> (p->nConsts-1-i)) & 1) ? ']' : ')'; p->pOutput[ p->nPos++ ] = 0; } static inline int Dau_DsdAddVarDef( Dau_Dsd_t * p, char * pStr ) { int u; assert( strlen(pStr) < 8 ); assert( p->nVarsUsed < 32 ); for ( u = 0; u < p->nVarsUsed; u++ ) p->Cache[p->nVarsUsed][u] = 0; for ( u = 0; u < p->nVarsUsed; u++ ) p->Cache[u][p->nVarsUsed] = 0; sprintf( p->pVarDefs[p->nVarsUsed++], "%s", pStr ); return p->nVarsUsed - 1; } static inline int Dau_DsdFindVarDef( int * pVars, int nVars, int VarDef ) { int v; for ( v = 0; v < nVars; v++ ) if ( pVars[v] == VarDef ) break; assert( v < nVars ); return v; } static inline void Dau_DsdInsertVarCache( Dau_Dsd_t * p, int v, int u, int Status ) { assert( v != u ); assert( Status > 0 && Status < 4 ); assert( p->Cache[v][u] == 0 ); p->Cache[v][u] = Status; } static inline int Dau_DsdLookupVarCache( Dau_Dsd_t * p, int v, int u ) { return p->Cache[v][u]; } /**Function************************************************************* Synopsis [Procedures specialized for 6-variable functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dau_Dsd6DecomposeSingleVarOne( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v ) { // consider negative cofactors if ( pTruth[0] & 1 ) { if ( Abc_Tt6Cof0IsConst1( pTruth[0], v ) ) // !(ax) { Dau_DsdWriteString( p, "!(" ); pTruth[0] = ~Abc_Tt6Cofactor1( pTruth[0], v ); goto finish; } } else { if ( Abc_Tt6Cof0IsConst0( pTruth[0], v ) ) // ax { Dau_DsdWriteString( p, "(" ); pTruth[0] = Abc_Tt6Cofactor1( pTruth[0], v ); goto finish; } } // consider positive cofactors if ( pTruth[0] >> 63 ) { if ( Abc_Tt6Cof1IsConst1( pTruth[0], v ) ) // !(!ax) { Dau_DsdWriteString( p, "!(!" ); pTruth[0] = ~Abc_Tt6Cofactor0( pTruth[0], v ); goto finish; } } else { if ( Abc_Tt6Cof1IsConst0( pTruth[0], v ) ) // !ax { Dau_DsdWriteString( p, "(!" ); pTruth[0] = Abc_Tt6Cofactor0( pTruth[0], v ); goto finish; } } // consider equal cofactors if ( Abc_Tt6CofsOpposite( pTruth[0], v ) ) // [ax] { Dau_DsdWriteString( p, "[" ); pTruth[0] = Abc_Tt6Cofactor0( pTruth[0], v ); p->uConstMask |= (1 << p->nConsts); goto finish; } return 0; finish: p->nConsts++; Dau_DsdWriteVar( p, pVars[v], 0 ); pVars[v] = pVars[nVars-1]; Abc_TtSwapVars( pTruth, 6, v, nVars-1 ); return 1; } int Dau_Dsd6DecomposeSingleVar( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars ) { clock_t clk = clock(); assert( nVars > 1 ); while ( 1 ) { int v; for ( v = nVars - 1; v >= 0 && nVars > 1; v-- ) if ( Dau_Dsd6DecomposeSingleVarOne( p, pTruth, pVars, nVars, v ) ) { nVars--; break; } if ( v == -1 || nVars == 1 ) break; } if ( nVars == 1 ) Dau_DsdWriteVar( p, pVars[--nVars], (int)(pTruth[0] & 1) ); s_Times[0] += clock() - clk; return nVars; } static inline int Dau_Dsd6FindSupportOne( Dau_Dsd_t * p, word tCof0, word tCof1, int * pVars, int nVars, int v, int u ) { int Status = Dau_DsdLookupVarCache( p, pVars[v], pVars[u] ); if ( Status == 0 ) { Status = (Abc_Tt6HasVar(tCof1, u) << 1) | Abc_Tt6HasVar(tCof0, u); Dau_DsdInsertVarCache( p, pVars[v], pVars[u], Status ); } return Status; } static inline unsigned Dau_Dsd6FindSupports( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v ) { int u; unsigned uSupports = 0; word tCof0 = Abc_Tt6Cofactor0( pTruth[0], v ); word tCof1 = Abc_Tt6Cofactor1( pTruth[0], v ); //Kit_DsdPrintFromTruth( (unsigned *)&tCof0, 6 );printf( "\n" ); //Kit_DsdPrintFromTruth( (unsigned *)&tCof1, 6 );printf( "\n" ); for ( u = 0; u < nVars; u++ ) if ( u != v ) uSupports |= (Dau_Dsd6FindSupportOne( p, tCof0, tCof1, pVars, nVars, v, u ) << (2 * u)); return uSupports; } static inline void Dau_DsdPrintSupports( unsigned uSupp, int nVars ) { int v, Value; printf( "Cofactor supports: " ); for ( v = nVars - 1; v >= 0; v-- ) { Value = ((uSupp >> (2*v)) & 3); if ( Value == 1 ) printf( "01" ); else if ( Value == 2 ) printf( "10" ); else if ( Value == 3 ) printf( "11" ); else printf( "00" ); if ( v ) printf( "-" ); } printf( "\n" ); } // checks decomposability with respect to the pair (v, u) static inline int Dau_Dsd6DecomposeDoubleVarsOne( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v, int u ) { char pBuffer[10] = { 0 }; word tCof0 = Abc_Tt6Cofactor0( pTruth[0], v ); word tCof1 = Abc_Tt6Cofactor1( pTruth[0], v ); int Status = Dau_Dsd6FindSupportOne( p, tCof0, tCof1, pVars, nVars, v, u ); assert( v > u ); //printf( "Checking %s and %s.\n", p->pVarDefs[pVars[v]], p->pVarDefs[pVars[u]] ); // Kit_DsdPrintFromTruth( (unsigned *)pTruth, 6 );printf( "\n" ); if ( Status == 3 ) { // both F(v=0) and F(v=1) depend on u if ( Abc_Tt6Cof0EqualCof1(tCof0, tCof1, u) && Abc_Tt6Cof0EqualCof1(tCof1, tCof0, u) ) // v+u { pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor1(tCof0, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u)); sprintf( pBuffer, "[%c%c]", 'a' + pVars[v], 'a' + pVars[u] ); goto finish; } } else if ( Status == 2 ) { // F(v=0) does not depend on u; F(v=1) depends on u if ( Abc_Tt6Cof0EqualCof0(tCof0, tCof1, u) ) // vu { sprintf( pBuffer, "(%c%c)", 'a' + pVars[v], 'a' + pVars[u] ); pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor1(tCof1, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u)); goto finish; } if ( Abc_Tt6Cof0EqualCof1(tCof0, tCof1, u) ) // v!u { sprintf( pBuffer, "(%c!%c)", 'a' + pVars[v], 'a' + pVars[u] ); pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor0(tCof1, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u)); goto finish; } } else if ( Status == 1 ) { // F(v=0) depends on u; F(v=1) does not depend on u if ( Abc_Tt6Cof0EqualCof1(tCof0, tCof1, u) ) // !vu { sprintf( pBuffer, "(!%c%c)", 'a' + pVars[v], 'a' + pVars[u] ); pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor1(tCof0, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u)); goto finish; } if ( Abc_Tt6Cof1EqualCof1(tCof0, tCof1, u) ) // !v!u { sprintf( pBuffer, "(!%c!%c)", 'a' + pVars[v], 'a' + pVars[u] ); pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor1(tCof1, u)); goto finish; } } return nVars; finish: // finalize decomposition assert( pBuffer[0] ); pVars[u] = Dau_DsdAddVarDef( p, pBuffer ); pVars[v] = pVars[nVars-1]; Abc_TtSwapVars( pTruth, 6, v, nVars-1 ); if ( Dau_Dsd6DecomposeSingleVarOne( p, pTruth, pVars, --nVars, u ) ) nVars = Dau_Dsd6DecomposeSingleVar( p, pTruth, pVars, --nVars ); return nVars; } int Dau_Dsd6DecomposeDoubleVars( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars ) { clock_t clk = clock(); while ( 1 ) { int v, u, nVarsOld; for ( v = nVars - 1; v > 0; v-- ) { for ( u = v - 1; u >= 0; u-- ) { if ( Dau_DsdLookupVarCache( p, pVars[v], pVars[u] ) ) continue; nVarsOld = nVars; nVars = Dau_Dsd6DecomposeDoubleVarsOne( p, pTruth, pVars, nVars, v, u ); if ( nVars == 0 ) { s_Times[1] += clock() - clk; return 0; } if ( nVarsOld > nVars ) break; } if ( u >= 0 ) // found break; } if ( v == 0 ) // not found break; } s_Times[1] += clock() - clk; return nVars; } // look for MUX-decomposable variable on top or at the bottom static inline int Dau_Dsd6DecomposeTripleVarsOuter( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v ) { extern int Dau_DsdDecomposeInt( Dau_Dsd_t * p, word * pTruth, int nVarsInit ); Dau_Dsd_t P1, * p1 = &P1; word tCof0, tCof1; p1->fSplitPrime = 0; // move this variable to the top ABC_SWAP( int, pVars[v], pVars[nVars-1] ); Abc_TtSwapVars( pTruth, 6, v, nVars-1 ); // cofactor w.r.t the last variable tCof0 = Abc_Tt6Cofactor0( pTruth[0], nVars - 1 ); tCof1 = Abc_Tt6Cofactor1( pTruth[0], nVars - 1 ); // compose the result Dau_DsdWriteString( p, "<" ); Dau_DsdWriteVar( p, pVars[nVars - 1], 0 ); // split decomposition Dau_DsdDecomposeInt( p1, &tCof1, nVars - 1 ); Dau_DsdTranslate( p, pVars, nVars - 1, p1->pOutput ); p->nSizeNonDec = p1->nSizeNonDec; // split decomposition Dau_DsdDecomposeInt( p1, &tCof0, nVars - 1 ); Dau_DsdTranslate( p, pVars, nVars - 1, p1->pOutput ); Dau_DsdWriteString( p, ">" ); p->nSizeNonDec = Abc_MaxInt( p->nSizeNonDec, p1->nSizeNonDec ); return 0; } static inline int Dau_Dsd6DecomposeTripleVarsInner( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v, unsigned uSupports ) { int iVar0 = Abc_TtSuppFindFirst( uSupports & (~uSupports >> 1) & 0x55555555 ) >> 1; int iVar1 = Abc_TtSuppFindFirst( ~uSupports & ( uSupports >> 1) & 0x55555555 ) >> 1; word tCof0 = Abc_Tt6Cofactor0( pTruth[0], v ); word tCof1 = Abc_Tt6Cofactor1( pTruth[0], v ); word C00 = Abc_Tt6Cofactor0( tCof0, iVar0 ); word C01 = Abc_Tt6Cofactor1( tCof0, iVar0 ); word C10 = Abc_Tt6Cofactor0( tCof1, iVar1 ); word C11 = Abc_Tt6Cofactor1( tCof1, iVar1 ); int fEqual0 = (C00 == C10) && (C01 == C11); int fEqual1 = (C00 == C11) && (C01 == C10); // assert( iVar0 < iVar1 ); // fEqual0 = Abc_TtCheckEqualCofs( &t, 1, iVar0, iVar1, 0, 2 ) && Abc_TtCheckEqualCofs( &t, 1, iVar0, iVar1, 1, 3 ); // fEqual1 = Abc_TtCheckEqualCofs( &t, 1, iVar0, iVar1, 0, 3 ) && Abc_TtCheckEqualCofs( &t, 1, iVar0, iVar1, 1, 2 ); if ( fEqual0 || fEqual1 ) { char pBuffer[10]; int VarId = pVars[iVar0]; pTruth[0] = (s_Truths6[v] & C11) | (~s_Truths6[v] & C10); sprintf( pBuffer, "<%c%c%s%c>", 'a' + pVars[v], 'a' + pVars[iVar1], fEqual1 ? "!":"", 'a' + pVars[iVar0] ); pVars[v] = Dau_DsdAddVarDef( p, pBuffer ); // remove iVar1 ABC_SWAP( int, pVars[iVar1], pVars[nVars-1] ); Abc_TtSwapVars( pTruth, 6, iVar1, --nVars ); // remove iVar0 iVar0 = Dau_DsdFindVarDef( pVars, nVars, VarId ); ABC_SWAP( int, pVars[iVar0], pVars[nVars-1] ); Abc_TtSwapVars( pTruth, 6, iVar0, --nVars ); // find the new var v = Dau_DsdFindVarDef( pVars, nVars, p->nVarsUsed-1 ); // remove single variables if possible if ( Dau_Dsd6DecomposeSingleVarOne( p, pTruth, pVars, nVars, v ) ) nVars = Dau_Dsd6DecomposeSingleVar( p, pTruth, pVars, --nVars ); return nVars; } return nVars; } int Dau_Dsd6DecomposeTripleVars( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars ) { clock_t clk = clock(); while ( 1 ) { int v; // Kit_DsdPrintFromTruth( (unsigned *)pTruth, 6 ); printf( "\n" ); for ( v = nVars - 1; v >= 0; v-- ) { unsigned uSupports = Dau_Dsd6FindSupports( p, pTruth, pVars, nVars, v ); // Dau_DsdPrintSupports( uSupports, nVars ); if ( (uSupports & (uSupports >> 1) & 0x55555555) == 0 ) // non-overlapping supports return Dau_Dsd6DecomposeTripleVarsOuter( p, pTruth, pVars, nVars, v ); if ( Abc_TtSuppOnlyOne( uSupports & (~uSupports >> 1) & 0x55555555) && Abc_TtSuppOnlyOne(~uSupports & ( uSupports >> 1) & 0x55555555) ) // one unique variable in each cofactor { int nVarsNew = Dau_Dsd6DecomposeTripleVarsInner( p, pTruth, pVars, nVars, v, uSupports ); if ( nVarsNew == nVars ) continue; if ( nVarsNew == 0 ) { s_Times[2] += clock() - clk; return 0; } nVars = Dau_Dsd6DecomposeDoubleVars( p, pTruth, pVars, nVarsNew ); if ( nVars == 0 ) { s_Times[2] += clock() - clk; return 0; } break; } } if ( v == -1 ) { s_Times[2] += clock() - clk; return nVars; } } assert( 0 ); return -1; } int Dau_Dsd6DecomposeInternal( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars ) { // decompose single variales on the output side nVars = Dau_Dsd6DecomposeSingleVar( p, pTruth, pVars, nVars ); if ( nVars == 0 ) return 0; // decompose double variables on the input side nVars = Dau_Dsd6DecomposeDoubleVars( p, pTruth, pVars, nVars ); if ( nVars == 0 ) return 0; // decompose MUX on the output/input side nVars = Dau_Dsd6DecomposeTripleVars( p, pTruth, pVars, nVars ); if ( nVars == 0 ) return 0; // write non-decomposable function return Dau_DsdWritePrime( p, pTruth, pVars, nVars ); } /**Function************************************************************* Synopsis [Procedures specialized for 6-variable functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dau_DsdDecomposeSingleVar( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars ) { return 0; } int Dau_DsdDecomposeDoubleVars( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars ) { return 0; } int Dau_DsdDecomposeTripleVars( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars ) { return 0; } int Dau_DsdDecomposeInternal( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars ) { // decompose single variales on the output side nVars = Dau_DsdDecomposeSingleVar( p, pTruth, pVars, nVars ); if ( nVars == 0 ) return 0; // decompose double variables on the input side nVars = Dau_DsdDecomposeDoubleVars( p, pTruth, pVars, nVars ); if ( nVars == 0 ) return 0; // decompose MUX on the output/input side nVars = Dau_DsdDecomposeTripleVars( p, pTruth, pVars, nVars ); if ( nVars == 0 ) return 0; // write non-decomposable function return Dau_DsdWritePrime( p, pTruth, pVars, nVars ); } /**Function************************************************************* Synopsis [Fast DSD for truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dau_DsdMinBase( word * pTruth, int nVars, int * pVarsNew ) { int v; for ( v = 0; v < nVars; v++ ) pVarsNew[v] = v; for ( v = nVars - 1; v >= 0; v-- ) { if ( Abc_TtHasVar( pTruth, nVars, v ) ) continue; Abc_TtSwapVars( pTruth, nVars, v, nVars-1 ); pVarsNew[v] = pVarsNew[--nVars]; } return nVars; } int Dau_DsdDecomposeInt( Dau_Dsd_t * p, word * pTruth, int nVarsInit ) { int Status = 0, nVars, pVars[16]; Dau_DsdInitialize( p, nVarsInit ); nVars = Dau_DsdMinBase( pTruth, nVarsInit, pVars ); assert( nVars > 0 && nVars <= 6 ); if ( nVars == 1 ) Dau_DsdWriteVar( p, pVars[0], (int)(pTruth[0] & 1) ); else if ( nVars <= 6 ) Status = Dau_Dsd6DecomposeInternal( p, pTruth, pVars, nVars ); else Status = Dau_DsdDecomposeInternal( p, pTruth, pVars, nVars ); Dau_DsdFinalize( p ); return Status; } int Dau_DsdDecompose( word * pTruth, int nVarsInit, int fSplitPrime, char * pRes ) { Dau_Dsd_t P, * p = &P; p->fSplitPrime = fSplitPrime; p->nSizeNonDec = 0; if ( (pTruth[0] & 1) == 0 && Abc_TtIsConst0(pTruth, Abc_TtWordNum(nVarsInit)) ) pRes[0] = '0', pRes[1] = 0; else if ( (pTruth[0] & 1) && Abc_TtIsConst1(pTruth, Abc_TtWordNum(nVarsInit)) ) pRes[0] = '1', pRes[1] = 0; else { int Status = Dau_DsdDecomposeInt( p, pTruth, nVarsInit ); Dau_DsdRemoveBraces( p->pOutput, Dau_DsdComputeMatches(p->pOutput) ); if ( pRes ) strcpy( pRes, p->pOutput ); assert( fSplitPrime || Status != 1 ); if ( fSplitPrime && Status == 2 ) return -1; } return p->nSizeNonDec; } void Dau_DsdTest44() { char pRes[DAU_MAX_STR]; // char * pStr = "(!(!a)!(!fe))"; // char * pStr = "([acb])"; // char * pStr = "!(f!(b!c!(d[ea])))"; // char * pStr = "[!(a[be])!(c!df)]"; // char * pStr = "<(e)fd>"; // char * pStr = "[d8001{abef}c]"; char * pStr = "[dc{abef}]"; // char * pStr3; word t = Dau_Dsd6ToTruth( pStr ); // return; int nNonDec = Dau_DsdDecompose( &t, 6, 1, pRes ); // Dau_DsdNormalize( pStr2 ); // Dau_DsdExtract( pStr, 2, 0 ); t = 0; } void Dau_DsdTest33() { char * pFileName = "_npn/npn/dsd06.txt"; FILE * pFile = fopen( pFileName, "rb" ); word t, t1, t2; char pBuffer[100]; char pRes[DAU_MAX_STR]; int nSizeNonDec; int i, Counter = 0; clock_t clk = clock(); while ( fgets( pBuffer, 100, pFile ) != NULL ) { char * pStr2 = pBuffer + strlen(pBuffer)-1; if ( *pStr2 == '\n' ) *pStr2-- = 0; if ( *pStr2 == '\r' ) *pStr2-- = 0; if ( pBuffer[0] == 'V' || pBuffer[0] == 0 ) continue; Counter++; for ( i = 0; i < 1000; i++ ) { Dau_DsdPermute( pBuffer ); t = t1 = Dau_Dsd6ToTruth( pBuffer[0] == '*' ? pBuffer + 1 : pBuffer ); nSizeNonDec = Dau_DsdDecompose( &t, 6, 0, pRes ); Dau_DsdNormalize( pRes ); // pStr2 = Dau_DsdPerform( t ); nSizeNonDec = 0; assert( nSizeNonDec == 0 ); t2 = Dau_Dsd6ToTruth( pRes ); if ( t1 != t2 ) { // Kit_DsdPrintFromTruth( (unsigned *)&t, 6 ); // printf( " " ); // Kit_DsdPrintFromTruth( (unsigned *)&t2, 6 ); printf( "%s -> %s \n", pBuffer, pStr2 ); printf( "Verification failed.\n" ); } } } printf( "Finished trying %d decompositions. ", Counter ); Abc_PrintTime( 1, "Time", clock() - clk ); Abc_PrintTime( 1, "Time1", s_Times[0] ); Abc_PrintTime( 1, "Time2", s_Times[1] ); Abc_PrintTime( 1, "Time3", s_Times[2] ); fclose( pFile ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END