diff options
Diffstat (limited to 'src/opt')
-rw-r--r-- | src/opt/dau/dauGia.c | 50 | ||||
-rw-r--r-- | src/opt/dsc/dsc.c | 525 | ||||
-rw-r--r-- | src/opt/dsc/dsc.h | 91 | ||||
-rw-r--r-- | src/opt/dsc/module.make | 1 | ||||
-rw-r--r-- | src/opt/sbd/module.make | 5 | ||||
-rw-r--r-- | src/opt/sbd/sbd.c | 53 | ||||
-rw-r--r-- | src/opt/sbd/sbd.h | 75 | ||||
-rw-r--r-- | src/opt/sbd/sbdCnf.c | 147 | ||||
-rw-r--r-- | src/opt/sbd/sbdCore.c | 1520 | ||||
-rw-r--r-- | src/opt/sbd/sbdInt.h | 78 | ||||
-rw-r--r-- | src/opt/sbd/sbdSat.c | 797 | ||||
-rw-r--r-- | src/opt/sbd/sbdSim.c | 310 | ||||
-rw-r--r-- | src/opt/sbd/sbdWin.c | 283 |
13 files changed, 3923 insertions, 12 deletions
diff --git a/src/opt/dau/dauGia.c b/src/opt/dau/dauGia.c index b75ded61..5e74ad21 100644 --- a/src/opt/dau/dauGia.c +++ b/src/opt/dau/dauGia.c @@ -238,12 +238,28 @@ int Dau_DsdBalance( Gia_Man_t * pGia, int * pFans, int nFans, int fAnd ) assert( nFans > 1 ); iFan0 = pFans[--nFans]; iFan1 = pFans[--nFans]; - if ( fAnd ) - iFan = Gia_ManHashAnd( pGia, iFan0, iFan1 ); - else if ( pGia->pMuxes ) - iFan = Gia_ManHashXorReal( pGia, iFan0, iFan1 ); - else - iFan = Gia_ManHashXor( pGia, iFan0, iFan1 ); + if ( pGia->pHTable == NULL ) + { + if ( fAnd ) + iFan = Gia_ManAppendAnd( pGia, iFan0, iFan1 ); + else if ( pGia->pMuxes ) + { + int fCompl = Abc_LitIsCompl(iFan0) ^ Abc_LitIsCompl(iFan1); + iFan = Gia_ManAppendXorReal( pGia, Abc_LitRegular(iFan0), Abc_LitRegular(iFan1) ); + iFan = Abc_LitNotCond( iFan, fCompl ); + } + else + iFan = Gia_ManAppendXor( pGia, iFan0, iFan1 ); + } + else + { + if ( fAnd ) + iFan = Gia_ManHashAnd( pGia, iFan0, iFan1 ); + else if ( pGia->pMuxes ) + iFan = Gia_ManHashXorReal( pGia, iFan0, iFan1 ); + else + iFan = Gia_ManHashXor( pGia, iFan0, iFan1 ); + } pObj = Gia_ManObj(pGia, Abc_Lit2Var(iFan)); if ( Gia_ObjIsAnd(pObj) ) { @@ -340,14 +356,24 @@ int Dau_DsdToGia_rec( Gia_Man_t * pGia, char * pStr, char ** p, int * pMatches, assert( **p == '{' && *q == '}' ); *p = q; } - if ( pGia->pMuxes ) - Res = Gia_ManHashMuxReal( pGia, Temp[0], Temp[1], Temp[2] ); + if ( pGia->pHTable == NULL ) + { + if ( pGia->pMuxes ) + Res = Gia_ManAppendMux( pGia, Temp[0], Temp[1], Temp[2] ); + else + Res = Gia_ManAppendMux( pGia, Temp[0], Temp[1], Temp[2] ); + } else - Res = Gia_ManHashMux( pGia, Temp[0], Temp[1], Temp[2] ); + { + if ( pGia->pMuxes ) + Res = Gia_ManHashMuxReal( pGia, Temp[0], Temp[1], Temp[2] ); + else + Res = Gia_ManHashMux( pGia, Temp[0], Temp[1], Temp[2] ); + } pObj = Gia_ManObj(pGia, Abc_Lit2Var(Res)); if ( Gia_ObjIsAnd(pObj) ) { - if ( pGia->pMuxes ) + if ( pGia->pMuxes && pGia->pHTable != NULL ) Gia_ObjSetMuxLevel( pGia, pObj ); else { @@ -377,7 +403,7 @@ int Dau_DsdToGia_rec( Gia_Man_t * pGia, char * pStr, char ** p, int * pMatches, vLeaves.nSize = nVars; vLeaves.pArray = Fanins; nObjOld = Gia_ManObjNum(pGia); - Res = Kit_TruthToGia( pGia, (unsigned *)pFunc, nVars, vCover, &vLeaves, 1 ); + Res = Kit_TruthToGia( pGia, (unsigned *)pFunc, nVars, vCover, &vLeaves, pGia->pHTable != NULL ); // assert( nVars <= 6 ); // Res = Dau_DsdToGiaCompose_rec( pGia, pFunc[0], Fanins, nVars ); for ( i = nObjOld; i < Gia_ManObjNum(pGia); i++ ) @@ -434,7 +460,7 @@ int Dsm_ManTruthToGia( void * p, word * pTruth, Vec_Int_t * vLeaves, Vec_Int_t * if ( nSizeNonDec ) m_NonDsd++; // printf( "%s\n", pDsd ); - if ( fDelayBalance ) + if ( fDelayBalance && pGia->vLevels ) return Dau_DsdToGia( pGia, pDsd, Vec_IntArray(vLeaves), vCover ); else return Dau_DsdToGia2( pGia, pDsd, Vec_IntArray(vLeaves), vCover ); diff --git a/src/opt/dsc/dsc.c b/src/opt/dsc/dsc.c new file mode 100644 index 00000000..ce180fe3 --- /dev/null +++ b/src/opt/dsc/dsc.c @@ -0,0 +1,525 @@ +/**CFile**************************************************************** + + FileName [dsc.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Disjoint support decomposition - ICCD'15] + + Synopsis [Disjoint-support decomposition with cofactoring and boolean difference analysis + from V. Callegaro, F. S. Marranghello, M. G. A. Martins, R. P. Ribas and A. I. Reis, + "Bottom-up disjoint-support decomposition based on cofactor and boolean difference analysis," ICCD'15] + + Author [Vinicius Callegaro, Mayler G. A. Martins, Felipe S. Marranghello, Renato P. Ribas and Andre I. Reis] + + Affiliation [UFRGS - Federal University of Rio Grande do Sul - Brazil] + + Date [Ver. 1.0. Started - October 24, 2014.] + + Revision [$Id: dsc.h,v 1.00 2014/10/24 00:00:00 vcallegaro Exp $] + +***********************************************************************/ + +#include "dsc.h" +#include <assert.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; +*/ +typedef struct Dsc_node_t_ Dsc_node_t; +struct Dsc_node_t_ +{ + word *pNegCof; + word *pPosCof; + word *pBoolDiff; + unsigned int on[DSC_MAX_VAR+1]; // pos cofactor spec - first element denotes the size of the array + unsigned int off[DSC_MAX_VAR+1]; // neg cofactor spec - first element denotes the size of the array + char exp[DSC_MAX_STR]; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +inline void xorInPlace( word * pOut, word * pIn2, int nWords) +{ + int w; + for ( w = 0; w < nWords; w++ ) + pOut[w] ^= pIn2[w]; +} + +void dsc_debug_node(Dsc_node_t * pNode, int nVars, const int TRUTH_WORDS) { + int i; + printf("Node:\t%s\n",pNode->exp); + printf("\tneg cof:\t");Abc_TtPrintHexRev(stdout, pNode->pNegCof, nVars); + printf("\tpos cof:\t");Abc_TtPrintHexRev(stdout, pNode->pPosCof, nVars); + printf("\tbool diff:\t");Abc_TtPrintHexRev(stdout, pNode->pBoolDiff, nVars); + printf("\toff:\t"); + for (i=1;i<=(int)pNode->off[0];i++) { + printf("%c%c", (pNode->off[i] & 1U) ? ' ' : '!', 'a'+(pNode->off[i] >> 1)); + } + printf("\ton:\t"); + for (i=1;i<=(int)pNode->on[0];i++) { + printf("%c%c", (pNode->on[i] & 1U) ? ' ' : '!', 'a'+(pNode->on[i] >> 1)); + } + printf("\n"); +} + +inline int dsc_and_test(Dsc_node_t *ni, Dsc_node_t *nj, const int TRUTH_WORDS, int* ci, int* cj) { + if (Abc_TtEqual(ni->pNegCof, nj->pNegCof, TRUTH_WORDS)) {*ci=1; *cj=1; return 1;} + else if (Abc_TtEqual(ni->pNegCof, nj->pPosCof, TRUTH_WORDS)) {*ci=1; *cj=0; return 1;} + else if (Abc_TtEqual(ni->pPosCof, nj->pNegCof, TRUTH_WORDS)) {*ci=0; *cj=1; return 1;} + else if (Abc_TtEqual(ni->pPosCof, nj->pPosCof, TRUTH_WORDS)) {*ci=0; *cj=0; return 1;} + return 0; +} + +inline int dsc_xor_test(Dsc_node_t *ni, Dsc_node_t *nj, const int TRUTH_WORDS) { + return Abc_TtEqual(ni->pBoolDiff, nj->pBoolDiff, TRUTH_WORDS); +} + +void concat(char* target, char begin, char end, char* s1, int s1Polarity, char* s2, int s2Polarity) { + *target++ = begin; + //s1 + if (!s1Polarity) + *target++ = '!'; + while (*s1 != '\0') + *target++ = *s1++; + // s2 + if (!s2Polarity) + *target++ = '!'; + while (*s2 != '\0') + *target++ = *s2++; + // end + *target++ = end; + *target = '\0'; +} + +void cubeCofactor(word * const pTruth, const unsigned int * const cubeCof, const int TRUTH_WORDS) { + int size = cubeCof[0]; + int i; + for (i = 1; i <= size; i++) { + unsigned int c = cubeCof[i]; + if (c & 1U) { + Abc_TtCofactor1(pTruth, TRUTH_WORDS, c >> 1); + } else { + Abc_TtCofactor0(pTruth, TRUTH_WORDS, c >> 1); + } + } +} + +void merge(unsigned int * const pOut, const unsigned int * const pIn) { + const int elementsToCopy = pIn[0]; + int i, j; + for (i = pOut[0]+1, j = 1; j <= elementsToCopy; i++, j++) { + pOut[i] = pIn[j]; + } + pOut[0] += elementsToCopy; +} + +void dsc_and_group(Dsc_node_t * pOut, Dsc_node_t * ni, int niPolarity, Dsc_node_t * nj, int njPolarity, int nVars, const int TRUTH_WORDS) { + unsigned int* xiOFF, * xiON, * xjOFF, * xjON; + // expression + concat(pOut->exp, '(', ')', ni->exp, niPolarity, nj->exp, njPolarity); + // ON-OFF + if (niPolarity) { + xiOFF = ni->off; + xiON = ni->on; + } else { + xiOFF = ni->on; + xiON = ni->off; + } + if (njPolarity) { + xjOFF = nj->off; + xjON = nj->on; + } else { + xjOFF = nj->on; + xjON = nj->off; + } + // creating both the new OFF specification and negative cofactor of the new group + { + // first element of the array represents the size of the cube-cofactor + int xiOFFSize = xiOFF[0]; + int xjOFFSize = xjOFF[0]; + if (xiOFFSize <= xjOFFSize) { + int i; + pOut->off[0] = xiOFFSize; // set the number of elements + for (i = 1; i <= xiOFFSize; i++) { + pOut->off[i] = xiOFF[i]; + } + } else { + int i; + pOut->off[0] = xjOFFSize; // set the number of elements + for (i = 1; i <= xjOFFSize; i++) { + pOut->off[i] = xjOFF[i]; + } + } + // set the negative cofactor of the new group + pOut->pNegCof = niPolarity ? ni->pNegCof : ni->pPosCof; + } + // creating both new ON specification and positive cofactor of the new group + { + int i; + int j; + unsigned int xiONSize = xiON[0]; + unsigned int xjONSize = xjON[0]; + pOut->on[0] = xiONSize + xjONSize; + for (i = 1; i <= (int)xiONSize; i++) { + pOut->on[i] = xiON[i]; + } + for (j = 1; j <= (int)xjONSize; j++) { + pOut->on[i++] = xjON[j]; + } + // set the positive cofactor of the new group + if (xiONSize >= xjONSize) { + pOut->pPosCof = niPolarity ? ni->pPosCof : ni->pNegCof; + cubeCofactor(pOut->pPosCof, xjON, TRUTH_WORDS); + } else { + pOut->pPosCof = njPolarity ? nj->pPosCof : nj->pNegCof; + cubeCofactor(pOut->pPosCof, xiON, TRUTH_WORDS); + } + } + // set the boolean difference of the new group + pOut->pBoolDiff = njPolarity ? nj->pNegCof : nj->pPosCof; + xorInPlace(pOut->pBoolDiff, pOut->pPosCof, TRUTH_WORDS); +} + +void dsc_xor_group(Dsc_node_t * pOut, Dsc_node_t * ni, Dsc_node_t * nj, int nVars, const int TRUTH_WORDS) { + // + const unsigned int * xiOFF = ni->off; + const unsigned int * xiON = ni->on; + const unsigned int * xjOFF = nj->off; + const unsigned int * xjON = nj->on; + // + const int xiOFFSize = xiOFF[0]; + const int xiONSize = xiON[0]; + const int xjOFFSize = xjOFF[0]; + const int xjONSize = xjON[0]; + // minCubeCofs + int minCCSize = xiOFFSize; + int minCCPolarity = 0; + Dsc_node_t * minCCNode = ni; + // expression + concat(pOut->exp, '[', ']', ni->exp, 1, nj->exp, 1); + if (minCCSize > xiONSize) { + minCCSize = xiONSize; + minCCPolarity = 1; + //minCCNode = ni; + } + if (minCCSize > xjOFFSize) { + minCCSize = xjOFFSize; + minCCPolarity = 0; + minCCNode = nj; + } + if (minCCSize > xjONSize) { + minCCSize = xjONSize; + minCCPolarity = 1; + minCCNode = nj; + } + // + if (minCCNode == ni) { + if (minCCPolarity) { + // gOFF = xiON, xjON + pOut->pNegCof = nj->pPosCof; + cubeCofactor(pOut->pNegCof, xiON, TRUTH_WORDS); + // gON = xiON, xjOFF + pOut->pPosCof = nj->pNegCof; + cubeCofactor(pOut->pPosCof, xiON, TRUTH_WORDS); + } else { + // gOFF = xiOFF, xjOFF + pOut->pNegCof = nj->pNegCof; + cubeCofactor(pOut->pNegCof, xiOFF, TRUTH_WORDS); + // gON = xiOFF, xjON + pOut->pPosCof = nj->pPosCof; + cubeCofactor(pOut->pPosCof, xiOFF, TRUTH_WORDS); + } + }else { + if (minCCPolarity) { + // gOFF = xjON, xiON + pOut->pNegCof = ni->pPosCof; + cubeCofactor(pOut->pNegCof, xjON, TRUTH_WORDS); + // gON = xjON, xiOFF + pOut->pPosCof = ni->pNegCof; + cubeCofactor(pOut->pPosCof, xjON, TRUTH_WORDS); + } else { + // gOFF = xjOFF, xiOFF + pOut->pNegCof = ni->pNegCof; + cubeCofactor(pOut->pNegCof, xjOFF, TRUTH_WORDS); + // gON = xjOFF, xiON + pOut->pPosCof = ni->pPosCof; + cubeCofactor(pOut->pPosCof, xjOFF, TRUTH_WORDS); + } + } + // bool diff + pOut->pBoolDiff = ni->pBoolDiff; + // evaluating specs + // off spec + pOut->off[0] = 0; + if ((xiOFFSize+xjOFFSize) <= (xiONSize+xjONSize)) { + merge(pOut->off, xiOFF); + merge(pOut->off, xjOFF); + } else { + merge(pOut->off, xiON); + merge(pOut->off, xjON); + } + // on spec + pOut->on[0] = 0; + if ((xiOFFSize+xjONSize) <= (xiONSize+xjOFFSize)) { + merge(pOut->on, xiOFF); + merge(pOut->on, xjON); + } else { + merge(pOut->on, xiON); + merge(pOut->on, xjOFF); + } +} + +/** + * memory allocator with a capacity of storing 3*nVars + * truth-tables for negative and positive cofactors and + * the boolean difference for each input variable + */ +extern word * Dsc_alloc_pool(int nVars) { + return ABC_ALLOC(word, 3 * Abc_TtWordNum(nVars) * nVars); +} + +/** + * just free the memory pool + */ +extern void Dsc_free_pool(word * pool) { + ABC_FREE(pool); +} + +/** + * This method implements the paper proposed by V. Callegaro, F. S. Marranghello, M. G. A. Martins, R. P. Ribas and A. I. Reis, + * entitled "Bottom-up disjoint-support decomposition based on cofactor and boolean difference analysis", presented at ICCD 2015. + * pTruth: pointer for the truth table representing the target function. + * nVarsInit: the number of variables of the truth table of the target function. + * pRes: pointer for storing the resulting decomposition, whenever a decomposition can be found. + * pool: NULL or a pointer for with a capacity of storing 3*nVars truth-tables. IF NULL, the function will allocate and free the memory of each call. + * (the results presented on ICCD paper are running this method with NULL for the memory pool). + * The method returns 0 if a full decomposition was found and a negative value otherwise. + */ +extern int Dsc_Decompose(word * pTruth, const int nVarsInit, char * const pRes, word *pool) { + const int TRUTH_WORDS = Abc_TtWordNum(nVarsInit); + const int NEED_POOL_ALLOC = (pool == NULL); + + Dsc_node_t nodes[DSC_MAX_VAR]; + Dsc_node_t *newNodes[DSC_MAX_VAR]; + Dsc_node_t *oldNodes[DSC_MAX_VAR]; + + Dsc_node_t freeNodes[DSC_MAX_VAR]; // N is the maximum number of possible groups. + int f = 0; // f represent the next free position in the freeNodes array + int o = 0; // o stands for the number of already tested nodes + int n = 0; // n will represent the number of current nodes (i.e. support) + + pRes[0] = '\0'; + pRes[1] = '\0'; + + if (NEED_POOL_ALLOC) + pool = ABC_ALLOC(word, 3 * TRUTH_WORDS * nVarsInit); + + // block for the node data allocation + { + // pointer for the next free truth word + word *pNextTruth = pool; + int iVar; + for (iVar = 0; iVar < nVarsInit; iVar++) { + // negative cofactor + Abc_TtCofactor0p(pNextTruth, pTruth, TRUTH_WORDS, iVar); + // dont care test + if (!Abc_TtEqual(pNextTruth, pTruth, TRUTH_WORDS)) { + Dsc_node_t *node = &nodes[iVar]; + node->pNegCof = pNextTruth; + // increment next truth pointer + pNextTruth += TRUTH_WORDS; + // positive cofactor + node->pPosCof = pNextTruth; + Abc_TtCofactor1p(node->pPosCof, pTruth, TRUTH_WORDS, iVar); + // increment next truth pointer + pNextTruth += TRUTH_WORDS; + // boolean difference + node->pBoolDiff = pNextTruth; + Abc_TtXor(node->pBoolDiff, node->pNegCof, node->pPosCof, TRUTH_WORDS, 0); + // increment next truth pointer + pNextTruth += TRUTH_WORDS; + // define on spec - + node->on[0] = 1; node->on[1] = (iVar << 1) | 1u; // lit = i*2+1, when polarity=true + // define off spec + node->off[0] = 1; node->off[1] = iVar << 1;// lit=i*2 otherwise + // store the node expression + node->exp[0] = 'a'+iVar; // TODO fix the variable names + node->exp[1] = '\0'; + // add the node to the newNodes array + newNodes[n++] = node; + } + } + } + //const int initialSupport = n; + if (n == 0) { + if (NEED_POOL_ALLOC) + ABC_FREE(pool); + if (Abc_TtIsConst0(pTruth, TRUTH_WORDS)) { + { if ( pRes ) pRes[0] = '0', pRes[1] = '\0'; } + return 0; + } else if (Abc_TtIsConst1(pTruth, TRUTH_WORDS)) { + { if ( pRes ) pRes[0] = '1', pRes[1] = '\0'; } + return 0; + } else { + Abc_Print(-1, "ERROR. No variable in the support of f, but f isn't constant!\n"); + return -1; + } + } + while (n > 0) { + int tempN = 0; + int i, j, iPolarity, jPolarity; + Dsc_node_t *ni, *nj, *newNode = NULL; + for (i = 0; i < n; i++) { + ni = newNodes[i]; + newNode = NULL; + j = 0; + while (j < o) { + nj = oldNodes[j]; + if (dsc_and_test(ni, nj, TRUTH_WORDS, &iPolarity, &jPolarity)) { + newNode = &freeNodes[f++]; + dsc_and_group(newNode, ni, iPolarity, nj, jPolarity, nVarsInit, TRUTH_WORDS); + } + // XOR test + if ((newNode == NULL) && (dsc_xor_test(ni, nj, TRUTH_WORDS))) { + newNode = &freeNodes[f++]; + dsc_xor_group(newNode, ni, nj, nVarsInit, TRUTH_WORDS); + } + if (newNode != NULL) { + oldNodes[j] = oldNodes[--o]; + break; + } else { + j++; + } + } + if (newNode != NULL) { + newNodes[tempN++] = newNode; + } else { + oldNodes[o++] = ni; + } + } + n = tempN; + } + if (o == 1) { + Dsc_node_t * solution = oldNodes[0]; + if (Abc_TtIsConst0(solution->pNegCof, TRUTH_WORDS) && Abc_TtIsConst1(solution->pPosCof, TRUTH_WORDS)) { + // Direct solution found + if ( pRes ) + strcpy( pRes, solution->exp); + if (NEED_POOL_ALLOC) + ABC_FREE(pool); + return 0; + } else if (Abc_TtIsConst1(solution->pNegCof, TRUTH_WORDS) && Abc_TtIsConst0(solution->pPosCof, TRUTH_WORDS)) { + // Complementary solution found + if ( pRes ) { + pRes[0] = '!'; + strcpy( &pRes[1], solution->exp); + } + if (NEED_POOL_ALLOC) + ABC_FREE(pool); + return 0; + } else { + printf("DSC ERROR: Final DSC node found, but differs from target function.\n"); + if (NEED_POOL_ALLOC) + ABC_FREE(pool); + return -1; + } + } + if (NEED_POOL_ALLOC) + ABC_FREE(pool); + return -1; +} + + +/**Function************************************************************* + Synopsis [DSD formula manipulation.] + Description [Code copied from dauDsd.c but changed DAU_MAX_VAR to DSC_MAX_VAR] +***********************************************************************/ +int * Dsc_ComputeMatches( char * p ) +{ + static int pMatches[DSC_MAX_VAR]; + int pNested[DSC_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 < DSC_MAX_VAR ); + } + assert( nNested == 0 ); + return pMatches; +} + +/**Function************************************************************* + Synopsis [DSD formula manipulation.] + Description [Code copied from dauDsd.c but changed DAU_MAX_VAR to DSC_MAX_VAR] +***********************************************************************/ +int Dsc_CountAnds_rec( char * pStr, char ** p, int * pMatches ) +{ + if ( **p == '!' ) + (*p)++; + while ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') ) + (*p)++; + if ( **p == '<' ) + { + char * q = pStr + pMatches[*p - pStr]; + if ( *(q+1) == '{' ) + *p = q+1; + } + if ( **p >= 'a' && **p <= 'z' ) // var + return 0; + if ( **p == '(' || **p == '[' ) // and/or/xor + { + int Counter = 0, AddOn = (**p == '(')? 1 : 3; + char * q = pStr + pMatches[ *p - pStr ]; + assert( *q == **p + 1 + (**p != '(') ); + for ( (*p)++; *p < q; (*p)++ ) + Counter += AddOn + Dsc_CountAnds_rec( pStr, p, pMatches ); + assert( *p == q ); + return Counter - AddOn; + } + if ( **p == '<' || **p == '{' ) // mux + { + int Counter = 3; + char * q = pStr + pMatches[ *p - pStr ]; + assert( *q == **p + 1 + (**p != '(') ); + for ( (*p)++; *p < q; (*p)++ ) + Counter += Dsc_CountAnds_rec( pStr, p, pMatches ); + assert( *p == q ); + return Counter; + } + assert( 0 ); + return 0; +} +/**Function************************************************************* + Synopsis [DSD formula manipulation.] + Description [Code copied from dauDsd.c but changed DAU_MAX_VAR to DSC_MAX_VAR] +***********************************************************************/ +extern int Dsc_CountAnds( char * pDsd ) +{ + if ( pDsd[1] == 0 ) + return 0; + return Dsc_CountAnds_rec( pDsd, &pDsd, Dsc_ComputeMatches(pDsd) ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END diff --git a/src/opt/dsc/dsc.h b/src/opt/dsc/dsc.h new file mode 100644 index 00000000..bf8958ea --- /dev/null +++ b/src/opt/dsc/dsc.h @@ -0,0 +1,91 @@ +/**CFile**************************************************************** + + FileName [dsc.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Disjoint support decomposition - ICCD'15] + + Synopsis [Disjoint-support decomposition with cofactoring and boolean difference analysis + from V. Callegaro, F. S. Marranghello, M. G. A. Martins, R. P. Ribas and A. I. Reis, + "Bottom-up disjoint-support decomposition based on cofactor and boolean difference analysis," ICCD'15] + + Author [Vinicius Callegaro, Mayler G. A. Martins, Felipe S. Marranghello, Renato P. Ribas and Andre I. Reis] + + Affiliation [UFRGS - Federal University of Rio Grande do Sul - Brazil] + + Date [Ver. 1.0. Started - October 24, 2014.] + + Revision [$Id: dsc.h,v 1.00 2014/10/24 00:00:00 vcallegaro Exp $] + +***********************************************************************/ + +#ifndef ABC__DSC___h +#define ABC__DSC___h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// +#include <stdio.h> +#include <string.h> +#include "misc/util/abc_global.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_HEADER_START + +#define DSC_MAX_VAR 16 // should be 6 or more, i.e. DSC_MAX_VAR >= 6 +#define DSC_MAX_STR DSC_MAX_VAR << 2 // DSC_MAX_VAR * 4 + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== dsc.c ==========================================================*/ + +/** + * memory allocator with a capacity of storing 3*nVars + * truth-tables for negative and positive cofactors and + * the boolean difference for each input variable + */ +extern word * Dsc_alloc_pool(int nVars); + +/** + * This method implements the paper proposed by V. Callegaro, F. S. Marranghello, M. G. A. Martins, R. P. Ribas and A. I. Reis, + * entitled "Bottom-up disjoint-support decomposition based on cofactor and boolean difference analysis", presented at ICCD 2015. + * pTruth: pointer for the truth table representing the target function. + * nVarsInit: the number of variables of the truth table of the target function. + * pRes: pointer for storing the resulting decomposition, whenever a decomposition can be found. + * pool: NULL or a pointer for with a capacity of storing 3*nVars truth-tables. IF NULL, the function will allocate and free the memory of each call. + * (the results presented on ICCD paper are running this method with NULL for the memory pool). + * The method returns 0 if a full decomposition was found and a negative value otherwise. + */ +extern int Dsc_Decompose(word * pTruth, const int nVarsInit, char * const pRes, word *pool); + +/** + * just free the memory pool + */ +extern void Dsc_free_pool(word * pool); + +int * Dsc_ComputeMatches( char * p ); +int Dsc_CountAnds_rec( char * pStr, char ** p, int * pMatches ); +extern int Dsc_CountAnds( char * pDsd ); + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/src/opt/dsc/module.make b/src/opt/dsc/module.make new file mode 100644 index 00000000..b2fd70c4 --- /dev/null +++ b/src/opt/dsc/module.make @@ -0,0 +1 @@ +SRC += src/opt/dsc/dsc.c diff --git a/src/opt/sbd/module.make b/src/opt/sbd/module.make new file mode 100644 index 00000000..d966e577 --- /dev/null +++ b/src/opt/sbd/module.make @@ -0,0 +1,5 @@ +SRC += src/opt/sbd/sbd.c \ + src/opt/sbd/sbdCnf.c \ + src/opt/sbd/sbdCore.c \ + src/opt/sbd/sbdSat.c \ + src/opt/sbd/sbdWin.c diff --git a/src/opt/sbd/sbd.c b/src/opt/sbd/sbd.c new file mode 100644 index 00000000..4d86d2ee --- /dev/null +++ b/src/opt/sbd/sbd.c @@ -0,0 +1,53 @@ +/**CFile**************************************************************** + + FileName [sbd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [SAT-based optimization using internal don't-cares.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: sbd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sbdInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/sbd/sbd.h b/src/opt/sbd/sbd.h new file mode 100644 index 00000000..89d29958 --- /dev/null +++ b/src/opt/sbd/sbd.h @@ -0,0 +1,75 @@ +/**CFile**************************************************************** + + FileName [sbd.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [SAT-based optimization using internal don't-cares.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: sbd.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__opt_sbd__h +#define ABC__opt_sbd__h + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Sbd_Par_t_ Sbd_Par_t; +struct Sbd_Par_t_ +{ + int nLutSize; // target LUT size + int nTfoLevels; // the number of TFO levels (windowing) + int nTfoFanMax; // the max number of fanouts (windowing) + int nWinSizeMax; // maximum window size (windowing) + int nBTLimit; // maximum number of SAT conflicts + int nWords; // simulation word count + int fArea; // area-oriented optimization + int fCover; // use complete cover procedure + int fVerbose; // verbose flag + int fVeryVerbose; // verbose flag +}; + + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== sbdCnf.c ==========================================================*/ +/*=== sbdCore.c ==========================================================*/ +extern void Sbd_ParSetDefault( Sbd_Par_t * pPars ); +extern Gia_Man_t * Sbd_NtkPerform( Gia_Man_t * p, Sbd_Par_t * pPars ); + + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/opt/sbd/sbdCnf.c b/src/opt/sbd/sbdCnf.c new file mode 100644 index 00000000..6291baed --- /dev/null +++ b/src/opt/sbd/sbdCnf.c @@ -0,0 +1,147 @@ +/**CFile**************************************************************** + + FileName [sbdCnf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [SAT-based optimization using internal don't-cares.] + + Synopsis [CNF computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: sbdCnf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sbdInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sbd_PrintCnf( Vec_Str_t * vCnf ) +{ + char Entry; + int i, Lit; + Vec_StrForEachEntry( vCnf, Entry, i ) + { + Lit = (int)Entry; + if ( Lit == -1 ) + printf( "\n" ); + else + printf( "%s%d ", Abc_LitIsCompl(Lit) ? "-":"", Abc_Lit2Var(Lit) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sbd_TruthToCnf( word Truth, int nVars, Vec_Int_t * vCover, Vec_Str_t * vCnf ) +{ + Vec_StrClear( vCnf ); + if ( Truth == 0 || ~Truth == 0 ) + { +// assert( nVars == 0 ); + Vec_StrPush( vCnf, (char)(Truth == 0) ); + Vec_StrPush( vCnf, (char)-1 ); + return 1; + } + else + { + int i, k, c, RetValue, Literal, Cube, nCubes = 0; + assert( nVars > 0 ); + for ( c = 0; c < 2; c ++ ) + { + Truth = c ? ~Truth : Truth; + RetValue = Kit_TruthIsop( (unsigned *)&Truth, nVars, vCover, 0 ); + assert( RetValue == 0 ); + nCubes += Vec_IntSize( vCover ); + Vec_IntForEachEntry( vCover, Cube, i ) + { + for ( k = 0; k < nVars; k++ ) + { + Literal = 3 & (Cube >> (k << 1)); + if ( Literal == 1 ) // '0' -> pos lit + Vec_StrPush( vCnf, (char)Abc_Var2Lit(k, 0) ); + else if ( Literal == 2 ) // '1' -> neg lit + Vec_StrPush( vCnf, (char)Abc_Var2Lit(k, 1) ); + else if ( Literal != 0 ) + assert( 0 ); + } + Vec_StrPush( vCnf, (char)Abc_Var2Lit(nVars, c) ); + Vec_StrPush( vCnf, (char)-1 ); + } + } + return nCubes; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sbd_TranslateCnf( Vec_Wec_t * vRes, Vec_Str_t * vCnf, Vec_Int_t * vFaninMap, int iPivotVar ) +{ + Vec_Int_t * vClause; + char Entry; + int i, Lit; + Vec_WecClear( vRes ); + vClause = Vec_WecPushLevel( vRes ); + Vec_StrForEachEntry( vCnf, Entry, i ) + { + if ( (int)Entry == -1 ) + { + vClause = Vec_WecPushLevel( vRes ); + continue; + } + Lit = Abc_Lit2LitV( Vec_IntArray(vFaninMap), (int)Entry ); + Lit = Abc_LitNotCond( Lit, Abc_Lit2Var(Lit) == iPivotVar ); + Vec_IntPush( vClause, Lit ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/sbd/sbdCore.c b/src/opt/sbd/sbdCore.c new file mode 100644 index 00000000..b6ec70f9 --- /dev/null +++ b/src/opt/sbd/sbdCore.c @@ -0,0 +1,1520 @@ +/**CFile**************************************************************** + + FileName [sbd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [SAT-based optimization using internal don't-cares.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: sbd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sbdInt.h" +#include "opt/dau/dau.h" +#include "misc/tim/tim.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define SBD_MAX_LUTSIZE 6 + + +typedef struct Sbd_Man_t_ Sbd_Man_t; +struct Sbd_Man_t_ +{ + Sbd_Par_t * pPars; // user's parameters + Gia_Man_t * pGia; // user's AIG manager (will be modified by adding nodes) + Vec_Wec_t * vTfos; // TFO for each node (roots are marked) (windowing) + Vec_Int_t * vLutLevs; // LUT level for each node after resynthesis + Vec_Int_t * vLutCuts; // LUT cut for each nodes after resynthesis + Vec_Int_t * vMirrors; // alternative node + Vec_Wrd_t * vSims[4]; // simulation information (main, backup, controlability) + Vec_Int_t * vCover; // temporary + Vec_Int_t * vLits; // temporary + int nConsts; // constants + int nChanges; // changes + abctime timeWin; + abctime timeCnf; + abctime timeSat; + abctime timeCov; + abctime timeEnu; + abctime timeOther; + abctime timeTotal; + // target node + int Pivot; // target node + Vec_Int_t * vTfo; // TFO (excludes node, includes roots) - precomputed + Vec_Int_t * vRoots; // TFO root nodes + Vec_Int_t * vWinObjs; // TFI + Pivot + sideTFI + TFO (including roots) + Vec_Int_t * vObj2Var; // SAT variables for the window (indexes of objects in vWinObjs) + Vec_Int_t * vDivVars; // divisor variables + Vec_Int_t * vDivValues; // SAT variables values for the divisor variables + Vec_Wec_t * vDivLevels; // divisors collected by levels + Vec_Int_t * vCounts[2]; // counters of zeros and ones + Vec_Wrd_t * vMatrix; // covering matrix + sat_solver * pSat; // SAT solver +}; + +static inline int * Sbd_ObjCut( Sbd_Man_t * p, int i ) { return Vec_IntEntryP( p->vLutCuts, (p->pPars->nLutSize + 1) * i ); } + +static inline word * Sbd_ObjSim0( Sbd_Man_t * p, int i ) { return Vec_WrdEntryP( p->vSims[0], p->pPars->nWords * i ); } +static inline word * Sbd_ObjSim1( Sbd_Man_t * p, int i ) { return Vec_WrdEntryP( p->vSims[1], p->pPars->nWords * i ); } +static inline word * Sbd_ObjSim2( Sbd_Man_t * p, int i ) { return Vec_WrdEntryP( p->vSims[2], p->pPars->nWords * i ); } +static inline word * Sbd_ObjSim3( Sbd_Man_t * p, int i ) { return Vec_WrdEntryP( p->vSims[3], p->pPars->nWords * i ); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sbd_ParSetDefault( Sbd_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Sbd_Par_t) ); + pPars->nLutSize = 4; // target LUT size + pPars->nTfoLevels = 2; // the number of TFO levels (windowing) + pPars->nTfoFanMax = 4; // the max number of fanouts (windowing) + pPars->nWinSizeMax = 0; // maximum window size (windowing) + pPars->nBTLimit = 0; // maximum number of SAT conflicts + pPars->nWords = 1; // simulation word count + pPars->fArea = 0; // area-oriented optimization + pPars->fCover = 0; // use complete cover procedure + pPars->fVerbose = 0; // verbose flag + pPars->fVeryVerbose = 0; // verbose flag +} + +/**Function************************************************************* + + Synopsis [Computes TFO and window roots for all nodes.] + + Description [TFO does not include the node itself. If TFO is empty, + it means that the node itself is its own root, which may happen if + the node is pointed by a PO or if it has too many fanouts.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Sbd_ManWindowRoots( Gia_Man_t * p, int nTfoLevels, int nTfoFanMax ) +{ + Vec_Wec_t * vTfos = Vec_WecStart( Gia_ManObjNum(p) ); // TFO nodes with roots marked + Vec_Wec_t * vTemp = Vec_WecStart( Gia_ManObjNum(p) ); // storage + Vec_Int_t * vNodes, * vNodes0, * vNodes1; + Vec_Bit_t * vPoDrivers = Vec_BitStart( Gia_ManObjNum(p) ); + int i, k, k2, Id, Fan; + Gia_ManLevelNum( p ); + Gia_ManCreateRefs( p ); + Gia_ManCleanMark0( p ); + Gia_ManForEachCiId( p, Id, i ) + { + vNodes = Vec_WecEntry( vTemp, Id ); + Vec_IntGrow( vNodes, 1 ); + Vec_IntPush( vNodes, Id ); + } + Gia_ManForEachCoDriverId( p, Id, i ) + Vec_BitWriteEntry( vPoDrivers, Id, 1 ); + Gia_ManForEachAndId( p, Id ) + { + int fAlwaysRoot = Vec_BitEntry(vPoDrivers, Id) || (Gia_ObjRefNumId(p, Id) >= nTfoFanMax); + vNodes0 = Vec_WecEntry( vTemp, Gia_ObjFaninId0(Gia_ManObj(p, Id), Id) ); + vNodes1 = Vec_WecEntry( vTemp, Gia_ObjFaninId1(Gia_ManObj(p, Id), Id) ); + vNodes = Vec_WecEntry( vTemp, Id ); + Vec_IntTwoMerge2( vNodes0, vNodes1, vNodes ); + k2 = 0; + Vec_IntForEachEntry( vNodes, Fan, k ) + { + int fRoot = fAlwaysRoot || (Gia_ObjLevelId(p, Id) - Gia_ObjLevelId(p, Fan) >= nTfoLevels); + Vec_WecPush( vTfos, Fan, Abc_Var2Lit(Id, fRoot) ); + if ( !fRoot ) Vec_IntWriteEntry( vNodes, k2++, Fan ); + } + Vec_IntShrink( vNodes, k2 ); + if ( !fAlwaysRoot ) + Vec_IntPush( vNodes, Id ); + } + Vec_WecFree( vTemp ); + Vec_BitFree( vPoDrivers ); + + // print the results + if ( 0 ) + Vec_WecForEachLevel( vTfos, vNodes, i ) + { + if ( !Gia_ObjIsAnd(Gia_ManObj(p, i)) ) + continue; + printf( "Node %3d : ", i ); + Vec_IntForEachEntry( vNodes, Fan, k ) + printf( "%d%s ", Abc_Lit2Var(Fan), Abc_LitIsCompl(Fan)? "*":"" ); + printf( "\n" ); + } + + return vTfos; +} + +/**Function************************************************************* + + Synopsis [Manager manipulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Sbd_Man_t * Sbd_ManStart( Gia_Man_t * pGia, Sbd_Par_t * pPars ) +{ + int i, w, Id; + Sbd_Man_t * p = ABC_CALLOC( Sbd_Man_t, 1 ); + p->timeTotal = Abc_Clock(); + p->pPars = pPars; + p->pGia = pGia; + p->vTfos = Sbd_ManWindowRoots( pGia, pPars->nTfoLevels, pPars->nTfoFanMax ); + p->vLutLevs = Vec_IntStart( Gia_ManObjNum(pGia) ); + p->vLutCuts = Vec_IntStart( Gia_ManObjNum(pGia) * (p->pPars->nLutSize + 1) ); + p->vMirrors = Vec_IntStartFull( Gia_ManObjNum(pGia) ); + for ( i = 0; i < 4; i++ ) + p->vSims[i] = Vec_WrdStart( Gia_ManObjNum(pGia) * p->pPars->nWords ); + // target node + p->vCover = Vec_IntAlloc( 100 ); + p->vLits = Vec_IntAlloc( 100 ); + p->vRoots = Vec_IntAlloc( 100 ); + p->vWinObjs = Vec_IntAlloc( Gia_ManObjNum(pGia) ); + p->vObj2Var = Vec_IntStart( Gia_ManObjNum(pGia) ); + p->vDivVars = Vec_IntAlloc( 100 ); + p->vDivValues = Vec_IntAlloc( 100 ); + p->vDivLevels = Vec_WecAlloc( 100 ); + p->vCounts[0] = Vec_IntAlloc( 100 ); + p->vCounts[1] = Vec_IntAlloc( 100 ); + p->vMatrix = Vec_WrdAlloc( 100 ); + // start input cuts + Gia_ManForEachCiId( pGia, Id, i ) + { + int * pCut = Sbd_ObjCut( p, Id ); + pCut[0] = 1; + pCut[1] = Id; + } + // generate random input + Gia_ManRandom( 1 ); + Gia_ManForEachCiId( pGia, Id, i ) + for ( w = 0; w < p->pPars->nWords; w++ ) + Sbd_ObjSim0(p, Id)[w] = Gia_ManRandomW( 0 ); + return p; +} +void Sbd_ManStop( Sbd_Man_t * p ) +{ + int i; + Vec_WecFree( p->vTfos ); + Vec_IntFree( p->vLutLevs ); + Vec_IntFree( p->vLutCuts ); + Vec_IntFree( p->vMirrors ); + for ( i = 0; i < 4; i++ ) + Vec_WrdFree( p->vSims[i] ); + Vec_IntFree( p->vCover ); + Vec_IntFree( p->vLits ); + Vec_IntFree( p->vRoots ); + Vec_IntFree( p->vWinObjs ); + Vec_IntFree( p->vObj2Var ); + Vec_IntFree( p->vDivVars ); + Vec_IntFree( p->vDivValues ); + Vec_WecFree( p->vDivLevels ); + Vec_IntFree( p->vCounts[0] ); + Vec_IntFree( p->vCounts[1] ); + Vec_WrdFree( p->vMatrix ); + if ( p->pSat ) sat_solver_delete( p->pSat ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Constructing window.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sbd_ManPropagateControlOne( Sbd_Man_t * p, int Node ) +{ + Gia_Obj_t * pNode = Gia_ManObj(p->pGia, Node); int w; + int iObj0 = Gia_ObjFaninId0(pNode, Node); + int iObj1 = Gia_ObjFaninId1(pNode, Node); + +// word * pSims = Sbd_ObjSim0(p, Node); +// word * pSims0 = Sbd_ObjSim0(p, iObj0); +// word * pSims1 = Sbd_ObjSim0(p, iObj1); + + word * pCtrl = Sbd_ObjSim2(p, Node); + word * pCtrl0 = Sbd_ObjSim2(p, iObj0); + word * pCtrl1 = Sbd_ObjSim2(p, iObj1); + + word * pDtrl = Sbd_ObjSim3(p, Node); + word * pDtrl0 = Sbd_ObjSim3(p, iObj0); + word * pDtrl1 = Sbd_ObjSim3(p, iObj1); + +// Gia_ObjPrint( p->pGia, pNode ); +// printf( "Node %2d : %d %d\n\n", Node, (int)(pSims[0] & 1), (int)(pCtrl[0] & 1) ); + + for ( w = 0; w < p->pPars->nWords; w++ ) + { +// word Sim0 = Gia_ObjFaninC0(pNode) ? ~pSims0[w] : pSims0[w]; +// word Sim1 = Gia_ObjFaninC1(pNode) ? ~pSims1[w] : pSims1[w]; + + pCtrl0[w] |= pCtrl[w];// & (pSims[w] | Sim1 | (~Sim0 & ~Sim1)); + pCtrl1[w] |= pCtrl[w];// & (pSims[w] | Sim0 | (~Sim0 & ~Sim1)); + + pDtrl0[w] |= pDtrl[w];// & (pSims[w] | Sim1 | (~Sim0 & ~Sim1)); + pDtrl1[w] |= pDtrl[w];// & (pSims[w] | Sim0 | (~Sim0 & ~Sim1)); + } +} +void Sbd_ManPropagateControl( Sbd_Man_t * p, int Pivot ) +{ + abctime clk = Abc_Clock(); + int i, Node; + Abc_TtCopy( Sbd_ObjSim3(p, Pivot), Sbd_ObjSim2(p, Pivot), p->pPars->nWords, 0 ); + // clean controlability + for ( i = 0; i < Vec_IntEntry(p->vObj2Var, Pivot) && ((Node = Vec_IntEntry(p->vWinObjs, i)), 1); i++ ) + { + Abc_TtClear( Sbd_ObjSim2(p, Node), p->pPars->nWords ); + Abc_TtClear( Sbd_ObjSim3(p, Node), p->pPars->nWords ); + //printf( "Clearing node %d.\n", Node ); + } + // propagate controlability to fanins for the TFI nodes starting from the pivot + for ( i = Vec_IntEntry(p->vObj2Var, Pivot); i >= 0 && ((Node = Vec_IntEntry(p->vWinObjs, i)), 1); i-- ) + if ( Gia_ObjIsAnd(Gia_ManObj(p->pGia, Node)) ) + Sbd_ManPropagateControlOne( p, Node ); + p->timeWin += Abc_Clock() - clk; +} +void Sbd_ManUpdateOrder( Sbd_Man_t * p, int Pivot ) +{ + int i, k, Node; + Vec_Int_t * vLevel; + int nTimeValidDivs = 0; + // collect divisors by logic level + int LevelMax = Vec_IntEntry(p->vLutLevs, Pivot); + Vec_WecClear( p->vDivLevels ); + Vec_WecInit( p->vDivLevels, LevelMax + 1 ); + Vec_IntForEachEntry( p->vWinObjs, Node, i ) + Vec_WecPush( p->vDivLevels, Vec_IntEntry(p->vLutLevs, Node), Node ); + // sort primary inputs + Vec_IntSort( Vec_WecEntry(p->vDivLevels, 0), 0 ); + // reload divisors + Vec_IntClear( p->vWinObjs ); + Vec_WecForEachLevel( p->vDivLevels, vLevel, i ) + { + Vec_IntForEachEntry( vLevel, Node, k ) + { + Vec_IntWriteEntry( p->vObj2Var, Node, Vec_IntSize(p->vWinObjs) ); + Vec_IntPush( p->vWinObjs, Node ); + } + // remember divisor cutoff + if ( i == LevelMax - 2 ) + nTimeValidDivs = Vec_IntSize(p->vWinObjs); + } + assert( nTimeValidDivs > 0 ); + Vec_IntFill( p->vDivValues, Abc_MinInt(63, nTimeValidDivs), 0 ); + //printf( "%d ", Abc_MinInt(63, nTimeValidDivs) ); +} +void Sbd_ManWindowSim_rec( Sbd_Man_t * p, int NodeInit ) +{ + Gia_Obj_t * pObj; + int Node = NodeInit; + if ( Vec_IntEntry(p->vMirrors, Node) >= 0 ) + Node = Abc_Lit2Var( Vec_IntEntry(p->vMirrors, Node) ); + if ( Gia_ObjIsTravIdCurrentId(p->pGia, Node) ) + return; + Gia_ObjSetTravIdCurrentId(p->pGia, Node); + pObj = Gia_ManObj( p->pGia, Node ); + if ( Gia_ObjIsAnd(pObj) ) + { + Sbd_ManWindowSim_rec( p, Gia_ObjFaninId0(pObj, Node) ); + Sbd_ManWindowSim_rec( p, Gia_ObjFaninId1(pObj, Node) ); + } + if ( !pObj->fMark0 ) + { + Vec_IntWriteEntry( p->vObj2Var, Node, Vec_IntSize(p->vWinObjs) ); + Vec_IntPush( p->vWinObjs, Node ); + } + if ( Gia_ObjIsCi(pObj) ) + return; + // simulate + assert( Gia_ObjIsAnd(pObj) ); + if ( Gia_ObjIsXor(pObj) ) + { + Abc_TtXor( Sbd_ObjSim0(p, Node), + Sbd_ObjSim0(p, Gia_ObjFaninId0(pObj, Node)), + Sbd_ObjSim0(p, Gia_ObjFaninId1(pObj, Node)), + p->pPars->nWords, + Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pObj) ); + + if ( pObj->fMark0 ) + Abc_TtXor( Sbd_ObjSim1(p, Node), + Gia_ObjFanin0(pObj)->fMark0 ? Sbd_ObjSim1(p, Gia_ObjFaninId0(pObj, Node)) : Sbd_ObjSim0(p, Gia_ObjFaninId0(pObj, Node)), + Gia_ObjFanin1(pObj)->fMark0 ? Sbd_ObjSim1(p, Gia_ObjFaninId1(pObj, Node)) : Sbd_ObjSim0(p, Gia_ObjFaninId1(pObj, Node)), + p->pPars->nWords, + Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pObj) ); + } + else + { + Abc_TtAndCompl( Sbd_ObjSim0(p, Node), + Sbd_ObjSim0(p, Gia_ObjFaninId0(pObj, Node)), Gia_ObjFaninC0(pObj), + Sbd_ObjSim0(p, Gia_ObjFaninId1(pObj, Node)), Gia_ObjFaninC1(pObj), + p->pPars->nWords ); + + if ( pObj->fMark0 ) + Abc_TtAndCompl( Sbd_ObjSim1(p, Node), + Gia_ObjFanin0(pObj)->fMark0 ? Sbd_ObjSim1(p, Gia_ObjFaninId0(pObj, Node)) : Sbd_ObjSim0(p, Gia_ObjFaninId0(pObj, Node)), Gia_ObjFaninC0(pObj), + Gia_ObjFanin1(pObj)->fMark0 ? Sbd_ObjSim1(p, Gia_ObjFaninId1(pObj, Node)) : Sbd_ObjSim0(p, Gia_ObjFaninId1(pObj, Node)), Gia_ObjFaninC1(pObj), + p->pPars->nWords ); + } + if ( Node != NodeInit ) + Abc_TtCopy( Sbd_ObjSim0(p, NodeInit), Sbd_ObjSim0(p, Node), p->pPars->nWords, Abc_LitIsCompl(Vec_IntEntry(p->vMirrors, NodeInit)) ); +} +int Sbd_ManWindow( Sbd_Man_t * p, int Pivot ) +{ + abctime clk = Abc_Clock(); + int i, Node; + // assign pivot and TFO (assume siminfo is assigned at the PIs) + p->Pivot = Pivot; + p->vTfo = Vec_WecEntry( p->vTfos, Pivot ); + // add constant node + Vec_IntClear( p->vWinObjs ); + Vec_IntWriteEntry( p->vObj2Var, 0, Vec_IntSize(p->vWinObjs) ); + Vec_IntPush( p->vWinObjs, 0 ); + // simulate TFI cone + Gia_ManIncrementTravId( p->pGia ); + Gia_ObjSetTravIdCurrentId(p->pGia, 0); + Sbd_ManWindowSim_rec( p, Pivot ); + Sbd_ManUpdateOrder( p, Pivot ); + // simulate node + Gia_ManObj(p->pGia, Pivot)->fMark0 = 1; + Abc_TtCopy( Sbd_ObjSim1(p, Pivot), Sbd_ObjSim0(p, Pivot), p->pPars->nWords, 1 ); + // mark TFO and simulate extended TFI without adding TFO nodes + Vec_IntClear( p->vRoots ); + Vec_IntForEachEntry( p->vTfo, Node, i ) + { + Gia_ManObj(p->pGia, Abc_Lit2Var(Node))->fMark0 = 1; + if ( !Abc_LitIsCompl(Node) ) + continue; + Sbd_ManWindowSim_rec( p, Abc_Lit2Var(Node) ); + Vec_IntPush( p->vRoots, Abc_Lit2Var(Node) ); + } + // add TFO nodes and remove marks + Gia_ManObj(p->pGia, Pivot)->fMark0 = 0; + Vec_IntForEachEntry( p->vTfo, Node, i ) + { + Gia_ManObj(p->pGia, Abc_Lit2Var(Node))->fMark0 = 0; + Vec_IntWriteEntry( p->vObj2Var, Abc_Lit2Var(Node), Vec_IntSize(p->vWinObjs) ); + Vec_IntPush( p->vWinObjs, Abc_Lit2Var(Node) ); + } + // compute controlability for node + if ( Vec_IntSize(p->vTfo) == 0 ) + Abc_TtFill( Sbd_ObjSim2(p, Pivot), p->pPars->nWords ); + else + Abc_TtClear( Sbd_ObjSim2(p, Pivot), p->pPars->nWords ); + Vec_IntForEachEntry( p->vTfo, Node, i ) + if ( Abc_LitIsCompl(Node) ) // root + Abc_TtOrXor( Sbd_ObjSim2(p, Pivot), Sbd_ObjSim0(p, Abc_Lit2Var(Node)), Sbd_ObjSim1(p, Abc_Lit2Var(Node)), p->pPars->nWords ); + p->timeWin += Abc_Clock() - clk; + // propagate controlability to fanins for the TFI nodes starting from the pivot + Sbd_ManPropagateControl( p, Pivot ); + assert( Vec_IntSize(p->vDivValues) < 64 ); + return (int)(Vec_IntSize(p->vDivValues) >= 64); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sbd_ManCheckConst( Sbd_Man_t * p, int Pivot ) +{ + extern void Sbd_ManPrintObj( Sbd_Man_t * p, int Pivot ); + int nMintCount = 1; + Vec_Ptr_t * vSims; + word * pSims = Sbd_ObjSim0( p, Pivot ); + word * pCtrl = Sbd_ObjSim2( p, Pivot ); + int PivotVar = Vec_IntEntry(p->vObj2Var, Pivot); + int RetValue, i, iObj, Ind, fFindOnset, nCares[2] = {0}; + abctime clk = Abc_Clock(); + extern int Sbd_ManCollectConstants( sat_solver * pSat, int nCareMints[2], int PivotVar, word * pVarSims[], Vec_Int_t * vInds ); + extern sat_solver * Sbd_ManSatSolver( sat_solver * pSat, Gia_Man_t * p, Vec_Int_t * vMirrors, int Pivot, Vec_Int_t * vWinObjs, Vec_Int_t * vObj2Var, Vec_Int_t * vTfo, Vec_Int_t * vRoots ); + p->pSat = Sbd_ManSatSolver( p->pSat, p->pGia, p->vMirrors, Pivot, p->vWinObjs, p->vObj2Var, p->vTfo, p->vRoots ); + p->timeCnf += Abc_Clock() - clk; + if ( p->pSat == NULL ) + { + if ( p->pPars->fVerbose ) + printf( "Found stuck-at-%d node %d.\n", 0, Pivot ); + Vec_IntWriteEntry( p->vLutLevs, Pivot, 0 ); + p->nConsts++; + return 0; + } + //return -1; + //Sbd_ManPrintObj( p, Pivot ); + + // count the number of on-set and off-set care-set minterms + Vec_IntClear( p->vLits ); + for ( i = 0; i < 64; i++ ) + if ( Abc_TtGetBit(pCtrl, i) ) + nCares[Abc_TtGetBit(pSims, i)]++; + else + Vec_IntPush( p->vLits, i ); + fFindOnset = (int)(nCares[0] < nCares[1]); + if ( nCares[0] >= nMintCount && nCares[1] >= nMintCount ) + return -1; + // find how many do we need + nCares[0] = nCares[0] < nMintCount ? nMintCount - nCares[0] : 0; + nCares[1] = nCares[1] < nMintCount ? nMintCount - nCares[1] : 0; + + if ( p->pPars->fVerbose ) + printf( "Computing %d offset and %d onset minterms for node %d.\n", nCares[0], nCares[1], Pivot ); + + if ( Vec_IntSize(p->vLits) >= nCares[0] + nCares[1] ) + Vec_IntShrink( p->vLits, nCares[0] + nCares[1] ); + else + { + // collect places to insert new minterms + for ( i = 0; i < 64 && Vec_IntSize(p->vLits) < nCares[0] + nCares[1]; i++ ) + if ( fFindOnset == Abc_TtGetBit(pSims, i) ) + Vec_IntPush( p->vLits, i ); + } + // collect simulation pointers + vSims = Vec_PtrAlloc( PivotVar + 1 ); + Vec_IntForEachEntry( p->vWinObjs, iObj, i ) + { + Vec_PtrPush( vSims, Sbd_ObjSim0(p, iObj) ); + if ( iObj == Pivot ) + break; + } + assert( i == PivotVar ); + // compute patterns + RetValue = Sbd_ManCollectConstants( p->pSat, nCares, PivotVar, (word **)Vec_PtrArray(vSims), p->vLits ); + // print computed miterms + if ( 0 && RetValue < 0 ) + { + Vec_Int_t * vPis = Vec_WecEntry(p->vDivLevels, 0); + int i, k, Ind; + printf( "Additional minterms:\n" ); + Vec_IntForEachEntry( p->vLits, Ind, k ) + { + for ( i = 0; i < Vec_IntSize(vPis); i++ ) + printf( "%d", Abc_TtGetBit( (word *)Vec_PtrEntry(vSims, Vec_IntEntry(p->vWinObjs, i)), Ind ) ); + printf( "\n" ); + } + } + Vec_PtrFree( vSims ); + if ( RetValue >= 0 ) + { + if ( p->pPars->fVerbose ) + printf( "Found stuck-at-%d node %d.\n", RetValue, Pivot ); + Vec_IntWriteEntry( p->vLutLevs, Pivot, 0 ); + p->nConsts++; + return RetValue; + } + // set controlability of these minterms + Vec_IntForEachEntry( p->vLits, Ind, i ) + Abc_TtSetBit( pCtrl, Ind ); + // propagate controlability to fanins for the TFI nodes starting from the pivot + Sbd_ManPropagateControl( p, Pivot ); + // double check that we now have enough minterms + for ( i = 0; i < 64; i++ ) + if ( Abc_TtGetBit(pCtrl, i) ) + nCares[Abc_TtGetBit(pSims, i)]++; + assert( nCares[0] >= nMintCount && nCares[1] >= nMintCount ); + return -1; +} + +/**Function************************************************************* + + Synopsis [Transposing 64-bit matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Sbd_TransposeMatrix64( word A[64] ) +{ + int j, k; + word t, m = 0x00000000FFFFFFFF; + for ( j = 32; j != 0; j = j >> 1, m = m ^ (m << j) ) + { + for ( k = 0; k < 64; k = (k + j + 1) & ~j ) + { + t = (A[k] ^ (A[k+j] >> j)) & m; + A[k] = A[k] ^ t; + A[k+j] = A[k+j] ^ (t << j); + } + } +} +static inline void Sbd_PrintMatrix64( word A[64] ) +{ + int j, k; + for ( j = 0; j < 64; j++, printf("\n") ) + for ( k = 0; k < 64; k++ ) + printf( "%d", (int)((A[j] >> k) & 1) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Profiling divisor candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sbd_ManPrintObj( Sbd_Man_t * p, int Pivot ) +{ + int nDivs = Vec_IntEntry(p->vObj2Var, Pivot) + 1; + int i, k, k0, k1, Id, Bit0, Bit1; + + Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs ) + printf( "%3d : ", Id ), Extra_PrintBinary( stdout, (unsigned *)Sbd_ObjSim0(p, Id), 64 ), printf( "\n" ); + + assert( p->Pivot == Pivot ); + Vec_IntClear( p->vCounts[0] ); + Vec_IntClear( p->vCounts[1] ); + + printf( "Node %d. Useful divisors = %d.\n", Pivot, Vec_IntSize(p->vDivValues) ); + printf( "Lev : " ); + Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs ) + { + if ( i == nDivs-1 ) + printf( " " ); + printf( "%d", Vec_IntEntry(p->vLutLevs, Id) ); + } + printf( "\n" ); + printf( "\n" ); + + if ( nDivs > 99 ) + { + printf( " : " ); + Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs ) + { + if ( i == nDivs-1 ) + printf( " " ); + printf( "%d", Id / 100 ); + } + printf( "\n" ); + } + if ( nDivs > 9 ) + { + printf( " : " ); + Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs ) + { + if ( i == nDivs-1 ) + printf( " " ); + printf( "%d", (Id % 100) / 10 ); + } + printf( "\n" ); + } + if ( nDivs > 0 ) + { + printf( " : " ); + Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs ) + { + if ( i == nDivs-1 ) + printf( " " ); + printf( "%d", Id % 10 ); + } + printf( "\n" ); + printf( "\n" ); + } + + // sampling matrix + for ( k = 0; k < p->pPars->nWords * 64; k++ ) + { + if ( !Abc_TtGetBit(Sbd_ObjSim2(p, Pivot), k) ) + continue; + + printf( "%3d : ", k ); + Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs ) + { + word * pSims = Sbd_ObjSim0( p, Id ); + word * pCtrl = Sbd_ObjSim2( p, Id ); + if ( i == nDivs-1 ) + { + if ( Abc_TtGetBit(pCtrl, k) ) + Vec_IntPush( p->vCounts[Abc_TtGetBit(pSims, k)], k ); + printf( " " ); + } + printf( "%c", Abc_TtGetBit(pCtrl, k) ? '0' + Abc_TtGetBit(pSims, k) : '.' ); + } + printf( "\n" ); + + printf( "%3d : ", k ); + Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs ) + { + word * pSims = Sbd_ObjSim0( p, Id ); + word * pCtrl = Sbd_ObjSim3( p, Id ); + if ( i == nDivs-1 ) + { + if ( Abc_TtGetBit(pCtrl, k) ) + Vec_IntPush( p->vCounts[Abc_TtGetBit(pSims, k)], k ); + printf( " " ); + } + printf( "%c", Abc_TtGetBit(pCtrl, k) ? '0' + Abc_TtGetBit(pSims, k) : '.' ); + } + printf( "\n" ); + + printf( "Sims: " ); + Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs ) + { + word * pSims = Sbd_ObjSim0( p, Id ); + //word * pCtrl = Sbd_ObjSim2( p, Id ); + if ( i == nDivs-1 ) + printf( " " ); + printf( "%c", '0' + Abc_TtGetBit(pSims, k) ); + } + printf( "\n" ); + + printf( "Ctrl: " ); + Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs ) + { + //word * pSims = Sbd_ObjSim0( p, Id ); + word * pCtrl = Sbd_ObjSim2( p, Id ); + if ( i == nDivs-1 ) + printf( " " ); + printf( "%c", '0' + Abc_TtGetBit(pCtrl, k) ); + } + printf( "\n" ); + + + printf( "\n" ); + } + // covering table + printf( "Exploring %d x %d covering table.\n", Vec_IntSize(p->vCounts[0]), Vec_IntSize(p->vCounts[1]) ); +/* + Vec_IntForEachEntryStop( p->vCounts[0], Bit0, k0, Abc_MinInt(Vec_IntSize(p->vCounts[0]), 8) ) + Vec_IntForEachEntryStop( p->vCounts[1], Bit1, k1, Abc_MinInt(Vec_IntSize(p->vCounts[1]), 8) ) + { + printf( "%3d %3d : ", Bit0, Bit1 ); + Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs ) + { + word * pSims = Sbd_ObjSim0( p, Id ); + word * pCtrl = Sbd_ObjSim2( p, Id ); + if ( i == nDivs-1 ) + printf( " " ); + printf( "%c", (Abc_TtGetBit(pCtrl, Bit0) && Abc_TtGetBit(pCtrl, Bit1) && Abc_TtGetBit(pSims, Bit0) != Abc_TtGetBit(pSims, Bit1)) ? '1' : '.' ); + } + printf( "\n" ); + } +*/ + Vec_WrdClear( p->vMatrix ); + Vec_IntForEachEntryStop( p->vCounts[0], Bit0, k0, Abc_MinInt(Vec_IntSize(p->vCounts[0]), 64) ) + Vec_IntForEachEntryStop( p->vCounts[1], Bit1, k1, Abc_MinInt(Vec_IntSize(p->vCounts[1]), 64) ) + { + word Row = 0; + Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs ) + { + word * pSims = Sbd_ObjSim0( p, Id ); + word * pCtrl = Sbd_ObjSim2( p, Id ); + if ( Abc_TtGetBit(pCtrl, Bit0) && Abc_TtGetBit(pCtrl, Bit1) && Abc_TtGetBit(pSims, Bit0) != Abc_TtGetBit(pSims, Bit1) ) + Abc_TtXorBit( &Row, i ); + } + if ( Vec_WrdPushUnique( p->vMatrix, Row ) ) + continue; + for ( i = 0; i < nDivs; i++ ) + printf( "%d", (int)((Row >> i) & 1) ); + printf( "\n" ); + } +} + +void Sbd_ManMatrPrint( word Cover[64], int nCol, int nRows ) +{ + int i, k; + for ( i = 0; i <= nCol; i++ ) + { + printf( "%2d : ", i ); + for ( k = 0; k < nRows; k++ ) + for ( k = 0; k < nRows; k++ ) + printf( "%d", (int)((Cover[i] >> k) & 1) ); + printf( "\n"); + } + printf( "\n"); +} +static inline void Sbd_ManCoverReverseOrder( word Cover[64] ) +{ + int i; + for ( i = 0; i < 32; i++ ) + { + word Cube = Cover[i]; + Cover[i] = Cover[63-i]; + Cover[63-i] = Cube; + } +} + +static inline int Sbd_ManAddCube1( word Cover[64], int nRows, word Cube ) +{ + int n, m; + if ( 0 ) + { + printf( "Adding cube: " ); + for ( n = 0; n < 64; n++ ) + printf( "%d", (int)((Cube >> n) & 1) ); + printf( "\n" ); + } + // do not add contained Cube + assert( nRows <= 64 ); + for ( n = 0; n < nRows; n++ ) + if ( (Cover[n] & Cube) == Cover[n] ) // Cube is contained + return nRows; + // remove rows contained by Cube + for ( n = m = 0; n < nRows; n++ ) + if ( (Cover[n] & Cube) != Cube ) // Cover[n] is not contained + Cover[m++] = Cover[n]; + if ( m < 64 ) + Cover[m++] = Cube; + for ( n = m; n < nRows; n++ ) + Cover[n] = 0; + nRows = m; + return nRows; +} +static inline int Sbd_ManAddCube2( word Cover[2][64], int nRows, word Cube[2] ) +{ + int n, m; + // do not add contained Cube + assert( nRows <= 64 ); + for ( n = 0; n < nRows; n++ ) + if ( (Cover[0][n] & Cube[0]) == Cover[0][n] && (Cover[1][n] & Cube[1]) == Cover[1][n] ) // Cube is contained + return nRows; + // remove rows contained by Cube + for ( n = m = 0; n < nRows; n++ ) + if ( (Cover[0][n] & Cube[0]) != Cube[0] || (Cover[1][n] & Cube[1]) != Cube[1] ) // Cover[n] is not contained + { + Cover[0][m] = Cover[0][n]; + Cover[1][m] = Cover[1][n]; + m++; + } + if ( m < 64 ) + { + Cover[0][m] = Cube[0]; + Cover[1][m] = Cube[1]; + m++; + } + for ( n = m; n < nRows; n++ ) + Cover[0][n] = Cover[1][n] = 0; + nRows = m; + return nRows; +} + +static inline int Sbd_ManFindCandsSimple( Sbd_Man_t * p, word Cover[64], int nDivs ) +{ + int c0, c1, c2, c3; + word Target = Cover[nDivs]; + Vec_IntClear( p->vDivVars ); + for ( c0 = 0; c0 < nDivs; c0++ ) + if ( Cover[c0] == Target ) + { + Vec_IntPush( p->vDivVars, c0 ); + return 1; + } + + for ( c0 = 0; c0 < nDivs; c0++ ) + for ( c1 = c0+1; c1 < nDivs; c1++ ) + if ( (Cover[c0] | Cover[c1]) == Target ) + { + Vec_IntPush( p->vDivVars, c0 ); + Vec_IntPush( p->vDivVars, c1 ); + return 1; + } + + for ( c0 = 0; c0 < nDivs; c0++ ) + for ( c1 = c0+1; c1 < nDivs; c1++ ) + for ( c2 = c1+1; c2 < nDivs; c2++ ) + if ( (Cover[c0] | Cover[c1] | Cover[c2]) == Target ) + { + Vec_IntPush( p->vDivVars, c0 ); + Vec_IntPush( p->vDivVars, c1 ); + Vec_IntPush( p->vDivVars, c2 ); + return 1; + } + + for ( c0 = 0; c0 < nDivs; c0++ ) + for ( c1 = c0+1; c1 < nDivs; c1++ ) + for ( c2 = c1+1; c2 < nDivs; c2++ ) + for ( c3 = c2+1; c3 < nDivs; c3++ ) + { + if ( (Cover[c0] | Cover[c1] | Cover[c2] | Cover[c3]) == Target ) + { + Vec_IntPush( p->vDivVars, c0 ); + Vec_IntPush( p->vDivVars, c1 ); + Vec_IntPush( p->vDivVars, c2 ); + Vec_IntPush( p->vDivVars, c3 ); + return 1; + } + } + return 0; +} + +static inline int Sbd_ManFindCands( Sbd_Man_t * p, word Cover[64], int nDivs ) +{ + int Ones[64], Order[64]; + int Limits[4] = { nDivs/4+1, nDivs/3+2, nDivs/2+3, nDivs }; + int c0, c1, c2, c3; + word Target = Cover[nDivs]; + + if ( nDivs < 8 || p->pPars->fCover ) + return Sbd_ManFindCandsSimple( p, Cover, nDivs ); + + Vec_IntClear( p->vDivVars ); + for ( c0 = 0; c0 < nDivs; c0++ ) + if ( Cover[c0] == Target ) + { + Vec_IntPush( p->vDivVars, c0 ); + return 1; + } + + for ( c0 = 0; c0 < nDivs; c0++ ) + for ( c1 = c0+1; c1 < nDivs; c1++ ) + if ( (Cover[c0] | Cover[c1]) == Target ) + { + Vec_IntPush( p->vDivVars, c0 ); + Vec_IntPush( p->vDivVars, c1 ); + return 1; + } + + // count ones + for ( c0 = 0; c0 < nDivs; c0++ ) + Ones[c0] = Abc_TtCountOnes( Cover[c0] ); + + // sort by the number of ones + for ( c0 = 0; c0 < nDivs; c0++ ) + Order[c0] = c0; + Vec_IntSelectSortCost2Reverse( Order, nDivs, Ones ); + + // sort with limits + for ( c0 = 0; c0 < Limits[0]; c0++ ) + for ( c1 = c0+1; c1 < Limits[1]; c1++ ) + for ( c2 = c1+1; c2 < Limits[2]; c2++ ) + if ( (Cover[Order[c0]] | Cover[Order[c1]] | Cover[Order[c2]]) == Target ) + { + Vec_IntPush( p->vDivVars, Order[c0] ); + Vec_IntPush( p->vDivVars, Order[c1] ); + Vec_IntPush( p->vDivVars, Order[c2] ); + return 1; + } + + for ( c0 = 0; c0 < Limits[0]; c0++ ) + for ( c1 = c0+1; c1 < Limits[1]; c1++ ) + for ( c2 = c1+1; c2 < Limits[2]; c2++ ) + for ( c3 = c2+1; c3 < Limits[3]; c3++ ) + { + if ( (Cover[Order[c0]] | Cover[Order[c1]] | Cover[Order[c2]] | Cover[Order[c3]]) == Target ) + { + Vec_IntPush( p->vDivVars, Order[c0] ); + Vec_IntPush( p->vDivVars, Order[c1] ); + Vec_IntPush( p->vDivVars, Order[c2] ); + Vec_IntPush( p->vDivVars, Order[c3] ); + return 1; + } + } + return 0; +} + + +int Sbd_ManExplore( Sbd_Man_t * p, int Pivot, word * pTruth ) +{ + int fVerbose = 0; + abctime clk, clkSat = 0, clkEnu = 0, clkAll = Abc_Clock(); + int nIters, nItersMax = 32; + extern word Sbd_ManSolve( sat_solver * pSat, int PivotVar, int FreeVar, Vec_Int_t * vDivVars, Vec_Int_t * vValues, Vec_Int_t * vTemp ); + + word MatrS[64] = {0}, MatrC[2][64] = {{0}}, Cubes[2][2][64] = {{{0}}}, Cover[64] = {0}, Cube, CubeNew[2]; + int i, k, n, Index, nCubes[2] = {0}, nRows = 0, nRowsOld; + + int nDivs = Vec_IntSize(p->vDivValues); + int PivotVar = Vec_IntEntry(p->vObj2Var, Pivot); + int FreeVar = Vec_IntSize(p->vWinObjs) + Vec_IntSize(p->vTfo) + Vec_IntSize(p->vRoots); + int RetValue = 0; + + if ( p->pPars->fVerbose ) + printf( "Node %d. Useful divisors = %d.\n", Pivot, nDivs ); + + if ( fVerbose ) + Sbd_ManPrintObj( p, Pivot ); + + // collect bit-matrices + for ( i = 0; i < nDivs; i++ ) + { + MatrS[63-i] = *Sbd_ObjSim0( p, Vec_IntEntry(p->vWinObjs, i) ); + MatrC[0][63-i] = *Sbd_ObjSim2( p, Vec_IntEntry(p->vWinObjs, i) ); + MatrC[1][63-i] = *Sbd_ObjSim3( p, Vec_IntEntry(p->vWinObjs, i) ); + } + MatrS[63-i] = *Sbd_ObjSim0( p, Pivot ); + MatrC[0][63-i] = *Sbd_ObjSim2( p, Pivot ); + MatrC[1][63-i] = *Sbd_ObjSim3( p, Pivot ); + + //Sbd_PrintMatrix64( MatrS ); + Sbd_TransposeMatrix64( MatrS ); + Sbd_TransposeMatrix64( MatrC[0] ); + Sbd_TransposeMatrix64( MatrC[1] ); + //Sbd_PrintMatrix64( MatrS ); + + // collect cubes + for ( i = 0; i < 64; i++ ) + { + assert( Abc_TtGetBit(&MatrC[0][i], nDivs) == Abc_TtGetBit(&MatrC[1][i], nDivs) ); + if ( !Abc_TtGetBit(&MatrC[0][i], nDivs) ) + continue; + Index = Abc_TtGetBit(&MatrS[i], nDivs); // Index==0 offset; Index==1 onset + for ( n = 0; n < 2; n++ ) + { + if ( n && MatrC[0][i] == MatrC[1][i] ) + continue; + assert( MatrC[n][i] ); + CubeNew[0] = ~MatrS[i] & MatrC[n][i]; + CubeNew[1] = MatrS[i] & MatrC[n][i]; + assert( CubeNew[0] || CubeNew[1] ); + nCubes[Index] = Sbd_ManAddCube2( Cubes[Index], nCubes[Index], CubeNew ); + } + } + + if ( p->pPars->fVerbose ) + printf( "Generated matrix with %d x %d entries.\n", nCubes[0], nCubes[1] ); + + if ( p->pPars->fVerbose ) + for ( n = 0; n < 2; n++ ) + { + printf( "%s:\n", n ? "Onset" : "Offset" ); + for ( i = 0; i < nCubes[n]; i++, printf( "\n" ) ) + for ( k = 0; k < 64; k++ ) + if ( Abc_TtGetBit(&Cubes[n][0][i], k) ) + printf( "0" ); + else if ( Abc_TtGetBit(&Cubes[n][1][i], k) ) + printf( "1" ); + else + printf( "." ); + printf( "\n" ); + } + + // create covering table + nRows = 0; + for ( i = 0; i < nCubes[0] && nRows < 32; i++ ) + for ( k = 0; k < nCubes[1] && nRows < 32; k++ ) + { + Cube = (Cubes[0][1][i] & Cubes[1][0][k]) | (Cubes[0][0][i] & Cubes[1][1][k]); + assert( Cube ); + nRows = Sbd_ManAddCube1( Cover, nRows, Cube ); + } + + Sbd_ManCoverReverseOrder( Cover ); + + if ( p->pPars->fVerbose ) + printf( "Generated cover with %d entries.\n", nRows ); + + //if ( p->pPars->fVerbose ) + //Sbd_PrintMatrix64( Cover ); + Sbd_TransposeMatrix64( Cover ); + //if ( p->pPars->fVerbose ) + //Sbd_PrintMatrix64( Cover ); + + Sbd_ManCoverReverseOrder( Cover ); + + nRowsOld = nRows; + for ( nIters = 0; nIters < nItersMax && nRows < 64; nIters++ ) + { + if ( p->pPars->fVerbose ) + Sbd_ManMatrPrint( Cover, nDivs, nRows ); + + clk = Abc_Clock(); + if ( !Sbd_ManFindCands( p, Cover, nDivs ) ) + { + if ( p->pPars->fVerbose ) + printf( "Cannot find a feasible cover.\n" ); + clkEnu += Abc_Clock() - clk; + clkAll = Abc_Clock() - clkAll - clkSat - clkEnu; + p->timeSat += clkSat; + p->timeCov += clkAll; + p->timeEnu += clkEnu; + return RetValue; + } + clkEnu += Abc_Clock() - clk; + + if ( p->pPars->fVerbose ) + printf( "Candidate support: " ), + Vec_IntPrint( p->vDivVars ); + + clk = Abc_Clock(); + *pTruth = Sbd_ManSolve( p->pSat, PivotVar, FreeVar+nIters, p->vDivVars, p->vDivValues, p->vLits ); + clkSat += Abc_Clock() - clk; + + if ( *pTruth == SBD_SAT_UNDEC ) + printf( "Node %d: Undecided.\n", Pivot ); + else if ( *pTruth == SBD_SAT_SAT ) + { + if ( p->pPars->fVerbose ) + { + int i; + printf( "Node %d: SAT.\n", Pivot ); + for ( i = 0; i < nDivs; i++ ) + printf( "%d", i % 10 ); + printf( "\n" ); + for ( i = 0; i < nDivs; i++ ) + printf( "%c", (Vec_IntEntry(p->vDivValues, i) & 0x4) ? '0' + (Vec_IntEntry(p->vDivValues, i) & 1) : 'x' ); + printf( "\n" ); + for ( i = 0; i < nDivs; i++ ) + printf( "%c", (Vec_IntEntry(p->vDivValues, i) & 0x8) ? '0' + ((Vec_IntEntry(p->vDivValues, i) >> 1) & 1) : 'x' ); + printf( "\n" ); + } + // add row to the covering table + for ( i = 0; i < nDivs; i++ ) + if ( Vec_IntEntry(p->vDivValues, i) == 0xE || Vec_IntEntry(p->vDivValues, i) == 0xD ) + Cover[i] |= ((word)1 << nRows); + Cover[nDivs] |= ((word)1 << nRows); + nRows++; + } + else + { + if ( p->pPars->fVerbose ) + { + printf( "Node %d: UNSAT.\n", Pivot ); + Extra_PrintBinary( stdout, (unsigned *)pTruth, 1 << Vec_IntSize(p->vDivVars) ), printf( "\n" ); + } + RetValue = 1; + break; + } + //break; + } + //printf( "Node %4d : Iter = %4d Start table = %4d Final table = %4d\n", Pivot, nIters, nRowsOld, nRows ); + clkAll = Abc_Clock() - clkAll - clkSat - clkEnu; + p->timeSat += clkSat; + p->timeCov += clkAll; + p->timeEnu += clkEnu; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Computes delay-oriented k-feasible cut at the node.] + + Description [Return 1 if node's LUT level does not exceed those of the fanins.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sbd_CutMergeSimple( Sbd_Man_t * p, int * pCut1, int * pCut2, int * pCut ) +{ + int * pBeg = pCut + 1; + int * pBeg1 = pCut1 + 1; + int * pBeg2 = pCut2 + 1; + int * pEnd1 = pCut1 + 1 + pCut1[0]; + int * pEnd2 = pCut2 + 1 + pCut2[0]; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( *pBeg1 == *pBeg2 ) + *pBeg++ = *pBeg1++, pBeg2++; + else if ( *pBeg1 < *pBeg2 ) + *pBeg++ = *pBeg1++; + else + *pBeg++ = *pBeg2++; + } + while ( pBeg1 < pEnd1 ) + *pBeg++ = *pBeg1++; + while ( pBeg2 < pEnd2 ) + *pBeg++ = *pBeg2++; + return (pCut[0] = pBeg - pCut - 1); +} +/* +int Sbd_ManMergeCuts( Sbd_Man_t * p, int Node ) +{ + int Result = 1; // no need to resynthesize + int pCut[2*SBD_MAX_LUTSIZE+1]; + int iFan0 = Gia_ObjFaninId0( Gia_ManObj(p->pGia, Node), Node ); + int iFan1 = Gia_ObjFaninId1( Gia_ManObj(p->pGia, Node), Node ); + int Level0 = Vec_IntEntry( p->vLutLevs, iFan0 ); + int Level1 = Vec_IntEntry( p->vLutLevs, iFan1 ); + int LevMax = (Level0 || Level1) ? Abc_MaxInt(Level0, Level1) : 1; + int * pCut0 = Sbd_ObjCut( p, iFan0 ); + int * pCut1 = Sbd_ObjCut( p, iFan1 ); + int nSize = Sbd_CutMergeSimple( p, pCut0, pCut1, pCut ); + if ( nSize > p->pPars->nLutSize ) + { + if ( Level0 != Level1 ) + { + int Cut0[2] = {1, iFan0}, * pCut0Temp = Level0 < LevMax ? Cut0 : pCut0; + int Cut1[2] = {1, iFan1}, * pCut1Temp = Level1 < LevMax ? Cut1 : pCut1; + nSize = Sbd_CutMergeSimple( p, pCut0Temp, pCut1Temp, pCut ); + } + if ( nSize > p->pPars->nLutSize ) + { + pCut[0] = 2; + pCut[1] = iFan0 < iFan1 ? iFan0 : iFan1; + pCut[2] = iFan0 < iFan1 ? iFan1 : iFan0; + Result = LevMax ? 0 : 1; + LevMax++; + } + } + assert( iFan0 != iFan1 ); + assert( Vec_IntEntry(p->vLutLevs, Node) == 0 ); + Vec_IntWriteEntry( p->vLutLevs, Node, LevMax ); + memcpy( Sbd_ObjCut(p, Node), pCut, sizeof(int) * (pCut[0] + 1) ); + //printf( "Setting node %d with delay %d (result = %d).\n", Node, LevMax, Result ); + return Result; +} +*/ +int Sbd_ManMergeCuts( Sbd_Man_t * p, int Node ) +{ + int pCut11[2*SBD_MAX_LUTSIZE+1]; + int pCut01[2*SBD_MAX_LUTSIZE+1]; + int pCut10[2*SBD_MAX_LUTSIZE+1]; + int pCut00[2*SBD_MAX_LUTSIZE+1]; + int iFan0 = Gia_ObjFaninId0( Gia_ManObj(p->pGia, Node), Node ); + int iFan1 = Gia_ObjFaninId1( Gia_ManObj(p->pGia, Node), Node ); + int Level0 = Vec_IntEntry( p->vLutLevs, iFan0 ) ? Vec_IntEntry( p->vLutLevs, iFan0 ) : 1; + int Level1 = Vec_IntEntry( p->vLutLevs, iFan1 ) ? Vec_IntEntry( p->vLutLevs, iFan1 ) : 1; + int * pCut0 = Sbd_ObjCut( p, iFan0 ); + int * pCut1 = Sbd_ObjCut( p, iFan1 ); + int Cut0[2] = {1, iFan0}; + int Cut1[2] = {1, iFan1}; + int nSize11 = Sbd_CutMergeSimple( p, pCut0, pCut1, pCut11 ); + int nSize01 = Sbd_CutMergeSimple( p, Cut0, pCut1, pCut01 ); + int nSize10 = Sbd_CutMergeSimple( p, pCut0, Cut1, pCut10 ); + int nSize00 = Sbd_CutMergeSimple( p, Cut0, Cut1, pCut00 ); + int Lev11 = nSize11 <= p->pPars->nLutSize ? Abc_MaxInt(Level0, Level1) : ABC_INFINITY; + int Lev01 = nSize01 <= p->pPars->nLutSize ? Abc_MaxInt(Level0+1, Level1) : ABC_INFINITY; + int Lev10 = nSize10 <= p->pPars->nLutSize ? Abc_MaxInt(Level0, Level1+1) : ABC_INFINITY; + int Lev00 = nSize00 <= p->pPars->nLutSize ? Abc_MaxInt(Level0+1, Level1+1) : ABC_INFINITY; + int * pCutRes = pCut11; + int LevCur = Lev11; + if ( Lev01 < LevCur || (Lev01 == LevCur && pCut01[0] < pCutRes[0]) ) + { + pCutRes = pCut01; + LevCur = Lev01; + } + if ( Lev10 < LevCur || (Lev10 == LevCur && pCut10[0] < pCutRes[0]) ) + { + pCutRes = pCut10; + LevCur = Lev10; + } + if ( Lev00 < LevCur || (Lev00 == LevCur && pCut00[0] < pCutRes[0]) ) + { + pCutRes = pCut00; + LevCur = Lev00; + } + assert( iFan0 != iFan1 ); + assert( Vec_IntEntry(p->vLutLevs, Node) == 0 ); + Vec_IntWriteEntry( p->vLutLevs, Node, LevCur ); + assert( pCutRes[0] <= p->pPars->nLutSize ); + memcpy( Sbd_ObjCut(p, Node), pCutRes, sizeof(int) * (pCutRes[0] + 1) ); + //printf( "Setting node %d with delay %d.\n", Node, LevCur ); + return LevCur == 1; // LevCur == Abc_MaxInt(Level0, Level1); +} +int Sbd_ManDelay( Sbd_Man_t * p ) +{ + int i, Id, Delay = 0; + Gia_ManForEachCoDriverId( p->pGia, Id, i ) + Delay = Abc_MaxInt( Delay, Vec_IntEntry(p->vLutLevs, Id) ); + return Delay; +} +void Sbd_ManMergeTest( Sbd_Man_t * p ) +{ + int Node; + Gia_ManForEachAndId( p->pGia, Node ) + Sbd_ManMergeCuts( p, Node ); + printf( "Delay %d.\n", Sbd_ManDelay(p) ); +} + +void Sbd_ManFindCut_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( pObj->fMark1 ) + return; + pObj->fMark1 = 1; + if ( pObj->fMark0 ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Sbd_ManFindCut_rec( p, Gia_ObjFanin0(pObj) ); + Sbd_ManFindCut_rec( p, Gia_ObjFanin1(pObj) ); +} +void Sbd_ManFindCutUnmark_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( !pObj->fMark1 ) + return; + pObj->fMark1 = 0; + if ( pObj->fMark0 ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Sbd_ManFindCutUnmark_rec( p, Gia_ObjFanin0(pObj) ); + Sbd_ManFindCutUnmark_rec( p, Gia_ObjFanin1(pObj) ); +} +void Sbd_ManFindCut( Sbd_Man_t * p, int Node, Vec_Int_t * vCutLits ) +{ + int pCut[SBD_MAX_LUTSIZE+1]; + int i, LevelMax = 0; + // label reachable nodes + Gia_Obj_t * pTemp, * pObj = Gia_ManObj(p->pGia, Node); + Sbd_ManFindCut_rec( p->pGia, pObj ); + // collect + pCut[0] = 0; + Gia_ManForEachObjVec( vCutLits, p->pGia, pTemp, i ) + if ( pTemp->fMark1 ) + { + LevelMax = Abc_MaxInt( LevelMax, Vec_IntEntry(p->vLutLevs, Gia_ObjId(p->pGia, pTemp)) ); + pCut[1+pCut[0]++] = Gia_ObjId(p->pGia, pTemp); + } + assert( pCut[0] <= p->pPars->nLutSize ); + // unlabel reachable nodes + Sbd_ManFindCutUnmark_rec( p->pGia, pObj ); + // create cut + assert( Vec_IntEntry(p->vLutLevs, Node) == 0 ); + Vec_IntWriteEntry( p->vLutLevs, Node, LevelMax+1 ); + memcpy( Sbd_ObjCut(p, Node), pCut, sizeof(int) * (pCut[0] + 1) ); +} + +int Sbd_ManImplement( Sbd_Man_t * p, int Pivot, word Truth ) +{ + Gia_Obj_t * pObj; + int i, k, w, iLit, Entry, Node; + int iObjLast = Gia_ManObjNum(p->pGia); + int iCurLev = Vec_IntEntry(p->vLutLevs, Pivot); + int iNewLev; + // collect leaf literals + Vec_IntClear( p->vLits ); + Vec_IntForEachEntry( p->vDivVars, Node, i ) + { + Node = Vec_IntEntry( p->vWinObjs, Node ); + if ( Vec_IntEntry(p->vMirrors, Node) >= 0 ) + Vec_IntPush( p->vLits, Vec_IntEntry(p->vMirrors, Node) ); + else + Vec_IntPush( p->vLits, Abc_Var2Lit(Node, 0) ); + } + // pretend to have MUXes +// assert( p->pGia->pMuxes == NULL ); + if ( p->pGia->nXors && p->pGia->pMuxes == NULL ) + p->pGia->pMuxes = (unsigned *)p; + // derive new function of the node + iLit = Dsm_ManTruthToGia( p->pGia, &Truth, p->vLits, p->vCover ); + if ( p->pGia->pMuxes == (unsigned *)p ) + p->pGia->pMuxes = NULL; + // remember this function + assert( Vec_IntEntry(p->vMirrors, Pivot) == -1 ); + Vec_IntWriteEntry( p->vMirrors, Pivot, iLit ); + if ( p->pPars->fVerbose ) + printf( "Replacing node %d by literal %d.\n", Pivot, iLit ); + // translate literals into variables + Vec_IntForEachEntry( p->vLits, Entry, i ) + Vec_IntWriteEntry( p->vLits, i, Abc_Lit2Var(Entry) ); + // label inputs + Gia_ManForEachObjVec( p->vLits, p->pGia, pObj, i ) + pObj->fMark0 = 1; + // extend data-structure to accommodate new nodes + assert( Vec_IntSize(p->vLutLevs) == iObjLast ); + for ( i = iObjLast; i < Gia_ManObjNum(p->pGia); i++ ) + { + Vec_IntPush( p->vLutLevs, 0 ); + Vec_IntPush( p->vObj2Var, 0 ); + Vec_IntPush( p->vMirrors, -1 ); + Vec_IntFillExtra( p->vLutCuts, Vec_IntSize(p->vLutCuts) + p->pPars->nLutSize + 1, 0 ); + Sbd_ManFindCut( p, i, p->vLits ); + for ( k = 0; k < 4; k++ ) + for ( w = 0; w < p->pPars->nWords; w++ ) + Vec_WrdPush( p->vSims[k], 0 ); + } + // unlabel inputs + Gia_ManForEachObjVec( p->vLits, p->pGia, pObj, i ) + pObj->fMark0 = 0; + // make sure delay reduction is achieved + iNewLev = Vec_IntEntry( p->vLutLevs, Abc_Lit2Var(iLit) ); + assert( iNewLev < iCurLev ); + // update delay of the initial node + assert( Vec_IntEntry(p->vLutLevs, Pivot) == iCurLev ); + Vec_IntWriteEntry( p->vLutLevs, Pivot, iNewLev ); + p->nChanges++; + return 0; +} + +/**Function************************************************************* + + Synopsis [Derives new AIG after resynthesis.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sbd_ManDerive_rec( Gia_Man_t * pNew, Gia_Man_t * p, int Node, Vec_Int_t * vMirrors ) +{ + Gia_Obj_t * pObj; + int Obj = Node; + if ( Vec_IntEntry(vMirrors, Node) >= 0 ) + Obj = Abc_Lit2Var( Vec_IntEntry(vMirrors, Node) ); + pObj = Gia_ManObj( p, Obj ); + if ( !~pObj->Value ) + { + assert( Gia_ObjIsAnd(pObj) ); + Sbd_ManDerive_rec( pNew, p, Gia_ObjFaninId0(pObj, Obj), vMirrors ); + Sbd_ManDerive_rec( pNew, p, Gia_ObjFaninId1(pObj, Obj), vMirrors ); + if ( Gia_ObjIsXor(pObj) ) + pObj->Value = Gia_ManHashXorReal( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + // set the original node as well + if ( Obj != Node ) + Gia_ManObj(p, Node)->Value = Abc_LitNotCond( pObj->Value, Abc_LitIsCompl(Vec_IntEntry(vMirrors, Node)) ); +} +Gia_Man_t * Sbd_ManDerive( Gia_Man_t * p, Vec_Int_t * vMirrors ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + if ( p->pMuxes ) + pNew->pMuxes = ABC_CALLOC( unsigned, Gia_ManObjNum(p) ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachCo( p, pObj, i ) + Sbd_ManDerive_rec( pNew, p, Gia_ObjFaninId0p(p, pObj), vMirrors ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Gia_ManTransferTiming( pNew, p ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Performs delay optimization for the given LUT size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sbd_NtkPerformOne( Sbd_Man_t * p, int Pivot ) +{ + int RetValue; word Truth = 0; + if ( Sbd_ManMergeCuts( p, Pivot ) ) + return; + //if ( Pivot != 344 ) + // continue; + if ( p->pPars->fVerbose ) + printf( "\nLooking at node %d\n", Pivot ); + if ( Sbd_ManWindow( p, Pivot ) ) + return; + RetValue = Sbd_ManCheckConst( p, Pivot ); + if ( RetValue >= 0 ) + Vec_IntWriteEntry( p->vMirrors, Pivot, RetValue ); + else if ( Sbd_ManExplore( p, Pivot, &Truth ) ) + Sbd_ManImplement( p, Pivot, Truth ); +} +Gia_Man_t * Sbd_NtkPerform( Gia_Man_t * pGia, Sbd_Par_t * pPars ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Sbd_Man_t * p = Sbd_ManStart( pGia, pPars ); + int nNodesOld = Gia_ManObjNum(pGia);//, Count = 0; + int k, Pivot; + assert( pPars->nLutSize <= 6 ); + //Sbd_ManMergeTest( p ); + //return NULL; + if ( pGia->pManTime != NULL && Tim_ManBoxNum((Tim_Man_t*)pGia->pManTime) ) + { + Vec_Int_t * vNodes = Gia_ManOrderWithBoxes( pGia ); + Tim_Man_t * pTimOld = (Tim_Man_t *)pGia->pManTime; + pGia->pManTime = Tim_ManDup( pTimOld, 1 ); + Tim_ManIncrementTravId( (Tim_Man_t *)pGia->pManTime ); + Gia_ManForEachObjVec( vNodes, pGia, pObj, k ) + { + Pivot = Gia_ObjId( pGia, pObj ); + if ( Pivot >= nNodesOld ) + continue; + if ( Gia_ObjIsAnd(pObj) ) + Sbd_NtkPerformOne( p, Pivot ); + else if ( Gia_ObjIsCi(pObj) ) + { + int arrTime = Tim_ManGetCiArrival( (Tim_Man_t*)pGia->pManTime, Gia_ObjCioId(pObj) ); + Vec_IntWriteEntry( p->vLutLevs, Pivot, arrTime ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + int arrTime = Vec_IntEntry( p->vLutLevs, Gia_ObjFaninId0(pObj, Pivot) ); + Tim_ManSetCoArrival( (Tim_Man_t*)pGia->pManTime, Gia_ObjCioId(pObj), arrTime ); + } + else if ( !Gia_ObjIsConst0(pObj) ) + assert( 0 ); + } + //Tim_ManPrint( pGia->pManTime ); + Tim_ManStop( (Tim_Man_t *)pGia->pManTime ); + pGia->pManTime = pTimOld; + Vec_IntFree( vNodes ); + } + else + { + Gia_ManForEachAndId( pGia, Pivot ) + if ( Pivot < nNodesOld ) + Sbd_NtkPerformOne( p, Pivot ); + } + printf( "Found %d constants and %d replacements with delay %d. ", p->nConsts, p->nChanges, Sbd_ManDelay(p) ); + p->timeTotal = Abc_Clock() - p->timeTotal; + Abc_PrintTime( 1, "Time", p->timeTotal ); + pNew = Sbd_ManDerive( pGia, p->vMirrors ); + // print runtime statistics + p->timeOther = p->timeTotal - p->timeWin - p->timeCnf - p->timeSat - p->timeCov - p->timeEnu; + if ( 0 ) + { + ABC_PRTP( "Win", p->timeWin , p->timeTotal ); + ABC_PRTP( "Cnf", p->timeCnf , p->timeTotal ); + ABC_PRTP( "Sat", p->timeSat , p->timeTotal ); + ABC_PRTP( "Cov", p->timeCov , p->timeTotal ); + ABC_PRTP( "Enu", p->timeEnu , p->timeTotal ); + ABC_PRTP( "Oth", p->timeOther, p->timeTotal ); + ABC_PRTP( "ALL", p->timeTotal, p->timeTotal ); + } + Sbd_ManStop( p ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/sbd/sbdInt.h b/src/opt/sbd/sbdInt.h new file mode 100644 index 00000000..4c553fb4 --- /dev/null +++ b/src/opt/sbd/sbdInt.h @@ -0,0 +1,78 @@ +/**CFile**************************************************************** + + FileName [rsbInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [SAT-based optimization using internal don't-cares.] + + Synopsis [Internal declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rsbInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__opt_sbdInt__h +#define ABC__opt_sbdInt__h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "misc/vec/vec.h" +#include "sat/bsat/satSolver.h" +#include "misc/util/utilNam.h" +#include "misc/util/utilTruth.h" +#include "map/scl/sclLib.h" +#include "map/scl/sclCon.h" +#include "bool/kit/kit.h" +#include "misc/st/st.h" +#include "map/mio/mio.h" +#include "base/abc/abc.h" +#include "sbd.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_HEADER_START + +#define SBD_SAT_UNDEC 0x1234567812345678 +#define SBD_SAT_SAT 0x8765432187654321 + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== sbdCnf.c ==========================================================*/ + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/opt/sbd/sbdSat.c b/src/opt/sbd/sbdSat.c new file mode 100644 index 00000000..ae865627 --- /dev/null +++ b/src/opt/sbd/sbdSat.c @@ -0,0 +1,797 @@ +/**CFile**************************************************************** + + FileName [sbd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [SAT-based optimization using internal don't-cares.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: sbd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sbdInt.h" +#include "misc/util/utilTruth.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define MAX_M 8 // max inputs +#define MAX_N 30 // max nodes +#define MAX_K 6 // max lutsize +#define MAX_D 8 // max delays + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define SBD_LUTS_MAX 2 +#define SBD_SIZE_MAX 4 +#define SBD_DIV_MAX 16 + +// new AIG manager +typedef struct Sbd_Pro_t_ Sbd_Pro_t; +struct Sbd_Pro_t_ +{ + int nLuts; // LUT count + int nSize; // LUT size + int nDivs; // divisor count + int nVars; // intermediate variables (nLuts * nSize) + int nPars; // total parameter count (nLuts * (1 << nSize) + nLuts * nSize * nDivs) + int pPars1[SBD_LUTS_MAX][1<<SBD_SIZE_MAX]; // lut parameters + int pPars2[SBD_LUTS_MAX][SBD_SIZE_MAX][SBD_DIV_MAX]; // topo parameters + int pVars[SBD_LUTS_MAX][SBD_SIZE_MAX+1]; // internal variables + int pDivs[SBD_DIV_MAX]; // divisor variables (external) +}; + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Sbd_ProblemSetup( Sbd_Pro_t * p, int nLuts, int nSize, int nDivs ) +{ + Vec_Int_t * vCnf = Vec_IntAlloc( 1000 ); + int i, k, d, v, n, iVar = 0; + assert( nLuts >= 1 && nLuts <= 2 ); + memset( p, 0, sizeof(Sbd_Pro_t) ); + p->nLuts = nLuts; + p->nSize = nSize; + p->nDivs = nDivs; + p->nVars = nLuts * nSize; + p->nPars = nLuts * (1 << nSize) + nLuts * nSize * nDivs; + // set parameters + for ( i = 0; i < nLuts; i++ ) + for ( k = 0; k < (1 << nSize); k++ ) + p->pPars1[i][k] = iVar++; + for ( i = 0; i < nLuts; i++ ) + for ( k = 0; k < nSize; k++ ) + for ( d = 0; d < nDivs; d++ ) + p->pPars2[i][k][d] = iVar++; + // set intermediate variables + for ( i = 0; i < nLuts; i++ ) + for ( k = 0; k < nSize; k++ ) + p->pVars[i][k] = iVar++; + // set top variables + for ( i = 1; i < nLuts; i++ ) + p->pVars[i][nSize] = p->pVars[i-1][0]; + // set divisor variables + for ( d = 0; d < nDivs; d++ ) + p->pDivs[d] = iVar++; + assert( iVar == p->nPars + p->nVars + p->nDivs ); + + // input compatiblity clauses + for ( i = 0; i < nLuts; i++ ) + for ( k = (i > 0); k < nSize; k++ ) + for ( d = 0; d < nDivs; d++ ) + for ( n = 0; n < nDivs; n++ ) + { + if ( n < d ) + { + Vec_IntPush( vCnf, Abc_Var2Lit(p->pPars2[i][k][d], 0) ); + Vec_IntPush( vCnf, Abc_Var2Lit(p->pPars2[i][k][n], 0) ); + Vec_IntPush( vCnf, -1 ); + } + else if ( k < nSize-1 ) + { + Vec_IntPush( vCnf, Abc_Var2Lit(p->pPars2[i][k][d], 0) ); + Vec_IntPush( vCnf, Abc_Var2Lit(p->pPars2[i][k+1][n], 0) ); + Vec_IntPush( vCnf, -1 ); + } + } + + // create LUT clauses + for ( i = 0; i < nLuts; i++ ) + for ( k = 0; k < (1 << nSize); k++ ) + for ( n = 0; n < 2; n++ ) + { + for ( v = 0; v < nSize; v++ ) + Vec_IntPush( vCnf, Abc_Var2Lit(p->pPars1[i][v], (k >> v) & 1) ); + Vec_IntPush( vCnf, Abc_Var2Lit(p->pVars[i][nSize], n) ); + Vec_IntPush( vCnf, Abc_Var2Lit(p->pPars1[i][k], !n) ); + Vec_IntPush( vCnf, -1 ); + } + + // create input clauses + for ( i = 0; i < nLuts; i++ ) + for ( k = (i > 0); k < nSize; k++ ) + for ( d = 0; d < nDivs; d++ ) + for ( n = 0; n < 2; n++ ) + { + Vec_IntPush( vCnf, Abc_Var2Lit(p->pPars2[i][k][d], 0) ); + Vec_IntPush( vCnf, Abc_Var2Lit(p->pPars1[i][k], n) ); + Vec_IntPush( vCnf, Abc_Var2Lit(p->pDivs[d], !n) ); + Vec_IntPush( vCnf, -1 ); + } + + return vCnf; +} +// add clauses to the don't-care computation solver +void Sbd_ProblemLoad1( Sbd_Pro_t * p, Vec_Int_t * vCnf, int iStartVar, int * pDivVars, int iTopVar, sat_solver * pSat ) +{ + int pLits[8], nLits, i, k, iLit, RetValue; + int ThisTopVar = p->pVars[0][p->nSize]; + int FirstDivVar = p->nPars + p->nVars; + // add clauses + for ( i = 0; i < Vec_IntSize(vCnf); i++ ) + { + assert( Vec_IntEntry(vCnf, i) != -1 ); + for ( k = i+1; k < Vec_IntSize(vCnf); k++ ) + if ( Vec_IntEntry(vCnf, i) == -1 ) + break; + nLits = 0; + Vec_IntForEachEntryStartStop( vCnf, iLit, i, i, k ) { + if ( Abc_Lit2Var(iLit) == ThisTopVar ) + pLits[nLits++] = Abc_Var2Lit( ThisTopVar, Abc_LitIsCompl(iLit) ); + else if ( Abc_Lit2Var(iLit) >= FirstDivVar ) + pLits[nLits++] = Abc_Var2Lit( pDivVars[Abc_Lit2Var(iLit)-FirstDivVar], Abc_LitIsCompl(iLit) ); + else + pLits[nLits++] = iLit + 2 * iStartVar; + } + assert( nLits <= 8 ); + RetValue = sat_solver_addclause( pSat, pLits, pLits + nLits ); + assert( RetValue ); + } +} +// add clauses to the functionality evaluation solver +void Sbd_ProblemLoad2( Sbd_Pro_t * p, Vec_Wec_t * vCnf, int iStartVar, int * pDivVarValues, int iTopVarValue, sat_solver * pSat ) +{ + Vec_Int_t * vLevel; + int pLits[8], nLits, i, k, iLit, RetValue; + int ThisTopVar = p->pVars[0][p->nSize]; + int FirstDivVar = p->nPars + p->nVars; + int FirstIntVar = p->nPars; + // add clauses + Vec_WecForEachLevel( vCnf, vLevel, i ) + { + nLits = 0; + Vec_IntForEachEntry( vLevel, iLit, k ) { + if ( Abc_Lit2Var(iLit) == ThisTopVar ) + { + if ( Abc_LitIsCompl(iLit) == iTopVarValue ) + break; + continue; + } + else if ( Abc_Lit2Var(iLit) >= FirstDivVar ) + { + if ( Abc_LitIsCompl(iLit) == pDivVarValues[Abc_Lit2Var(iLit)-FirstDivVar] ) + break; + continue; + } + else if ( Abc_Lit2Var(iLit) >= FirstIntVar ) + pLits[nLits++] = iLit + 2 * iStartVar; + else + pLits[nLits++] = iLit; + } + if ( k < Vec_IntSize(vLevel) ) + continue; + assert( nLits <= 8 ); + RetValue = sat_solver_addclause( pSat, pLits, pLits + nLits ); + assert( RetValue ); + } +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +sat_solver * Sbd_SolverTopo( int M, int N, int K, int pVars[MAX_N][MAX_M+MAX_N][MAX_K], int pVars2[MAX_M+MAX_N][MAX_D], int pDelays[], int Req, int * pnVars ) // inputs, nodes, lutsize +{ + sat_solver * pSat = NULL; + Vec_Int_t * vTemp = Vec_IntAlloc(100); + // assign vars + int RetValue, n, i, j, j2, k, k2, d, Count, nVars = 0; + for ( n = 0; n < N; n++ ) + for ( i = 0; i < M+N; i++ ) + for ( k = 0; k < K; k++ ) + pVars[n][i][k] = -1; + for ( n = 0; n < N; n++ ) + for ( i = 0; i < M+n; i++ ) + for ( k = 0; k < K; k++ ) + pVars[n][i][k] = nVars++; + printf( "Number of topo vars = %d.\n", nVars ); + *pnVars = nVars; + // add constraints + pSat = sat_solver_new(); + sat_solver_setnvars( pSat, nVars ); + // each node is used + for ( i = 0; i < M+N-1; i++ ) + { + Vec_IntClear( vTemp ); + for ( n = 0; n < N; n++ ) + for ( k = 0; k < K; k++ ) + if ( pVars[n][i][k] >= 0 ) + Vec_IntPush( vTemp, Abc_Var2Lit(pVars[n][i][k], 0) ); + RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); + assert( RetValue ); + } + printf( "Added %d node connectivity constraints.\n", i ); + // each fanin of each node is connected exactly once + Count = 0; + for ( n = 0; n < N; n++ ) + for ( k = 0; k < K; k++ ) + { + // connected + Vec_IntClear( vTemp ); + for ( i = 0; i < M+n; i++ ) + Vec_IntPush( vTemp, Abc_Var2Lit(pVars[n][i][k], 0) ); + RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); + assert( RetValue ); + // exactly once + for ( i = 0; i < M+n; i++ ) + for ( j = i+1; j < M+n; j++ ) + { + Vec_IntFillTwo( vTemp, 2, Abc_Var2Lit(pVars[n][i][k], 1), Abc_Var2Lit(pVars[n][j][k], 1) ); + RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); + assert( RetValue ); + Count++; + } + } + printf( "Added %d fanin connectivity constraints.\n", Count ); + // node fanins are unique + Count = 0; + for ( n = 0; n < N; n++ ) + for ( i = 0; i < M+n; i++ ) + for ( k = 0; k < K; k++ ) + for ( j = i; j < M+n; j++ ) + for ( k2 = k+1; k2 < K; k2++ ) + { + Vec_IntFillTwo( vTemp, 2, Abc_Var2Lit(pVars[n][i][k], 1), Abc_Var2Lit(pVars[n][j][k2], 1) ); + RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); + assert( RetValue ); + Count++; + } + printf( "Added %d fanin exclusivity constraints.\n", Count ); + // nodes are ordered + Count = 0; + for ( n = 1; n < N; n++ ) + for ( i = 0; i < M+n-1; i++ ) + { + // first of n cannot be smaller than first of n-1 (but can be equal) + for ( j = i+1; j < M+n-1; j++ ) + { + Vec_IntFillTwo( vTemp, 2, Abc_Var2Lit(pVars[n][i][0], 1), Abc_Var2Lit(pVars[n-1][j][0], 1) ); + RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); + assert( RetValue ); + Count++; + } + // if first nodes of n and n-1 are equal, second nodes are ordered + Vec_IntFillTwo( vTemp, 2, Abc_Var2Lit(pVars[n][i][0], 1), Abc_Var2Lit(pVars[n-1][i][0], 1) ); + for ( j = 0; j < i; j++ ) + for ( j2 = j+1; j2 < i; j2++ ) + { + Vec_IntPushTwo( vTemp, Abc_Var2Lit(pVars[n][j][1], 1), Abc_Var2Lit(pVars[n-1][j2][1], 1) ); + RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); + assert( RetValue ); + Vec_IntShrink( vTemp, 2 ); + Count++; + } + } + printf( "Added %d node ordering constraints.\n", Count ); + // exclude fanins of two-input nodes + Count = 0; + if ( K == 2 ) + for ( n = 1; n < N; n++ ) + for ( i = M; i < M+n; i++ ) + for ( j = 0; j < i; j++ ) + for ( k = 0; k < K; k++ ) + { + Vec_IntClear( vTemp ); + Vec_IntPush( vTemp, Abc_Var2Lit(pVars[n][i][0], 1) ); + Vec_IntPush( vTemp, Abc_Var2Lit(pVars[n][j][1], 1) ); + Vec_IntPush( vTemp, Abc_Var2Lit(pVars[i-M][j][k], 1) ); + RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); + assert( RetValue ); + Count++; + } + printf( "Added %d two-node non-triviality constraints.\n", Count ); + + + // assign delay vars + assert( Req < MAX_D-1 ); + for ( i = 0; i < M+N; i++ ) + for ( d = 0; d < MAX_D; d++ ) + pVars2[i][d] = nVars++; + printf( "Number of total vars = %d.\n", nVars ); + // set input delays + for ( i = 0; i < M; i++ ) + { + assert( pDelays[i] < MAX_D-2 ); + Vec_IntFill( vTemp, 1, Abc_Var2Lit(pVars2[i][pDelays[i]], 0) ); + RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); + assert( RetValue ); + } + // set output delay + for ( k = Req; k < MAX_D; k++ ) + { + Vec_IntFill( vTemp, 1, Abc_Var2Lit(pVars2[M+N-1][Req+1], 1) ); + RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); + assert( RetValue ); + } + // set internal nodes + for ( n = 0; n < N; n++ ) + for ( i = 0; i < M+n; i++ ) + for ( k = 0; k < K; k++ ) + for ( d = 0; d < MAX_D-1; d++ ) + { + Vec_IntFill( vTemp, 1, Abc_Var2Lit(pVars[n][i][k], 1) ); + Vec_IntPush( vTemp, Abc_Var2Lit(pVars2[i][d], 1) ); + Vec_IntPush( vTemp, Abc_Var2Lit(pVars2[M+n][d+1], 0) ); + RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); + assert( RetValue ); + } + + + Vec_IntFree( vTemp ); + return pSat; +} +void Sbd_SolverTopoPrint( sat_solver * pSat, int M, int N, int K, int pVars[MAX_N][MAX_M+MAX_N][MAX_K] ) +{ + int n, i, k; + printf( "Solution:\n" ); + printf( " | " ); + for ( n = 0; n < N; n++ ) + printf( "%2d ", M+n ); + printf( "\n" ); + for ( i = M+N-2; i >= 0; i-- ) + { + printf( "%2d %c | ", i, i < M ? 'i' : ' ' ); + for ( n = 0; n < N; n++ ) + { + for ( k = K-1; k >= 0; k-- ) + if ( pVars[n][i][k] == -1 ) + printf( " " ); + else + printf( "%c", sat_solver_var_value(pSat, pVars[n][i][k]) ? '*' : '.' ); + printf( " " ); + } + printf( "\n" ); + } +} +void Sbd_SolverTopoTest() +{ + int M = 8; // 6; // inputs + int N = 3; // 16; // nodes + int K = 4; // 2; // lutsize + int status, v, nVars, nIter, nSols = 0; + int pVars[MAX_N][MAX_M+MAX_N][MAX_K]; // 20 x 32 x 6 = 3840 + int pVars2[MAX_M+MAX_N][MAX_D]; // 20 x 32 x 6 = 3840 + int pDelays[MAX_M] = {1,0,0,0,1}; + abctime clk = Abc_Clock(); + Vec_Int_t * vLits = Vec_IntAlloc(100); + sat_solver * pSat = Sbd_SolverTopo( M, N, K, pVars, pVars2, pDelays, 2, &nVars ); + for ( nIter = 0; nIter < 1000000; nIter++ ) + { + // find onset minterm + status = sat_solver_solve( pSat, NULL, NULL, 0, 0, 0, 0 ); + if ( status == l_Undef ) + break; + if ( status == l_False ) + break; + assert( status == l_True ); + nSols++; + // print solution + if ( nIter < 5 ) + Sbd_SolverTopoPrint( pSat, M, N, K, pVars ); + // remember variable values + Vec_IntClear( vLits ); + for ( v = 0; v < nVars; v++ ) + if ( sat_solver_var_value(pSat, v) ) + Vec_IntPush( vLits, Abc_Var2Lit(v, 1) ); + // add breaking clause + status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits) ); + if ( status == 0 ) + break; + //if ( nIter == 5 ) + // break; + } + sat_solver_delete( pSat ); + Vec_IntFree( vLits ); + printf( "Found %d solutions. ", nSols ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + + + +/**Function************************************************************* + + Synopsis [Synthesize random topology.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sbd_SolverSynth( int M, int N, int K, int pLuts[MAX_N][MAX_K] ) +{ + int Used[MAX_M+MAX_N] = {0}; + int nUnused = M; + int n, iFan0, iFan1; + srand( time(NULL) ); + for ( n = 0; nUnused < N - n; n++ ) + { + iFan0 = iFan1 = 0; + while ( (iFan0 = rand() % (M + n)) == (iFan1 = rand() % (M + n)) ) + ; + pLuts[n][0] = iFan0; + pLuts[n][1] = iFan1; + if ( Used[iFan0] == 0 ) + { + Used[iFan0] = 1; + nUnused--; + } + if ( Used[iFan1] == 0 ) + { + Used[iFan1] = 1; + nUnused--; + } + nUnused++; + } + if ( nUnused == N - n ) + { + // undo the first one + for ( iFan0 = 0; iFan0 < M+n; iFan0++ ) + if ( Used[iFan0] ) + { + Used[iFan0] = 0; + nUnused++; + break; + } + + } + assert( nUnused == N - n + 1 ); + for ( ; n < N; n++ ) + { + for ( iFan0 = 0; iFan0 < M+n; iFan0++ ) + if ( Used[iFan0] == 0 ) + { + Used[iFan0] = 1; + break; + } + assert( iFan0 < M+n ); + for ( iFan1 = 0; iFan1 < M+n; iFan1++ ) + if ( Used[iFan1] == 0 ) + { + Used[iFan1] = 1; + break; + } + assert( iFan1 < M+n ); + pLuts[n][0] = iFan0; + pLuts[n][1] = iFan1; + } + + printf( "{\n" ); + for ( n = 0; n < N; n++ ) + printf( " {%d, %d}%s // %d\n", pLuts[n][0], pLuts[n][1], n==N-1 ? "" :",", M+n ); + printf( "};\n" ); +} + + +/**Function************************************************************* + + Synopsis [Compute truth table for the given parameter settings.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word Sbd_SolverTruth( int M, int N, int K, int pLuts[MAX_N][MAX_K], int pValues[MAX_N*((1<<MAX_K)-1)] ) +{ + int i, k, v, nLutPars = (1 << K) - 1; + word Truths[MAX_M+MAX_N]; + assert( M <= 6 && N <= MAX_N ); + for ( i = 0; i < M; i++ ) + Truths[i] = s_Truths6[i]; + for ( i = 0; i < N; i++ ) + { + word Truth = 0, Mint; + for ( k = 1; k <= nLutPars; k++ ) + { + if ( !pValues[i*nLutPars+k-1] ) + continue; + Mint = ~(word)0; + for ( v = 0; v < K; v++ ) + Mint &= ((k >> v) & 1) ? Truths[pLuts[i][v]] : ~Truths[pLuts[i][v]]; + Truth |= Mint; + } + Truths[M+i] = Truth; + } + return Truths[M+N-1]; +} +word * Sbd_SolverTruthWord( int M, int N, int K, int pLuts[MAX_N][MAX_K], int pValues[MAX_N*((1<<MAX_K)-1)], word * pTruthsElem, int fCompl ) +{ + int i, k, v, nLutPars = (1 << K) - 1; + int nWords = Abc_TtWordNum( M ); + word * pRes = pTruthsElem + (M+N-1)*nWords; + assert( M <= MAX_M && N <= MAX_N ); + for ( i = 0; i < N; i++ ) + { + word * pMint, * pTruth = pTruthsElem + (M+i)*nWords; + Abc_TtClear( pTruth, nWords ); + for ( k = 1; k <= nLutPars; k++ ) + { + if ( !pValues[i*nLutPars+k-1] ) + continue; + pMint = pTruthsElem + (M+N)*nWords; + Abc_TtFill( pMint, nWords ); + for ( v = 0; v < K; v++ ) + { + word * pFanin = pTruthsElem + pLuts[i][v]*nWords; + Abc_TtAndSharp( pMint, pMint, pFanin, nWords, ((k >> v) & 1) == 0 ); + } + Abc_TtOr( pTruth, pTruth, pMint, nWords ); + } + } + if ( fCompl ) + Abc_TtNot( pRes, nWords ); + return pRes; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sbd_SolverFunc( int M, int N, int K, int pLuts[MAX_N][MAX_K], word * pTruthInit, int * pValues ) +{ + int fVerbose = 0; + abctime clk = Abc_Clock(); + abctime clk2, clkOther = 0; + sat_solver * pSat = NULL; + int nWords = Abc_TtWordNum(M); + int pLits[MAX_K+2], pLits2[MAX_K+2], nLits; + int nLutPars = (1 << K) - 1, nVars = N * nLutPars; + int i, k, m, status, iMint, Iter, fCompl = (int)(pTruthInit[0] & 1); + // create truth tables + word * pTruthNew, * pTruths = ABC_ALLOC( word, Abc_TtWordNum(MAX_N) * (MAX_M + MAX_N + 1) ); + Abc_TtElemInit2( pTruths, M ); + // create solver + pSat = sat_solver_new(); + sat_solver_setnvars( pSat, nVars ); + printf( "Number of parameters %d x %d = %d.\n", N, nLutPars, nVars ); + // start with the last minterm +// iMint = (1 << M) - 1; + iMint = 1; + for ( Iter = 0; Iter < (1 << M); Iter++ ) + { + // assign the first intermediate variable + int nVarStart = sat_solver_nvars(pSat); + sat_solver_setnvars( pSat, nVarStart + N - 1 ); + // add clauses for nodes + //if ( fVerbose ) + printf( "Iter %3d : Mint = %3d. Conflicts =%8d.\n", Iter, iMint, sat_solver_nconflicts(pSat) ); + for ( i = 0; i < N; i++ ) + for ( m = 0; m <= nLutPars; m++ ) + { + if ( fVerbose ) + printf( "i = %d. m = %d.\n", i, m ); + // selector variables + nLits = 0; + for ( k = 0; k < K; k++ ) + { + if ( pLuts[i][k] >= M ) + { + assert( pLuts[i][k] - M < N - 1 ); + pLits[nLits] = pLits2[nLits] = Abc_Var2Lit( nVarStart + pLuts[i][k] - M, (m >> k) & 1 ); + nLits++; + } + else if ( ((iMint >> pLuts[i][k]) & 1) != ((m >> k) & 1) ) + break; + } + if ( k < K ) + continue; + // add parameter + if ( m ) + { + pLits[nLits] = Abc_Var2Lit( i*nLutPars + m-1, 1 ); + pLits2[nLits] = Abc_Var2Lit( i*nLutPars + m-1, 0 ); + nLits++; + } + // node variable + if ( i != N - 1 ) + { + pLits[nLits] = Abc_Var2Lit( nVarStart + i, 0 ); + pLits2[nLits] = Abc_Var2Lit( nVarStart + i, 1 ); + nLits++; + } + // add clauses + if ( i != N - 1 || Abc_TtGetBit(pTruthInit, iMint) != fCompl ) + { + status = sat_solver_addclause( pSat, pLits2, pLits2 + nLits ); + if ( status == 0 ) + { + fCompl = -1; + goto finish; + } + } + if ( (i != N - 1 || Abc_TtGetBit(pTruthInit, iMint) == fCompl) && m > 0 ) + { + status = sat_solver_addclause( pSat, pLits, pLits + nLits ); + if ( status == 0 ) + { + fCompl = -1; + goto finish; + } + } + } + + // run SAT solver + status = sat_solver_solve( pSat, NULL, NULL, 0, 0, 0, 0 ); + if ( status == l_Undef ) + break; + if ( status == l_False ) + { + fCompl = -1; + goto finish; + } + assert( status == l_True ); + + // collect values + for ( i = 0; i < nVars; i++ ) + pValues[i] = sat_solver_var_value(pSat, i); + + clk2 = Abc_Clock(); + pTruthNew = Sbd_SolverTruthWord( M, N, K, pLuts, pValues, pTruths, fCompl ); + clkOther += Abc_Clock() - clk2; + + if ( fVerbose ) + { + for ( i = 0; i < nVars; i++ ) + printf( "%d=%d ", i, pValues[i] ); + printf( " " ); + for ( i = nVars; i < sat_solver_nvars(pSat); i++ ) + printf( "%d=%d ", i, sat_solver_var_value(pSat, i) ); + printf( "\n" ); + Extra_PrintBinary( stdout, (unsigned *)pTruthInit, (1 << M) ); printf( "\n" ); + Extra_PrintBinary( stdout, (unsigned *)pTruthNew, (1 << M) ); printf( "\n" ); + } + if ( Abc_TtEqual(pTruthInit, pTruthNew, nWords) ) + break; + + // get new minterm + iMint = Abc_TtFindFirstDiffBit( pTruthInit, pTruthNew, M ); + } +finish: + printf( "Finished after %d iterations and %d conflicts. ", Iter, sat_solver_nconflicts(pSat) ); + sat_solver_delete( pSat ); + ABC_FREE( pTruths ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Abc_PrintTime( 1, "Time", clkOther ); + return fCompl; +} +void Sbd_SolverFuncTest() +{ +// int M = 4; // 6; // inputs +// int N = 3; // 16; // nodes +// int K = 2; // 2; // lutsize +// word Truth = ~((word)3 << 8); +// int pLuts[MAX_N][MAX_K] = { {0,1}, {2,3}, {4,5}, {6,7}, {8,9} }; + +/* + int M = 6; // 6; // inputs + int N = 19; // 16; // nodes + int K = 2; // 2; // lutsize + word pTruth[4] = { ABC_CONST(0x9ef7a8d9c7193a0f), 0, 0, 0 }; + int pLuts[MAX_N][MAX_K] = { + {3, 5}, {1, 6}, {0, 5}, {8, 2}, {7, 9}, + {0, 1}, {2, 11}, {5, 12}, {3, 13}, {1, 14}, + {10, 15}, {11, 2}, {3, 17}, {9, 18}, {0, 13}, + {20, 7}, {19, 21}, {4, 16}, {23, 22} + }; +*/ + +/* + int M = 6; // 6; // inputs + int N = 5; // 16; // nodes + int K = 4; // 2; // lutsize + word Truth = ABC_CONST(0x9ef7a8d9c7193a0f); + int pLuts[MAX_N][MAX_K] = { + {0, 1, 2, 3}, // 6 + {1, 2, 3, 4}, // 7 + {2, 3, 4, 5}, // 8 + {0, 1, 4, 5}, // 9 + {6, 7, 8, 9} // 10 + }; +*/ + +/* + int M = 8; // 6; // inputs + int N = 7; // 16; // nodes + int K = 2; // 2; // lutsize +// word pTruth[4] = { 0, 0, 0, ABC_CONST(0x8000000000000000) }; +// word pTruth[4] = { ABC_CONST(0x0000000000000001), 0, 0, 0 }; + word pTruth[4] = { 0, 0, 0, ABC_CONST(0x0000000000020000) }; + int pLuts[MAX_N][MAX_K] = { {0,1}, {2,3}, {4,5}, {6,7}, {8,9}, {10,11}, {12,13} }; +*/ + + int M = 8; // 6; // inputs + int N = 7; // 16; // nodes + int K = 2; // 2; // lutsize + word pTruth[4] = { ABC_CONST(0x0000080000020000), ABC_CONST(0x0000000000020000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000020000) }; + int pLuts[MAX_N][MAX_K] = { {0,1}, {2,3}, {4,5}, {6,7}, {8,9}, {10,11}, {12,13} }; + + int pValues[MAX_N*((1<<MAX_K)-1)]; + int Res, i, k, nLutPars = (1 << K) - 1; + + //Sbd_SolverSynth( M, N, K, pLuts ); + + Res = Sbd_SolverFunc( M, N, K, pLuts, pTruth, pValues ); + if ( Res == -1 ) + { + printf( "Solution does not exist.\n" ); + return; + } + printf( "Result (compl = %d):\n", Res ); + for ( i = 0; i < N; i++ ) + { + for ( k = nLutPars-1; k >= 0; k-- ) + printf( "%d", pValues[i*nLutPars+k] ); + printf( "0\n" ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/sbd/sbdSim.c b/src/opt/sbd/sbdSim.c new file mode 100644 index 00000000..3bb44159 --- /dev/null +++ b/src/opt/sbd/sbdSim.c @@ -0,0 +1,310 @@ +/**CFile**************************************************************** + + FileName [sbdSim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [SAT-based optimization using internal don't-cares.] + + Synopsis [Simulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: sbdSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sbdInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline word * Sbd_ObjSims( Gia_Man_t * p, int i ) { return Vec_WrdEntryP( p->vSims, p->iPatsPi * i ); } +static inline word * Sbd_ObjCtrl( Gia_Man_t * p, int i ) { return Vec_WrdEntryP( p->vSimsPi, p->iPatsPi * i ); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [This does not work.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sbd_GiaSimRoundBack2( Gia_Man_t * p ) +{ + int nWords = p->iPatsPi; + Gia_Obj_t * pObj; + int w, i, Id; + // init primary outputs + Gia_ManForEachCoId( p, Id, i ) + for ( w = 0; w < nWords; w++ ) + Sbd_ObjSims(p, Id)[w] = Gia_ManRandomW(0); + // transfer to nodes + Gia_ManForEachCo( p, pObj, i ) + { + word * pSims = Sbd_ObjSims(p, Gia_ObjId(p, pObj)); + Abc_TtCopy( Sbd_ObjSims(p, Gia_ObjFaninId0p(p, pObj)), pSims, nWords, Gia_ObjFaninC0(pObj) ); + } + // simulate nodes + Gia_ManForEachAndReverse( p, pObj, i ) + { + word * pSims = Sbd_ObjSims(p, i); + word * pSims0 = Sbd_ObjSims(p, Gia_ObjFaninId0(pObj, i)); + word * pSims1 = Sbd_ObjSims(p, Gia_ObjFaninId1(pObj, i)); + word Rand = Gia_ManRandomW(0); + for ( w = 0; w < nWords; w++ ) + { + pSims0[w] = pSims[w] | Rand; + pSims1[w] = pSims[w] | ~Rand; + } + if ( Gia_ObjFaninC0(pObj) ) Abc_TtNot( pSims0, nWords ); + if ( Gia_ObjFaninC1(pObj) ) Abc_TtNot( pSims1, nWords ); + } + // primary inputs are initialized +} + + +/**Function************************************************************* + + Synopsis [Tries to falsify a sequence of two-literal SAT problems.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sbd_GiaSatOne_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int Value, int fFirst, int iPat ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return (int)pObj->fMark0 == Value; + Gia_ObjSetTravIdCurrent(p, pObj); + pObj->fMark0 = Value; + if ( Gia_ObjIsCi(pObj) ) + { + word * pSims = Sbd_ObjSims(p, Gia_ObjId(p, pObj)); + if ( Abc_TtGetBit( pSims, iPat ) != Value ) + Abc_TtXorBit( pSims, iPat ); + return 1; + } + assert( Gia_ObjIsAnd(pObj) ); + assert( !Gia_ObjIsXor(pObj) ); + if ( Value ) + return Sbd_GiaSatOne_rec( p, Gia_ObjFanin0(pObj), !Gia_ObjFaninC0(pObj), fFirst, iPat ) && + Sbd_GiaSatOne_rec( p, Gia_ObjFanin1(pObj), !Gia_ObjFaninC1(pObj), fFirst, iPat ); + if ( fFirst ) + return Sbd_GiaSatOne_rec( p, Gia_ObjFanin0(pObj), Gia_ObjFaninC0(pObj), fFirst, iPat ); + else + return Sbd_GiaSatOne_rec( p, Gia_ObjFanin1(pObj), Gia_ObjFaninC1(pObj), fFirst, iPat ); +} +int Sbd_GiaSatOne( Gia_Man_t * p, Vec_Int_t * vPairs ) +{ + int k, n, Var1, Var2, iPat = 0; + //Gia_ManSetPhase( p ); + Vec_IntForEachEntryDouble( vPairs, Var1, Var2, k ) + { + Gia_Obj_t * pObj1 = Gia_ManObj( p, Var1 ); + Gia_Obj_t * pObj2 = Gia_ManObj( p, Var2 ); + assert( Var2 > 0 ); + if ( Var1 == 0 ) + { + for ( n = 0; n < 2; n++ ) + { + Gia_ManIncrementTravId( p ); + if ( Sbd_GiaSatOne_rec(p, pObj2, !pObj2->fPhase, n, iPat) ) + { + iPat++; + break; + } + } + printf( "%c", n == 2 ? '.' : 'c' ); + } + else + { + for ( n = 0; n < 2; n++ ) + { + Gia_ManIncrementTravId( p ); + if ( Sbd_GiaSatOne_rec(p, pObj1, !pObj1->fPhase, n, iPat) && Sbd_GiaSatOne_rec(p, pObj2, pObj2->fPhase, n, iPat) ) + { + iPat++; + break; + } + Gia_ManIncrementTravId( p ); + if ( Sbd_GiaSatOne_rec(p, pObj1, pObj1->fPhase, n, iPat) && Sbd_GiaSatOne_rec(p, pObj2, !pObj2->fPhase, n, iPat) ) + { + iPat++; + break; + } + } + printf( "%c", n == 2 ? '.' : 'e' ); + } + if ( iPat == 64 * p->iPatsPi - 1 ) + break; + } + printf( "\n" ); + return iPat; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sbd_GiaSimRoundBack( Gia_Man_t * p ) +{ + extern void Sbd_GiaSimRound( Gia_Man_t * p, int fTry, Vec_Int_t ** pvMap ); + Vec_Int_t * vReprs = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_Int_t * vPairs = Vec_IntAlloc( 1000 ); + Vec_Int_t * vMap; // maps each node into its class + int i, nConsts = 0, nClasses = 0, nPats; + Sbd_GiaSimRound( p, 0, &vMap ); + Gia_ManForEachAndId( p, i ) + { + if ( Vec_IntEntry(vMap, i) == 0 ) + Vec_IntPushTwo( vPairs, 0, i ), nConsts++; + else if ( Vec_IntEntry(vReprs, Vec_IntEntry(vMap, i)) == 0 ) + Vec_IntWriteEntry( vReprs, Vec_IntEntry(vMap, i), i ); + else if ( Vec_IntEntry(vReprs, Vec_IntEntry(vMap, i)) != -1 ) + { + Vec_IntPushTwo( vPairs, Vec_IntEntry(vReprs, Vec_IntEntry(vMap, i)), i ); + Vec_IntWriteEntry( vReprs, Vec_IntEntry(vMap, i), -1 ); + nClasses++; + } + } + Vec_IntFree( vMap ); + Vec_IntFree( vReprs ); + printf( "Constants = %d. Classes = %d.\n", nConsts, nClasses ); + + nPats = Sbd_GiaSatOne( p, vPairs ); + Vec_IntFree( vPairs ); + + printf( "Generated %d patterns.\n", nPats ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sbd_GiaSimRound( Gia_Man_t * p, int fTry, Vec_Int_t ** pvMap ) +{ + int nWords = p->iPatsPi; + Vec_Mem_t * vStore; + Gia_Obj_t * pObj; + Vec_Int_t * vMap = Vec_IntStart( Gia_ManObjNum(p) ); + int w, i, Id, fCompl, RetValue; + // init primary inputs + if ( fTry ) + { + Sbd_GiaSimRoundBack( p ); + Gia_ManForEachCiId( p, Id, i ) + Sbd_ObjSims(p, Id)[0] <<= 1; + } + else + { + Gia_ManForEachCiId( p, Id, i ) + for ( w = 0; w < nWords; w++ ) + Sbd_ObjSims(p, Id)[w] = Gia_ManRandomW(0) << !w; + } + // simulate internal nodes + vStore = Vec_MemAlloc( nWords, 16 ); // 2^12 N-word entries per page + Vec_MemHashAlloc( vStore, 1 << 16 ); + RetValue = Vec_MemHashInsert( vStore, Sbd_ObjSims(p, 0) ); // const zero + assert( RetValue == 0 ); + Gia_ManForEachAnd( p, pObj, i ) + { + word * pSims = Sbd_ObjSims(p, i); + if ( Gia_ObjIsXor(pObj) ) + Abc_TtXor( pSims, + Sbd_ObjSims(p, Gia_ObjFaninId0(pObj, i)), + Sbd_ObjSims(p, Gia_ObjFaninId1(pObj, i)), + nWords, + Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pObj) ); + else + Abc_TtAndCompl( pSims, + Sbd_ObjSims(p, Gia_ObjFaninId0(pObj, i)), Gia_ObjFaninC0(pObj), + Sbd_ObjSims(p, Gia_ObjFaninId1(pObj, i)), Gia_ObjFaninC1(pObj), + nWords ); + // hash sim info + fCompl = (int)(pSims[0] & 1); + if ( fCompl ) Abc_TtNot( pSims, nWords ); + Vec_IntWriteEntry( vMap, i, Vec_MemHashInsert(vStore, pSims) ); + if ( fCompl ) Abc_TtNot( pSims, nWords ); + } + Gia_ManForEachCo( p, pObj, i ) + { + word * pSims = Sbd_ObjSims(p, Gia_ObjId(p, pObj)); + Abc_TtCopy( pSims, Sbd_ObjSims(p, Gia_ObjFaninId0p(p, pObj)), nWords, Gia_ObjFaninC0(pObj) ); +// printf( "%d ", Abc_TtCountOnesVec(pSims, nWords) ); + assert( Gia_ObjPhase(pObj) == (int)(pSims[0] & 1) ); + } +// printf( "\n" ); + Vec_MemHashFree( vStore ); + Vec_MemFree( vStore ); + printf( "Objects = %6d. Unique = %6d.\n", Gia_ManAndNum(p), Vec_IntCountUnique(vMap) ); + if ( pvMap ) + *pvMap = vMap; + else + Vec_IntFree( vMap ); +} +void Sbd_GiaSimTest( Gia_Man_t * pGia ) +{ + Gia_ManSetPhase( pGia ); + + // allocate simulation info + pGia->iPatsPi = 32; + pGia->vSims = Vec_WrdStart( Gia_ManObjNum(pGia) * pGia->iPatsPi ); + pGia->vSimsPi = Vec_WrdStart( Gia_ManObjNum(pGia) * pGia->iPatsPi ); + + Gia_ManRandom( 1 ); + + Sbd_GiaSimRound( pGia, 0, NULL ); + Sbd_GiaSimRound( pGia, 0, NULL ); + Sbd_GiaSimRound( pGia, 0, NULL ); + + printf( "\n" ); + Sbd_GiaSimRound( pGia, 1, NULL ); + printf( "\n" ); + Sbd_GiaSimRound( pGia, 1, NULL ); + printf( "\n" ); + Sbd_GiaSimRound( pGia, 1, NULL ); + + Vec_WrdFreeP( &pGia->vSims ); + Vec_WrdFreeP( &pGia->vSimsPi ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/sbd/sbdWin.c b/src/opt/sbd/sbdWin.c new file mode 100644 index 00000000..d722f456 --- /dev/null +++ b/src/opt/sbd/sbdWin.c @@ -0,0 +1,283 @@ +/**CFile**************************************************************** + + FileName [sbd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [SAT-based optimization using internal don't-cares.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: sbd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sbdInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Constructs SAT solver for the window.] + + Description [The window for the pivot node (Pivot) is represented as + a DFS ordered array of objects (vWinObjs) whose indexed in the array + (which will be used as SAT variables) are given in array vObj2Var. + The TFO nodes are listed as the last ones in vWinObjs. The root nodes + are labeled with Abc_LitIsCompl() in vTfo and also given in vRoots.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +sat_solver * Sbd_ManSatSolver( sat_solver * pSat, Gia_Man_t * p, Vec_Int_t * vMirrors, int Pivot, Vec_Int_t * vWinObjs, Vec_Int_t * vObj2Var, Vec_Int_t * vTfo, Vec_Int_t * vRoots ) +{ + Gia_Obj_t * pObj; + int i, iLit = 1, iObj, Fan0, Fan1, Lit0m, Lit1m, Node, fCompl0, fCompl1, RetValue; + int TfoStart = Vec_IntSize(vWinObjs) - Vec_IntSize(vTfo); + int PivotVar = Vec_IntEntry(vObj2Var, Pivot); + //Vec_IntPrint( vWinObjs ); + //Vec_IntPrint( vTfo ); + //Vec_IntPrint( vRoots ); + // create SAT solver + if ( pSat == NULL ) + pSat = sat_solver_new(); + else + sat_solver_restart( pSat ); + sat_solver_setnvars( pSat, Vec_IntSize(vWinObjs) + Vec_IntSize(vTfo) + Vec_IntSize(vRoots) + 32 ); + // create constant 0 clause + sat_solver_addclause( pSat, &iLit, &iLit + 1 ); + // add clauses for all nodes + Vec_IntForEachEntryStart( vWinObjs, iObj, i, 1 ) + { + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + continue; + assert( Gia_ObjIsAnd(pObj) ); + assert( Vec_IntEntry( vMirrors, iObj ) < 0 ); + Node = Vec_IntEntry( vObj2Var, iObj ); + Lit0m = Vec_IntEntry( vMirrors, Gia_ObjFaninId0(pObj, iObj) ); + Lit1m = Vec_IntEntry( vMirrors, Gia_ObjFaninId1(pObj, iObj) ); + Fan0 = Lit0m >= 0 ? Abc_Lit2Var(Lit0m) : Gia_ObjFaninId0(pObj, iObj); + Fan1 = Lit1m >= 0 ? Abc_Lit2Var(Lit1m) : Gia_ObjFaninId1(pObj, iObj); + Fan0 = Vec_IntEntry( vObj2Var, Fan0 ); + Fan1 = Vec_IntEntry( vObj2Var, Fan1 ); + fCompl0 = Gia_ObjFaninC0(pObj) ^ (Lit0m >= 0 && Abc_LitIsCompl(Lit0m)); + fCompl1 = Gia_ObjFaninC1(pObj) ^ (Lit1m >= 0 && Abc_LitIsCompl(Lit1m)); + if ( Gia_ObjIsXor(pObj) ) + sat_solver_add_xor( pSat, Node, Fan0, Fan1, fCompl0 ^ fCompl1 ); + else + sat_solver_add_and( pSat, Node, Fan0, Fan1, fCompl0, fCompl1, 0 ); + } + // add second clauses for the TFO + Vec_IntForEachEntryStart( vWinObjs, iObj, i, TfoStart ) + { + pObj = Gia_ManObj( p, iObj ); + assert( Gia_ObjIsAnd(pObj) ); + assert( Vec_IntEntry( vMirrors, iObj ) < 0 ); + Node = Vec_IntEntry( vObj2Var, iObj ) + Vec_IntSize(vTfo); + Lit0m = Vec_IntEntry( vMirrors, Gia_ObjFaninId0(pObj, iObj) ); + Lit1m = Vec_IntEntry( vMirrors, Gia_ObjFaninId1(pObj, iObj) ); + Fan0 = Lit0m >= 0 ? Abc_Lit2Var(Lit0m) : Gia_ObjFaninId0(pObj, iObj); + Fan1 = Lit1m >= 0 ? Abc_Lit2Var(Lit1m) : Gia_ObjFaninId1(pObj, iObj); + Fan0 = Vec_IntEntry( vObj2Var, Fan0 ); + Fan1 = Vec_IntEntry( vObj2Var, Fan1 ); + Fan0 = Fan0 < TfoStart ? Fan0 : Fan0 + Vec_IntSize(vTfo); + Fan1 = Fan1 < TfoStart ? Fan1 : Fan1 + Vec_IntSize(vTfo); + fCompl0 = Gia_ObjFaninC0(pObj) ^ (Fan0 == PivotVar) ^ (Lit0m >= 0 && Abc_LitIsCompl(Lit0m)); + fCompl1 = Gia_ObjFaninC1(pObj) ^ (Fan1 == PivotVar) ^ (Lit1m >= 0 && Abc_LitIsCompl(Lit1m)); + if ( Gia_ObjIsXor(pObj) ) + sat_solver_add_xor( pSat, Node, Fan0, Fan1, fCompl0 ^ fCompl1 ); + else + sat_solver_add_and( pSat, Node, Fan0, Fan1, fCompl0, fCompl1, 0 ); + } + if ( Vec_IntSize(vRoots) > 0 ) + { + // create XOR clauses for the roots + int nVars = Vec_IntSize(vWinObjs) + Vec_IntSize(vTfo); + Vec_Int_t * vFaninVars = Vec_IntAlloc( Vec_IntSize(vRoots) ); + Vec_IntForEachEntry( vRoots, iObj, i ) + { + assert( Vec_IntEntry( vMirrors, iObj ) < 0 ); + Node = Vec_IntEntry( vObj2Var, iObj ); + Vec_IntPush( vFaninVars, Abc_Var2Lit(nVars, 0) ); + sat_solver_add_xor( pSat, Node, Node + Vec_IntSize(vTfo), nVars++, 0 ); + } + // make OR clause for the last nRoots variables + RetValue = sat_solver_addclause( pSat, Vec_IntArray(vFaninVars), Vec_IntLimit(vFaninVars) ); + Vec_IntFree( vFaninVars ); + if ( RetValue == 0 ) + { + sat_solver_delete( pSat ); + return NULL; + } + assert( sat_solver_nvars(pSat) == nVars + 32 ); + } + // finalize + RetValue = sat_solver_simplify( pSat ); + if ( RetValue == 0 ) + { + sat_solver_delete( pSat ); + return NULL; + } + return pSat; +} + +/**Function************************************************************* + + Synopsis [Solves one SAT problem.] + + Description [Computes node function for PivotVar with fanins in vDivVars + using don't-care represented in the SAT solver. Uses array vValues to + return the values of the first Vec_IntSize(vValues) SAT variables in case + the implementation of the node with the given fanins does not exist.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word Sbd_ManSolve( sat_solver * pSat, int PivotVar, int FreeVar, Vec_Int_t * vDivVars, Vec_Int_t * vValues, Vec_Int_t * vTemp ) +{ + int nBTLimit = 0; + word uCube, uTruth = 0; + int status, i, iVar, nFinal, * pFinal, pLits[2], nIter = 0; + assert( FreeVar < sat_solver_nvars(pSat) ); + pLits[0] = Abc_Var2Lit( PivotVar, 0 ); // F = 1 + pLits[1] = Abc_Var2Lit( FreeVar, 0 ); // iNewLit + while ( 1 ) + { + // find onset minterm + status = sat_solver_solve( pSat, pLits, pLits + 2, nBTLimit, 0, 0, 0 ); + if ( status == l_Undef ) + return SBD_SAT_UNDEC; + if ( status == l_False ) + return uTruth; + assert( status == l_True ); + // remember variable values + for ( i = 0; i < Vec_IntSize(vValues); i++ ) + Vec_IntWriteEntry( vValues, i, 2*sat_solver_var_value(pSat, i) ); + // collect divisor literals + Vec_IntClear( vTemp ); + Vec_IntPush( vTemp, Abc_LitNot(pLits[0]) ); // F = 0 + Vec_IntForEachEntry( vDivVars, iVar, i ) + Vec_IntPush( vTemp, sat_solver_var_literal(pSat, iVar) ); + // check against offset + status = sat_solver_solve( pSat, Vec_IntArray(vTemp), Vec_IntArray(vTemp) + Vec_IntSize(vTemp), nBTLimit, 0, 0, 0 ); + if ( status == l_Undef ) + return SBD_SAT_UNDEC; + if ( status == l_True ) + break; + assert( status == l_False ); + // compute cube and add clause + nFinal = sat_solver_final( pSat, &pFinal ); + uCube = ~(word)0; + Vec_IntClear( vTemp ); + Vec_IntPush( vTemp, Abc_LitNot(pLits[1]) ); // NOT(iNewLit) + for ( i = 0; i < nFinal; i++ ) + { + if ( pFinal[i] == pLits[0] ) + continue; + Vec_IntPush( vTemp, pFinal[i] ); + iVar = Vec_IntFind( vDivVars, Abc_Lit2Var(pFinal[i]) ); assert( iVar >= 0 ); + uCube &= Abc_LitIsCompl(pFinal[i]) ? s_Truths6[iVar] : ~s_Truths6[iVar]; + } + uTruth |= uCube; + status = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntArray(vTemp) + Vec_IntSize(vTemp) ); + assert( status ); + nIter++; + } + assert( status == l_True ); + // store the counter-example + for ( i = 0; i < Vec_IntSize(vValues); i++ ) + Vec_IntAddToEntry( vValues, i, sat_solver_var_value(pSat, i) ); + + for ( i = 0; i < Vec_IntSize(vValues); i++ ) + Vec_IntAddToEntry( vValues, i, 0xC ); +/* + // reduce the counter example + for ( n = 0; n < 2; n++ ) + { + Vec_IntClear( vTemp ); + Vec_IntPush( vTemp, Abc_Var2Lit(PivotVar, n) ); // n = 0 => F = 1 (expanding offset against onset) + for ( i = 0; i < Vec_IntSize(vValues); i++ ) + Vec_IntPush( vTemp, Abc_Var2Lit(i, !((Vec_IntEntry(vValues, i) >> n) & 1)) ); + status = sat_solver_solve( pSat, Vec_IntArray(vTemp), Vec_IntArray(vTemp) + Vec_IntSize(vTemp), nBTLimit, 0, 0, 0 ); + assert( status == l_False ); + // compute cube and add clause + nFinal = sat_solver_final( pSat, &pFinal ); + for ( i = 0; i < nFinal; i++ ) + if ( Abc_Lit2Var(pFinal[i]) != PivotVar ) + Vec_IntAddToEntry( vValues, Abc_Lit2Var(pFinal[i]), 1 << (n+2) ); + } +*/ + return SBD_SAT_SAT; +} + +/**Function************************************************************* + + Synopsis [Returns a bunch of positive/negative random care minterms.] + + Description [Returns 0/1 if the functions is const 0/1.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void sat_solver_random_polarity(sat_solver* s) +{ + int i, k; + for ( i = 0; i < s->size; i += 64 ) + { + word Polar = Gia_ManRandomW(0); + for ( k = 0; k < 64 && (i << 6) + k < s->size; k++ ) + s->polarity[(i << 6) + k] = Abc_TtGetBit(&Polar, k); + } +} +int Sbd_ManCollectConstants( sat_solver * pSat, int nCareMints[2], int PivotVar, word * pVarSims[], Vec_Int_t * vInds ) +{ + int nBTLimit = 0; + int i, Ind; + assert( Vec_IntSize(vInds) == nCareMints[0] + nCareMints[1] ); + Vec_IntForEachEntry( vInds, Ind, i ) + { + int fOffSet = (int)(i < nCareMints[0]); + int status, k, iLit = Abc_Var2Lit( PivotVar, fOffSet ); + sat_solver_random_polarity( pSat ); + status = sat_solver_solve( pSat, &iLit, &iLit + 1, nBTLimit, 0, 0, 0 ); + if ( status == l_Undef ) + return -2; + if ( status == l_False ) + return fOffSet; + for ( k = 0; k <= PivotVar; k++ ) + if ( Abc_TtGetBit(pVarSims[k], Ind) != sat_solver_var_value(pSat, k) ) + Abc_TtXorBit(pVarSims[k], Ind); + } + return -1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + |