From 85abb6bde78927b4b9b9dd1b71ddc4666efe495d Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 7 Nov 2016 09:39:29 -0800 Subject: Isolating CBA types into a separate header. --- src/base/cba/cba.h | 111 +---------------------------------------------------- 1 file changed, 1 insertion(+), 110 deletions(-) (limited to 'src') diff --git a/src/base/cba/cba.h b/src/base/cba/cba.h index 36a93f32..adf12a45 100644 --- a/src/base/cba/cba.h +++ b/src/base/cba/cba.h @@ -29,6 +29,7 @@ #include "misc/extra/extra.h" #include "misc/util/utilNam.h" #include "misc/vec/vecHash.h" +#include "cbaTypes.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// @@ -40,116 +41,6 @@ ABC_NAMESPACE_HEADER_START /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// -// network objects -typedef enum { - CBA_OBJ_NONE = 0, // 00: unused - CBA_OBJ_PI, // 01: input - CBA_OBJ_PO, // 02: output - CBA_OBJ_BOX, // 03: box - - CBA_BOX_CF, // 04: - CBA_BOX_CT, // 05: - CBA_BOX_CX, // 06: - CBA_BOX_CZ, // 07: - - CBA_BOX_BUF, // 08: - CBA_BOX_INV, // 09: - CBA_BOX_AND, // 10: - CBA_BOX_NAND, // 11: - CBA_BOX_OR, // 12: - CBA_BOX_NOR, // 13: - CBA_BOX_XOR, // 14: - CBA_BOX_XNOR, // 15: - CBA_BOX_SHARP, // 16: - CBA_BOX_SHARPL, // 17: - CBA_BOX_MUX, // 18: - CBA_BOX_MAJ, // 19: - - CBA_BOX_ABC, // 20: - CBA_BOX_BA, // 21: - CBA_BOX_BO, // 22: - CBA_BOX_BX, // 23: - CBA_BOX_BN, // 24: - CBA_BOX_BAO, // 25: - CBA_BOX_BOA, // 26: - - CBA_BOX_RAND, // 27: - CBA_BOX_RNAND, // 28: - CBA_BOX_ROR, // 29: - CBA_BOX_RNOR, // 30: - CBA_BOX_RXOR, // 31: - CBA_BOX_RXNOR, // 32: - - CBA_BOX_LNOT, // 33 - CBA_BOX_LAND, // 34: - CBA_BOX_LNAND, // 35: - CBA_BOX_LOR, // 36: - CBA_BOX_LNOR, // 37: - CBA_BOX_LXOR, // 38: - CBA_BOX_LXNOR, // 39: - - CBA_BOX_NMUX, // 40: - CBA_BOX_SEL, // 41: - CBA_BOX_PSEL, // 42: - CBA_BOX_ENC, // 43: - CBA_BOX_PENC, // 44: - CBA_BOX_DEC, // 45: - CBA_BOX_EDEC, // 46: - - CBA_BOX_ADD, // 47: - CBA_BOX_SUB, // 48: - CBA_BOX_MUL, // 49: - CBA_BOX_SMUL, // 50: - CBA_BOX_DIV, // 51: - CBA_BOX_MOD, // 52: - CBA_BOX_REM, // 53: - CBA_BOX_POW, // 54: - CBA_BOX_MIN, // 55: - CBA_BOX_SQRT, // 56: - CBA_BOX_ABS, // 57: - - CBA_BOX_SLTHAN, // 58: - CBA_BOX_LTHAN, // 59: - CBA_BOX_LETHAN, // 60: - CBA_BOX_METHAN, // 61: - CBA_BOX_MTHAN, // 62: - CBA_BOX_EQU, // 63: - CBA_BOX_NEQU, // 64: - - CBA_BOX_SHIL, // 65: - CBA_BOX_SHIR, // 66: - CBA_BOX_SHILA, // 67: - CBA_BOX_SHIRA, // 68: - CBA_BOX_ROTL, // 69: - CBA_BOX_ROTR, // 70: - - CBA_BOX_NODE, // 71: - CBA_BOX_LUT, // 72: - CBA_BOX_GATE, // 73: - CBA_BOX_TABLE, // 74: - - CBA_BOX_TRI, // 75: - CBA_BOX_RAM, // 76: - CBA_BOX_RAMR, // 77: - CBA_BOX_RAMW, // 78: - CBA_BOX_RAMWC, // 79: - CBA_BOX_RAML, // 80: - CBA_BOX_RAMS, // 81: - CBA_BOX_RAMBOX, // 82: - - CBA_BOX_LATCH, // 83: - CBA_BOX_LATCHRS, // 84: - CBA_BOX_DFF, // 85: - CBA_BOX_DFFCPL, // 86: - CBA_BOX_DFFRS, // 87: - - CBA_BOX_SLICE, // 88: - CBA_BOX_CONCAT, // 89: - - CBA_BOX_LAST // 90 -} Cba_ObjType_t; - - typedef struct Cba_Ntk_t_ Cba_Ntk_t; typedef struct Cba_Man_t_ Cba_Man_t; -- cgit v1.2.3 From 6cd66183e4304eb66805b8236642bf1f85cfa14f Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 8 Nov 2016 06:13:47 -0800 Subject: Isolating CBA types into a separate header. --- src/base/cba/cbaTypes.h | 169 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 src/base/cba/cbaTypes.h (limited to 'src') diff --git a/src/base/cba/cbaTypes.h b/src/base/cba/cbaTypes.h new file mode 100644 index 00000000..6fad9985 --- /dev/null +++ b/src/base/cba/cbaTypes.h @@ -0,0 +1,169 @@ +/**CFile**************************************************************** + + FileName [cbaTypes.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Hierarchical word-level netlist.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - July 21, 2015.] + + Revision [$Id: cbaTypes.h,v 1.00 2014/11/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__base__cba__cba__types_h +#define ABC__base__cba__cba__types_h + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// network objects +typedef enum { + CBA_OBJ_NONE = 0, // 00: unused + CBA_OBJ_PI, // 01: input + CBA_OBJ_PO, // 02: output + CBA_OBJ_BOX, // 03: box + + CBA_BOX_CF, // 04: + CBA_BOX_CT, // 05: + CBA_BOX_CX, // 06: + CBA_BOX_CZ, // 07: + + CBA_BOX_BUF, // 08: + CBA_BOX_INV, // 09: + CBA_BOX_AND, // 10: + CBA_BOX_NAND, // 11: + CBA_BOX_OR, // 12: + CBA_BOX_NOR, // 13: + CBA_BOX_XOR, // 14: + CBA_BOX_XNOR, // 15: + CBA_BOX_SHARP, // 16: + CBA_BOX_SHARPL, // 17: + CBA_BOX_MUX, // 18: + CBA_BOX_MAJ, // 19: + + CBA_BOX_ABC, // 20: + CBA_BOX_BA, // 21: + CBA_BOX_BO, // 22: + CBA_BOX_BX, // 23: + CBA_BOX_BN, // 24: + CBA_BOX_BAO, // 25: + CBA_BOX_BOA, // 26: + + CBA_BOX_RAND, // 27: + CBA_BOX_RNAND, // 28: + CBA_BOX_ROR, // 29: + CBA_BOX_RNOR, // 30: + CBA_BOX_RXOR, // 31: + CBA_BOX_RXNOR, // 32: + + CBA_BOX_LNOT, // 33 + CBA_BOX_LAND, // 34: + CBA_BOX_LNAND, // 35: + CBA_BOX_LOR, // 36: + CBA_BOX_LNOR, // 37: + CBA_BOX_LXOR, // 38: + CBA_BOX_LXNOR, // 39: + + CBA_BOX_NMUX, // 40: + CBA_BOX_SEL, // 41: + CBA_BOX_PSEL, // 42: + CBA_BOX_ENC, // 43: + CBA_BOX_PENC, // 44: + CBA_BOX_DEC, // 45: + CBA_BOX_EDEC, // 46: + + CBA_BOX_ADD, // 47: + CBA_BOX_SUB, // 48: + CBA_BOX_MUL, // 49: + CBA_BOX_SMUL, // 50: + CBA_BOX_DIV, // 51: + CBA_BOX_MOD, // 52: + CBA_BOX_REM, // 53: + CBA_BOX_POW, // 54: + CBA_BOX_MIN, // 55: + CBA_BOX_SQRT, // 56: + CBA_BOX_ABS, // 57: + + CBA_BOX_SLTHAN, // 58: + CBA_BOX_LTHAN, // 59: + CBA_BOX_LETHAN, // 60: + CBA_BOX_METHAN, // 61: + CBA_BOX_MTHAN, // 62: + CBA_BOX_EQU, // 63: + CBA_BOX_NEQU, // 64: + + CBA_BOX_SHIL, // 65: + CBA_BOX_SHIR, // 66: + CBA_BOX_SHILA, // 67: + CBA_BOX_SHIRA, // 68: + CBA_BOX_ROTL, // 69: + CBA_BOX_ROTR, // 70: + + CBA_BOX_NODE, // 71: + CBA_BOX_LUT, // 72: + CBA_BOX_GATE, // 73: + CBA_BOX_TABLE, // 74: + + CBA_BOX_TRI, // 75: + CBA_BOX_RAM, // 76: + CBA_BOX_RAMR, // 77: + CBA_BOX_RAMW, // 78: + CBA_BOX_RAMWC, // 79: + CBA_BOX_RAML, // 80: + CBA_BOX_RAMS, // 81: + CBA_BOX_RAMBOX, // 82: + + CBA_BOX_LATCH, // 83: + CBA_BOX_LATCHRS, // 84: + CBA_BOX_DFF, // 85: + CBA_BOX_DFFCPL, // 86: + CBA_BOX_DFFRS, // 87: + + CBA_BOX_SLICE, // 88: + CBA_BOX_CONCAT, // 89: + + CBA_BOX_LAST // 90 +} Cba_ObjType_t; + + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_HEADER_END + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + -- cgit v1.2.3 From faf8d6ecea8e7b7030a13531b834522f9821ff30 Mon Sep 17 00:00:00 2001 From: Vinicius Callegaro Date: Tue, 8 Nov 2016 17:00:35 -0200 Subject: 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, entitled "Bottom-up disjoint-support decomposition based on cofactor and boolean difference analysis" presented in ICCD'15. --- src/base/abci/abc.c | 3 + src/base/abci/abcDec.c | 22 +- src/opt/dsc/dsc.c | 526 ++++++++++++++++++++++++++++++++++++++++++++++++ src/opt/dsc/dsc.h | 91 +++++++++ src/opt/dsc/module.make | 1 + 5 files changed, 642 insertions(+), 1 deletion(-) create mode 100644 src/opt/dsc/dsc.c create mode 100644 src/opt/dsc/dsc.h create mode 100644 src/opt/dsc/module.make (limited to 'src') diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 953a6c6a..ffcd5054 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -6212,6 +6212,9 @@ usage: Abc_Print( -2, "\t 3: disjoint-support decomposition with cofactoring\n" ); Abc_Print( -2, "\t 4: updated disjoint-support decomposition with cofactoring\n" ); Abc_Print( -2, "\t 5: enumerating decomposable variable sets\n" ); + Abc_Print( -2, "\t 6: disjoint-support decomposition with cofactoring and boolean difference analysis\n" ); + Abc_Print( -2, "\t from V. Callegaro, F. S. Marranghello, M. G. A. Martins, R. P. Ribas and A. I. Reis,\n"); + Abc_Print( -2, "\t \"Bottom-up disjoint-support decomposition based on cofactor and boolean difference analysis,\" ICCD'15.\n" ); Abc_Print( -2, "\t-N : the number of support variables (binary files only) [default = unused]\n" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); diff --git a/src/base/abci/abcDec.c b/src/base/abci/abcDec.c index 919a46de..8bb04f16 100644 --- a/src/base/abci/abcDec.c +++ b/src/base/abci/abcDec.c @@ -26,6 +26,7 @@ #include "bool/kit/kit.h" #include "opt/dau/dau.h" #include "misc/util/utilTruth.h" +#include "opt/dsc/dsc.h" ABC_NAMESPACE_IMPL_START @@ -484,6 +485,8 @@ void Abc_TruthDecPerform( Abc_TtStore_t * p, int DecType, int fVerbose ) pAlgoName = "fast DSD"; else if ( DecType == 5 ) pAlgoName = "analysis"; + else if ( DecType == 6 ) + pAlgoName = "DSD ICCD'15"; if ( pAlgoName ) printf( "Applying %-10s to %8d func%s of %2d vars... ", @@ -577,6 +580,23 @@ void Abc_TruthDecPerform( Abc_TtStore_t * p, int DecType, int fVerbose ) if ( fVerbose ) printf( "\n" ); } + } else if ( DecType == 6 ) + { + char pDsd[DSC_MAX_STR]; + /* memory pool with a capacity of storing 3*nVars + truth-tables for negative and positive cofactors and + the boolean difference for each input variable */ + word *mem_pool = Dsc_alloc_pool(p->nVars); + for ( i = 0; i < p->nFuncs; i++ ) + { + if ( fVerbose ) + printf( "%7d : ", i ); + Dsc_Decompose(p->pFuncs[i], p->nVars, pDsd, mem_pool); + if ( fVerbose ) + printf( "%s\n", pDsd[0] ? pDsd : "NULL"); + nNodes += Dsc_CountAnds( pDsd ); + } + Dsc_free_pool(mem_pool); } else assert( 0 ); @@ -629,7 +649,7 @@ int Abc_DecTest( char * pFileName, int DecType, int nVarNum, int fVerbose ) printf( "Using truth tables from file \"%s\"...\n", pFileName ); if ( DecType == 0 ) { if ( nVarNum < 0 ) Abc_TtStoreTest( pFileName ); } - else if ( DecType >= 1 && DecType <= 5 ) + else if ( DecType >= 1 && DecType <= 6 ) Abc_TruthDecTest( pFileName, DecType, nVarNum, fVerbose ); else printf( "Unknown decomposition type value (%d).\n", DecType ); diff --git a/src/opt/dsc/dsc.c b/src/opt/dsc/dsc.c new file mode 100644 index 00000000..409b040f --- /dev/null +++ b/src/opt/dsc/dsc.c @@ -0,0 +1,526 @@ +/**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 +#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) { + 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"); + int i; + for (i=1;i<=pNode->off[0];i++) { + printf("%c%c", (pNode->off[i] & 1U) ? ' ' : '!', 'a'+(pNode->off[i] >> 1)); + } + printf("\ton:\t"); + for (i=1;i<=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) { + // expression + concat(pOut->exp, '(', ')', ni->exp, niPolarity, nj->exp, njPolarity); + // ON-OFF + unsigned int* xiOFF, * xiON, * xjOFF, * xjON; + 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) { + pOut->off[0] = xiOFFSize; // set the number of elements + int i; + for (i = 1; i <= xiOFFSize; i++) { + pOut->off[i] = xiOFF[i]; + } + } else { + pOut->off[0] = xjOFFSize; // set the number of elements + int i; + 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 + { + unsigned int xiONSize = xiON[0]; + unsigned int xjONSize = xjON[0]; + pOut->on[0] = xiONSize + xjONSize; + int i; + for (i = 1; i <= xiONSize; i++) { + pOut->on[i] = xiON[i]; + } + int j; + for (j = 1; j <= 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) { + // expression + concat(pOut->exp, '[', ']', ni->exp, 1, nj->exp, 1); + // + const unsigned int const * xiOFF = ni->off; + const unsigned int const * xiON = ni->on; + const unsigned int const * xjOFF = nj->off; + const unsigned int const * 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; + 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); + + pRes[0] = '\0'; + pRes[1] = '\0'; + + Dsc_node_t nodes[DSC_MAX_VAR]; + Dsc_node_t *newNodes[DSC_MAX_VAR]; + Dsc_node_t *oldNodes[DSC_MAX_VAR]; + + int n = 0; // n will represent the number of current nodes (i.e. support) + + 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; + } + } + 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 + 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 +#include +#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 -- cgit v1.2.3 From c6afb9db639b7ce0ac714e4e63e629b4c8bf1ac1 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 9 Nov 2016 21:17:44 -0800 Subject: Equivalent fault detection code. --- src/base/abci/abc.c | 25 +- src/base/abci/abcDetect.c | 1066 ++++++++++++++++++++++++++++++++++++++++++++- src/map/mio/mio.h | 1 + src/map/mio/mioApi.c | 1 + src/map/mio/mioRead.c | 3 + 5 files changed, 1087 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 953a6c6a..b1c81cd5 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -7237,21 +7237,28 @@ usage: ***********************************************************************/ int Abc_CommandDetect( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fSeq, int fVerbose ); + extern void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fSeq, int fVerbose, int fVeryVerbose ); + extern void Abc_NtkGenFaultList( Abc_Ntk_t * pNtk, char * pFileName ); Abc_Ntk_t * pNtk; - int c, fSeq = 0, fVerbose = 0; + int c, fGen = 0, fSeq = 0, fVerbose = 0, fVeryVerbose = 0; pNtk = Abc_FrameReadNtk(pAbc); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "gsvwh" ) ) != EOF ) { switch ( c ) { + case 'g': + fGen ^= 1; + break; case 's': fSeq ^= 1; break; case 'v': fVerbose ^= 1; break; + case 'w': + fVeryVerbose ^= 1; + break; case 'h': goto usage; default: @@ -7268,14 +7275,22 @@ int Abc_CommandDetect( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Only applicable to a logic network.\n" ); return 1; } - Abc_NtkDetectClassesTest( pNtk, fSeq, fVerbose ); + if ( fGen ) + { + char * pFileName = Extra_FileNameGenericAppend(Abc_NtkSpec(pNtk), "_faults.txt"); + Abc_NtkGenFaultList( pNtk, pFileName ); + } + else + Abc_NtkDetectClassesTest( pNtk, fSeq, fVerbose, fVeryVerbose ); return 0; usage: - Abc_Print( -2, "usage: detect [-svh]\n" ); + Abc_Print( -2, "usage: detect [-gsvwh]\n" ); Abc_Print( -2, "\t detects properties of internal nodes\n" ); + Abc_Print( -2, "\t-g : toggle generating fault list for the given network [default = %s]\n", fGen? "yes": "no" ); Abc_Print( -2, "\t-s : toggle using sequential circuit information [default = %s]\n", fSeq? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printing equivalence classes [default = %s]\n", fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } diff --git a/src/base/abci/abcDetect.c b/src/base/abci/abcDetect.c index c87169b5..b1a598cd 100644 --- a/src/base/abci/abcDetect.c +++ b/src/base/abci/abcDetect.c @@ -23,6 +23,8 @@ #include "misc/util/utilNam.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.h" +#include "map/mio/mio.h" +#include "map/mio/exp.h" ABC_NAMESPACE_IMPL_START @@ -31,7 +33,7 @@ ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// typedef enum { - ABC_FIN_NONE = 0, // 0: unknown + ABC_FIN_NONE = -100, // 0: unknown ABC_FIN_SA0, // 1: ABC_FIN_SA1, // 2: ABC_FIN_NEG, // 3: @@ -50,6 +52,49 @@ typedef enum { /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// +/**Function************************************************************* + + Synopsis [Generates fault list for the given mapped network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkGenFaultList( Abc_Ntk_t * pNtk, char * pFileName ) +{ + Mio_Library_t * pLib = (Mio_Library_t *)pNtk->pManFunc; + Mio_Gate_t * pGate; + Abc_Obj_t * pObj; + int i, Count = 1; + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + return; + } + assert( Abc_NtkIsMappedLogic(pNtk) ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + Mio_Gate_t * pGateObj = (Mio_Gate_t *)pObj->pData; + int nInputs = Mio_GateReadPinNum(pGateObj); + // add basic faults (SA0, SA1, NEG) + fprintf( pFile, "%d %s %s\n", Count, Abc_ObjName(pObj), "SA0" ), Count++; + fprintf( pFile, "%d %s %s\n", Count, Abc_ObjName(pObj), "SA1" ), Count++; + fprintf( pFile, "%d %s %s\n", Count, Abc_ObjName(pObj), "NEG" ), Count++; + // add other faults, which correspond to changing the given gate + // by another gate with the same support-size from the same library + Mio_LibraryForEachGate( pLib, pGate ) + if ( pGate != pGateObj && Mio_GateReadPinNum(pGate) == nInputs ) + fprintf( pFile, "%d %s %s\n", Count, Abc_ObjName(pObj), Mio_GateReadName(pGate) ), Count++; + } + printf( "Generated fault list \"%s\" for network \"%s\" with %d nodes and %d faults.\n", + pFileName, Abc_NtkName(pNtk), Abc_NtkNodeNum(pNtk), Count-1 ); + fclose( pFile ); +} + /**Function************************************************************* Synopsis [Recognize type.] @@ -61,6 +106,16 @@ typedef enum { SeeAlso [] ***********************************************************************/ +int Io_ReadFinTypeMapped( Mio_Library_t * pLib, char * pThis ) +{ + Mio_Gate_t * pGate = Mio_LibraryReadGateByName( pLib, pThis, NULL ); + if ( pGate == NULL ) + { + printf( "Cannot find gate \"%s\" in the current library.\n", pThis ); + return ABC_FIN_NONE; + } + return Mio_GateReadCell( pGate ); +} int Io_ReadFinType( char * pThis ) { if ( !strcmp(pThis, "SA0") ) return ABC_FIN_SA0; @@ -106,6 +161,7 @@ char * Io_WriteFinType( int Type ) ***********************************************************************/ Vec_Int_t * Io_ReadFins( Abc_Ntk_t * pNtk, char * pFileName, int fVerbose ) { + Mio_Library_t * pLib = (Mio_Library_t *)pNtk->pManFunc; char Buffer[1000]; Abc_Obj_t * pObj; Abc_Nam_t * pNam; @@ -142,6 +198,8 @@ Vec_Int_t * Io_ReadFins( Abc_Ntk_t * pNtk, char * pFileName, int fVerbose ) { // read line number char * pToken = strtok( Buffer, " \n\r\t" ); + if ( pToken == NULL ) + break; if ( nLines++ != atoi(pToken) ) { printf( "Line numbers are not consecutive. Quitting.\n" ); @@ -158,7 +216,15 @@ Vec_Int_t * Io_ReadFins( Abc_Ntk_t * pNtk, char * pFileName, int fVerbose ) } // read type pToken = strtok( NULL, " \n\r\t" ); - Type = Io_ReadFinType( pToken ); + if ( Abc_NtkIsMappedLogic(pNtk) ) + { + if ( !strcmp(pToken, "SA0") || !strcmp(pToken, "SA1") || !strcmp(pToken, "NEG") ) + Type = Io_ReadFinType( pToken ); + else + Type = Io_ReadFinTypeMapped( pLib, pToken ); + } + else + Type = Io_ReadFinType( pToken ); if ( Type == ABC_FIN_NONE ) { printf( "Cannot read type \"%s\" of object \"%s\".\n", pToken, Abc_ObjName(Abc_NtkObj(pNtk, iObj)) ); @@ -182,6 +248,987 @@ finish: } +/**Function************************************************************* + + Synopsis [Extend the network by adding second timeframe.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFrameExtend( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vFanins, * vNodes; + Abc_Obj_t * pObj, * pFanin, * pReset, * pEnable, * pSignal; + Abc_Obj_t * pResetN, * pEnableN, * pAnd0, * pAnd1, * pMux; + int i, k, iStartPo, nPisOld = Abc_NtkPiNum(pNtk), nPosOld = Abc_NtkPoNum(pNtk); + // skip if there are no flops + if ( pNtk->nConstrs == 0 ) + return; + assert( Abc_NtkPiNum(pNtk) >= pNtk->nConstrs ); + assert( Abc_NtkPoNum(pNtk) >= pNtk->nConstrs * 4 ); + // collect nodes + vNodes = Vec_PtrAlloc( Abc_NtkNodeNum(pNtk) ); + Abc_NtkForEachNode( pNtk, pObj, i ) + Vec_PtrPush( vNodes, pObj ); + // duplicate PIs + vFanins = Vec_PtrAlloc( 2 ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + if ( i == nPisOld ) + break; + if ( i < nPisOld - pNtk->nConstrs ) + { + Abc_NtkDupObj( pNtk, pObj, 0 ); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), "_frame1" ); + continue; + } + // create flop input + iStartPo = nPosOld + 4 * (i - nPisOld); + pReset = Abc_ObjFanin0( Abc_NtkPo( pNtk, iStartPo + 1 ) ); + pEnable = Abc_ObjFanin0( Abc_NtkPo( pNtk, iStartPo + 2 ) ); + pSignal = Abc_ObjFanin0( Abc_NtkPo( pNtk, iStartPo + 3 ) ); + pResetN = Abc_NtkCreateNodeInv( pNtk, pReset ); + pEnableN = Abc_NtkCreateNodeInv( pNtk, pEnable ); + Vec_PtrFillTwo( vFanins, 2, pEnableN, pObj ); + pAnd0 = Abc_NtkCreateNodeAnd( pNtk, vFanins ); + Vec_PtrFillTwo( vFanins, 2, pEnable, pSignal ); + pAnd1 = Abc_NtkCreateNodeAnd( pNtk, vFanins ); + Vec_PtrFillTwo( vFanins, 2, pAnd0, pAnd1 ); + pMux = Abc_NtkCreateNodeOr( pNtk, vFanins ); + Vec_PtrFillTwo( vFanins, 2, pResetN, pMux ); + pObj->pCopy = Abc_NtkCreateNodeAnd( pNtk, vFanins ); + } + // duplicate internal nodes + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + Abc_NtkDupObj( pNtk, pObj, 0 ); + // connect objects + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + // create new POs and reconnect flop inputs + Abc_NtkForEachPo( pNtk, pObj, i ) + { + if ( i == nPosOld ) + break; + if ( i < nPosOld - 4 * pNtk->nConstrs ) + { + Abc_NtkDupObj( pNtk, pObj, 0 ); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), "_frame1" ); + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pObj)->pCopy ); + continue; + } + Abc_ObjPatchFanin( pObj, Abc_ObjFanin0(pObj), Abc_ObjFanin0(pObj)->pCopy ); + } + Vec_PtrFree( vFanins ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Detect equivalence classes of nodes in terms of their TFO.] + + Description [Given is the logic network (pNtk) and the set of objects + (primary inputs or internal nodes) to be considered (vObjs), this function + returns a set of equivalence classes of these objects in terms of their + transitive fanout (TFO). Two objects belong to the same class if the set + of COs they feed into are the same.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDetectObjClasses_rec( Abc_Obj_t * pObj, Vec_Int_t * vMap, Hsh_VecMan_t * pHash, Vec_Int_t * vTemp ) +{ + Vec_Int_t * vArray, * vSet; + Abc_Obj_t * pNext; int i; + // get the CO set for this object + int Entry = Vec_IntEntry(vMap, Abc_ObjId(pObj)); + if ( Entry != -1 ) // the set is already computed + return Entry; + // compute a new CO set + assert( Abc_ObjIsCi(pObj) || Abc_ObjIsNode(pObj) ); + // if there is no fanouts, the set of COs is empty + if ( Abc_ObjFanoutNum(pObj) == 0 ) + { + Vec_IntWriteEntry( vMap, Abc_ObjId(pObj), 0 ); + return 0; + } + // compute the set for the first fanout + Entry = Abc_NtkDetectObjClasses_rec( Abc_ObjFanout0(pObj), vMap, pHash, vTemp ); + if ( Abc_ObjFanoutNum(pObj) == 1 ) + { + Vec_IntWriteEntry( vMap, Abc_ObjId(pObj), Entry ); + return Entry; + } + vSet = Vec_IntAlloc( 16 ); + // initialize the set with that of first fanout + vArray = Hsh_VecReadEntry( pHash, Entry ); + Vec_IntClear( vSet ); + Vec_IntAppend( vSet, vArray ); + // iteratively add sets of other fanouts + Abc_ObjForEachFanout( pObj, pNext, i ) + { + if ( i == 0 ) + continue; + Entry = Abc_NtkDetectObjClasses_rec( pNext, vMap, pHash, vTemp ); + vArray = Hsh_VecReadEntry( pHash, Entry ); + Vec_IntTwoMerge2( vSet, vArray, vTemp ); + ABC_SWAP( Vec_Int_t, *vSet, *vTemp ); + } + // create or find new set and map the object into it + Entry = Hsh_VecManAdd( pHash, vSet ); + Vec_IntWriteEntry( vMap, Abc_ObjId(pObj), Entry ); + Vec_IntFree( vSet ); + return Entry; +} +Vec_Wec_t * Abc_NtkDetectObjClasses( Abc_Ntk_t * pNtk, Vec_Int_t * vObjs, Vec_Wec_t ** pvCos ) +{ + Vec_Wec_t * vClasses; // classes of equivalence objects from vObjs + Vec_Int_t * vClassMap; // mapping of each CO set into its class in vClasses + Vec_Int_t * vClass; // one equivalence class + Abc_Obj_t * pObj; + int i, iObj, SetId, ClassId; + // create hash table to hash sets of CO indexes + Hsh_VecMan_t * pHash = Hsh_VecManStart( 1000 ); + // create elementary sets (each composed of one CO) and map COs into them + Vec_Int_t * vMap = Vec_IntStartFull( Abc_NtkObjNumMax(pNtk) ); + Vec_Int_t * vSet = Vec_IntAlloc( 16 ); + assert( Abc_NtkIsLogic(pNtk) ); + // compute empty set + SetId = Hsh_VecManAdd( pHash, vSet ); + assert( SetId == 0 ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + Vec_IntFill( vSet, 1, Abc_ObjId(pObj) ); + SetId = Hsh_VecManAdd( pHash, vSet ); + Vec_IntWriteEntry( vMap, Abc_ObjId(pObj), SetId ); + } + // make sure the array of objects is sorted + Vec_IntSort( vObjs, 0 ); + // begin from the objects and map their IDs into sets of COs + Abc_NtkForEachObjVec( vObjs, pNtk, pObj, i ) + Abc_NtkDetectObjClasses_rec( pObj, vMap, pHash, vSet ); + Vec_IntFree( vSet ); + // create map for mapping CO set its their classes + vClassMap = Vec_IntStartFull( Hsh_VecSize(pHash) + 1 ); + // collect classes of objects + vClasses = Vec_WecAlloc( 1000 ); + Vec_IntForEachEntry( vObjs, iObj, i ) + { + //char * pName = Abc_ObjName( Abc_NtkObj(pNtk, iObj) ); + // for a given object (iObj), find the ID of its COs set + SetId = Vec_IntEntry( vMap, iObj ); + assert( SetId >= 0 ); + // for the given CO set, finds its equivalence class + ClassId = Vec_IntEntry( vClassMap, SetId ); + if ( ClassId == -1 ) // there is no equivalence class + { + // map this CO set into a new equivalence class + Vec_IntWriteEntry( vClassMap, SetId, Vec_WecSize(vClasses) ); + vClass = Vec_WecPushLevel( vClasses ); + } + else // get hold of the equivalence class + vClass = Vec_WecEntry( vClasses, ClassId ); + // add objects to the class + Vec_IntPush( vClass, iObj ); + // print the set for this object + //printf( "Object %5d : ", iObj ); + //Vec_IntPrint( Hsh_VecReadEntry(pHash, SetId) ); + } + // collect arrays of COs for each class + *pvCos = Vec_WecStart( Vec_WecSize(vClasses) ); + Vec_WecForEachLevel( vClasses, vClass, i ) + { + iObj = Vec_IntEntry( vClass, 0 ); + // for a given object (iObj), find the ID of its COs set + SetId = Vec_IntEntry( vMap, iObj ); + assert( SetId >= 0 ); + // for the given CO set ID, find the set + vSet = Hsh_VecReadEntry( pHash, SetId ); + Vec_IntAppend( Vec_WecEntry(*pvCos, i), vSet ); + } + Hsh_VecManStop( pHash ); + Vec_IntFree( vClassMap ); + Vec_IntFree( vMap ); + return vClasses; +} +void Abc_NtkDetectClassesTest2( Abc_Ntk_t * pNtk, int fVerbose, int fVeryVerbose ) +{ + Vec_Int_t * vObjs; + Vec_Wec_t * vRes, * vCos; + // for testing, create the set of object IDs for all combinational inputs (CIs) + Abc_Obj_t * pObj; int i; + vObjs = Vec_IntAlloc( Abc_NtkCiNum(pNtk) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Vec_IntPush( vObjs, Abc_ObjId(pObj) ); + // compute equivalence classes of CIs and print them + vRes = Abc_NtkDetectObjClasses( pNtk, vObjs, &vCos ); + Vec_WecPrint( vRes, 0 ); + Vec_WecPrint( vCos, 0 ); + // clean up + Vec_IntFree( vObjs ); + Vec_WecFree( vRes ); + Vec_WecFree( vCos ); +} + +/**Function************************************************************* + + Synopsis [Collecting objects.] + + Description [Collects combinational inputs (vCIs) and internal nodes (vNodes) + reachable from the given set of combinational outputs (vCOs).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFinMiterCollect_rec( Abc_Obj_t * pObj, Vec_Int_t * vCis, Vec_Int_t * vNodes ) +{ + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return; + Abc_NodeSetTravIdCurrent(pObj); + if ( Abc_ObjIsCi(pObj) ) + Vec_IntPush( vCis, Abc_ObjId(pObj) ); + else + { + Abc_Obj_t * pFanin; int i; + assert( Abc_ObjIsNode( pObj ) ); + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_NtkFinMiterCollect_rec( pFanin, vCis, vNodes ); + Vec_IntPush( vNodes, Abc_ObjId(pObj) ); + } +} +void Abc_NtkFinMiterCollect( Abc_Ntk_t * pNtk, Vec_Int_t * vCos, Vec_Int_t * vCis, Vec_Int_t * vNodes ) +{ + Abc_Obj_t * pObj; int i; + Vec_IntClear( vCis ); + Vec_IntClear( vNodes ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachObjVec( vCos, pNtk, pObj, i ) + Abc_NtkFinMiterCollect_rec( Abc_ObjFanin0(pObj), vCis, vNodes ); +} + +/**Function************************************************************* + + Synopsis [Simulates expression using given simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mio_LibGateSimulate( Mio_Gate_t * pGate, word * ppFaninSims[6], int nWords, word * pObjSim ) +{ + int i, w, nVars = Mio_GateReadPinNum(pGate); + Vec_Int_t * vExpr = Mio_GateReadExpr( pGate ); + assert( nVars <= 6 ); + for ( w = 0; w < nWords; w++ ) + { + word uFanins[6]; + for ( i = 0; i < nVars; i++ ) + uFanins[i] = ppFaninSims[i][w]; + pObjSim[w] = Exp_Truth6( nVars, vExpr, uFanins ); + } +} + +/**Function************************************************************* + + Synopsis [Simulates expression for one simulation pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mio_LibGateSimulateOne( Mio_Gate_t * pGate, int iBits[6] ) +{ + int nVars = Mio_GateReadPinNum(pGate); + int i, iMint = 0; + for ( i = 0; i < nVars; i++ ) + if ( iBits[i] ) + iMint |= (1 << i); + return Abc_InfoHasBit( (unsigned *)Mio_GateReadTruthP(pGate), iMint ); +} + +/**Function************************************************************* + + Synopsis [Simulated expression with one bit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mio_LibGateSimulateGia( Gia_Man_t * pGia, Mio_Gate_t * pGate, int iLits[6], Vec_Int_t * vLits ) +{ + int i, nVars = Mio_GateReadPinNum(pGate); + Vec_Int_t * vExpr = Mio_GateReadExpr( pGate ); + if ( Exp_IsConst0(vExpr) ) + return 0; + if ( Exp_IsConst1(vExpr) ) + return 1; + if ( Exp_IsLit(vExpr) ) + { + int Index0 = Vec_IntEntry(vExpr,0) >> 1; + int fCompl0 = Vec_IntEntry(vExpr,0) & 1; + assert( Index0 < nVars ); + return Abc_LitNotCond( iLits[Index0], fCompl0 ); + } + Vec_IntClear( vLits ); + for ( i = 0; i < nVars; i++ ) + Vec_IntPush( vLits, iLits[i] ); + for ( i = 0; i < Exp_NodeNum(vExpr); i++ ) + { + int Index0 = Vec_IntEntry( vExpr, 2*i+0 ) >> 1; + int Index1 = Vec_IntEntry( vExpr, 2*i+1 ) >> 1; + int fCompl0 = Vec_IntEntry( vExpr, 2*i+0 ) & 1; + int fCompl1 = Vec_IntEntry( vExpr, 2*i+1 ) & 1; + Vec_IntPush( vLits, Gia_ManHashAnd( pGia, Abc_LitNotCond(Vec_IntEntry(vLits, Index0), fCompl0), Abc_LitNotCond(Vec_IntEntry(vLits, Index1), fCompl1) ) ); + } + return Abc_LitNotCond( Vec_IntEntryLast(vLits), Vec_IntEntryLast(vExpr) & 1 ); +} + +/**Function************************************************************* + + Synopsis [AIG construction and simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_NtkFinSimOneLit( Gia_Man_t * pNew, Abc_Obj_t * pObj, int Type, Vec_Int_t * vMap, int n, Vec_Int_t * vTemp ) +{ + if ( Abc_NtkIsMappedLogic(pObj->pNtk) && Type >= 0 ) + { + extern int Mio_LibGateSimulateGia( Gia_Man_t * pGia, Mio_Gate_t * pGate, int iLits[6], Vec_Int_t * vLits ); + Mio_Library_t * pLib = (Mio_Library_t *)pObj->pNtk->pManFunc; + int i, Lits[6]; + for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ ) + Lits[i] = Vec_IntEntry( vMap, Abc_Var2Lit(Abc_ObjFaninId(pObj, i), n) ); + return Mio_LibGateSimulateGia( pNew, Mio_LibraryReadGateById(pLib, Type), Lits, vTemp ); + } + else + { + int iLit0 = Abc_ObjFaninNum(pObj) > 0 ? Vec_IntEntry( vMap, Abc_Var2Lit(Abc_ObjFaninId0(pObj), n) ) : -1; + int iLit1 = Abc_ObjFaninNum(pObj) > 1 ? Vec_IntEntry( vMap, Abc_Var2Lit(Abc_ObjFaninId1(pObj), n) ) : -1; + assert( Type != ABC_FIN_NEG ); + if ( Type == ABC_FIN_SA0 ) return 0; + if ( Type == ABC_FIN_SA1 ) return 1; + if ( Type == ABC_FIN_RDOB_BUFF ) return iLit0; + if ( Type == ABC_FIN_RDOB_NOT ) return Abc_LitNot( iLit0 ); + if ( Type == ABC_FIN_RDOB_AND ) return Gia_ManHashAnd( pNew, iLit0, iLit1 ); + if ( Type == ABC_FIN_RDOB_OR ) return Gia_ManHashOr( pNew, iLit0, iLit1 ); + if ( Type == ABC_FIN_RDOB_XOR ) return Gia_ManHashXor( pNew, iLit0, iLit1 ); + if ( Type == ABC_FIN_RDOB_NAND ) return Abc_LitNot(Gia_ManHashAnd( pNew, iLit0, iLit1 )); + if ( Type == ABC_FIN_RDOB_NOR ) return Abc_LitNot(Gia_ManHashOr( pNew, iLit0, iLit1 )); + if ( Type == ABC_FIN_RDOB_NXOR ) return Abc_LitNot(Gia_ManHashXor( pNew, iLit0, iLit1 )); + assert( 0 ); + return -1; + } +} +static inline int Abc_NtkFinSimOneBit( Abc_Obj_t * pObj, int Type, Vec_Wrd_t * vSims, int nWords, int iBit ) +{ + if ( Abc_NtkIsMappedLogic(pObj->pNtk) && Type >= 0 ) + { + extern int Mio_LibGateSimulateOne( Mio_Gate_t * pGate, int iBits[6] ); + Mio_Library_t * pLib = (Mio_Library_t *)pObj->pNtk->pManFunc; + int i, iBits[6]; + for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ ) + { + word * pSim0 = Vec_WrdEntryP( vSims, nWords * Abc_ObjFaninId(pObj, i) ); + iBits[i] = Abc_InfoHasBit( (unsigned*)pSim0, iBit ); + } + return Mio_LibGateSimulateOne( Mio_LibraryReadGateById(pLib, Type), iBits ); + } + else + { + word * pSim0 = Abc_ObjFaninNum(pObj) > 0 ? Vec_WrdEntryP( vSims, nWords * Abc_ObjFaninId0(pObj) ) : NULL; + word * pSim1 = Abc_ObjFaninNum(pObj) > 1 ? Vec_WrdEntryP( vSims, nWords * Abc_ObjFaninId1(pObj) ) : NULL; + int iBit0 = Abc_ObjFaninNum(pObj) > 0 ? Abc_InfoHasBit( (unsigned*)pSim0, iBit ) : -1; + int iBit1 = Abc_ObjFaninNum(pObj) > 1 ? Abc_InfoHasBit( (unsigned*)pSim1, iBit ) : -1; + assert( Type != ABC_FIN_NEG ); + if ( Type == ABC_FIN_SA0 ) return 0; + if ( Type == ABC_FIN_SA1 ) return 1; + if ( Type == ABC_FIN_RDOB_BUFF ) return iBit0; + if ( Type == ABC_FIN_RDOB_NOT ) return !iBit0; + if ( Type == ABC_FIN_RDOB_AND ) return iBit0 & iBit1; + if ( Type == ABC_FIN_RDOB_OR ) return iBit0 | iBit1; + if ( Type == ABC_FIN_RDOB_XOR ) return iBit0 ^ iBit1; + if ( Type == ABC_FIN_RDOB_NAND ) return !(iBit0 & iBit1); + if ( Type == ABC_FIN_RDOB_NOR ) return !(iBit0 | iBit1); + if ( Type == ABC_FIN_RDOB_NXOR ) return !(iBit0 ^ iBit1); + assert( 0 ); + return -1; + } +} +static inline void Abc_NtkFinSimOneWord( Abc_Obj_t * pObj, int Type, Vec_Wrd_t * vSims, int nWords ) +{ + if ( Abc_NtkIsMappedLogic(pObj->pNtk) ) + { + extern void Mio_LibGateSimulate( Mio_Gate_t * pGate, word * ppFaninSims[6], int nWords, word * pObjSim ); + word * ppSims[6]; int i; + word * pSim = Vec_WrdEntryP( vSims, nWords * Abc_ObjId(pObj) ); + assert( Type == -1 ); + for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ ) + ppSims[i] = Vec_WrdEntryP( vSims, nWords * Abc_ObjFaninId(pObj, i) ); + Mio_LibGateSimulate( (Mio_Gate_t *)pObj->pData, ppSims, nWords, pSim ); + } + else + { + word * pSim = Vec_WrdEntryP( vSims, nWords * Abc_ObjId(pObj) ); int w; + word * pSim0 = Abc_ObjFaninNum(pObj) > 0 ? Vec_WrdEntryP( vSims, nWords * Abc_ObjFaninId0(pObj) ) : NULL; + word * pSim1 = Abc_ObjFaninNum(pObj) > 1 ? Vec_WrdEntryP( vSims, nWords * Abc_ObjFaninId1(pObj) ) : NULL; + assert( Type != ABC_FIN_NEG ); + if ( Type == ABC_FIN_SA0 ) for ( w = 0; w < nWords; w++ ) pSim[w] = 0; + else if ( Type == ABC_FIN_SA1 ) for ( w = 0; w < nWords; w++ ) pSim[w] = ~((word)0); + else if ( Type == ABC_FIN_RDOB_BUFF ) for ( w = 0; w < nWords; w++ ) pSim[w] = pSim0[w]; + else if ( Type == ABC_FIN_RDOB_NOT ) for ( w = 0; w < nWords; w++ ) pSim[w] = ~pSim0[w]; + else if ( Type == ABC_FIN_RDOB_AND ) for ( w = 0; w < nWords; w++ ) pSim[w] = pSim0[w] & pSim1[w]; + else if ( Type == ABC_FIN_RDOB_OR ) for ( w = 0; w < nWords; w++ ) pSim[w] = pSim0[w] | pSim1[w]; + else if ( Type == ABC_FIN_RDOB_XOR ) for ( w = 0; w < nWords; w++ ) pSim[w] = pSim0[w] ^ pSim1[w]; + else if ( Type == ABC_FIN_RDOB_NAND ) for ( w = 0; w < nWords; w++ ) pSim[w] = ~(pSim0[w] & pSim1[w]); + else if ( Type == ABC_FIN_RDOB_NOR ) for ( w = 0; w < nWords; w++ ) pSim[w] = ~(pSim0[w] | pSim1[w]); + else if ( Type == ABC_FIN_RDOB_NXOR ) for ( w = 0; w < nWords; w++ ) pSim[w] = ~(pSim0[w] ^ pSim1[w]); + else assert( 0 ); + } +} + + +// returns 1 if the functionality with indexes i1 and i2 is the same +static inline int Abc_NtkFinCompareSimTwo( Abc_Ntk_t * pNtk, Vec_Int_t * vCos, Vec_Wrd_t * vSims, int nWords, int i1, int i2 ) +{ + Abc_Obj_t * pObj; int i; + assert( i1 != i2 ); + Abc_NtkForEachObjVec( vCos, pNtk, pObj, i ) + { + word * pSim0 = Vec_WrdEntryP( vSims, nWords * Abc_ObjFaninId0(pObj) ); + if ( Abc_InfoHasBit((unsigned*)pSim0, i1) != Abc_InfoHasBit((unsigned*)pSim0, i2) ) + return 0; + } + return 1; +} + +Gia_Man_t * Abc_NtkFinMiterToGia( Abc_Ntk_t * pNtk, Vec_Int_t * vTypes, Vec_Int_t * vCos, Vec_Int_t * vCis, Vec_Int_t * vNodes, + int iObjs[2], int Types[2], Vec_Int_t * vLits ) +{ + Gia_Man_t * pNew = NULL, * pTemp; + Abc_Obj_t * pObj; + Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); + int n, i, Type, iMiter, iLit, * pLits; + // create AIG manager + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( pNtk->pName ); + pNew->pSpec = Abc_UtilStrsav( pNtk->pSpec ); + Gia_ManHashStart( pNew ); + // create inputs + Abc_NtkForEachObjVec( vCis, pNtk, pObj, i ) + { + iLit = Gia_ManAppendCi(pNew); + for ( n = 0; n < 2; n++ ) + { + if ( iObjs[n] != (int)Abc_ObjId(pObj) ) + Vec_IntWriteEntry( vLits, Abc_Var2Lit(Abc_ObjId(pObj), n), iLit ); + else if ( Types[n] != ABC_FIN_NEG ) + Vec_IntWriteEntry( vLits, Abc_Var2Lit(Abc_ObjId(pObj), n), Abc_NtkFinSimOneLit(pNew, pObj, Types[n], vLits, n, vTemp) ); + else // if ( iObjs[n] == (int)Abc_ObjId(pObj) && Types[n] == ABC_FIN_NEG ) + Vec_IntWriteEntry( vLits, Abc_Var2Lit(Abc_ObjId(pObj), n), Abc_LitNot(iLit) ); + } + } + // create internal nodes + Abc_NtkForEachObjVec( vNodes, pNtk, pObj, i ) + { + Type = Abc_NtkIsMappedLogic(pNtk) ? Mio_GateReadCell((Mio_Gate_t *)pObj->pData) : Vec_IntEntry(vTypes, Abc_ObjId(pObj)); + for ( n = 0; n < 2; n++ ) + { + if ( iObjs[n] != (int)Abc_ObjId(pObj) ) + Vec_IntWriteEntry( vLits, Abc_Var2Lit(Abc_ObjId(pObj), n), Abc_NtkFinSimOneLit(pNew, pObj, Type, vLits, n, vTemp) ); + else if ( Types[n] != ABC_FIN_NEG ) + Vec_IntWriteEntry( vLits, Abc_Var2Lit(Abc_ObjId(pObj), n), Abc_NtkFinSimOneLit(pNew, pObj, Types[n], vLits, n, vTemp) ); + else // if ( iObjs[n] == (int)Abc_ObjId(pObj) && Types[n] == ABC_FIN_NEG ) + Vec_IntWriteEntry( vLits, Abc_Var2Lit(Abc_ObjId(pObj), n), Abc_LitNot(Abc_NtkFinSimOneLit(pNew, pObj, Type, vLits, n, vTemp)) ); + } + } + // create comparator + iMiter = 0; + Abc_NtkForEachObjVec( vCos, pNtk, pObj, i ) + { + pLits = Vec_IntEntryP( vLits, Abc_Var2Lit(Abc_ObjFaninId0(pObj), 0) ); + iLit = Gia_ManHashXor( pNew, pLits[0], pLits[1] ); + iMiter = Gia_ManHashOr( pNew, iMiter, iLit ); + } + Gia_ManAppendCo( pNew, iMiter ); + // perform cleanup + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vTemp ); + return pNew; +} +void Abc_NtkFinSimulateOne( Abc_Ntk_t * pNtk, Vec_Int_t * vTypes, Vec_Int_t * vCos, Vec_Int_t * vCis, Vec_Int_t * vNodes, + Vec_Wec_t * vMap2, Vec_Int_t * vPat, Vec_Wrd_t * vSims, int nWords, Vec_Int_t * vPairs, Vec_Wec_t * vRes, int iLevel, int iItem ) +{ + Abc_Obj_t * pObj; + Vec_Int_t * vClass, * vArray; + int i, Counter = 0; + int nItems = Vec_WecSizeSize(vRes); + assert( nItems == Vec_WecSizeSize(vMap2) ); + assert( nItems <= 128 * nWords ); + // assign inputs + assert( Vec_IntSize(vPat) == Vec_IntSize(vCis) ); + Abc_NtkForEachObjVec( vCis, pNtk, pObj, i ) + { + int w, iObj = Abc_ObjId( pObj ); + word Init = Vec_IntEntry(vPat, i) ? ~((word)0) : 0; + word * pSim = Vec_WrdEntryP( vSims, nWords * Abc_ObjId(pObj) ); + for ( w = 0; w < nWords; w++ ) + pSim[w] = Init; + vArray = Vec_WecEntry(vMap2, iObj); + if ( Vec_IntSize(vArray) > 0 ) + { + int k, iFin, Index, iObj, Type; + Vec_IntForEachEntryDouble( vArray, iFin, Index, k ) + { + assert( Index < 64 ); + iObj = Vec_IntEntry( vPairs, 2*iFin ); + assert( iObj == (int)Abc_ObjId(pObj) ); + Type = Vec_IntEntry( vPairs, 2*iFin+1 ); + assert( Type == ABC_FIN_NEG || Type == ABC_FIN_SA0 || Type == ABC_FIN_SA1 ); + if ( Type == ABC_FIN_NEG || Abc_InfoHasBit((unsigned *)pSim, Index) != Abc_NtkFinSimOneBit(pObj, Type, vSims, nWords, Index) ) + Abc_InfoXorBit( (unsigned *)pSim, Index ); + Counter++; + } + } + } + // simulate internal nodes + Abc_NtkForEachObjVec( vNodes, pNtk, pObj, i ) + { + int iObj = Abc_ObjId( pObj ); + int Type = Abc_NtkIsMappedLogic(pNtk) ? -1 : Vec_IntEntry( vTypes, iObj ); + word * pSim = Vec_WrdEntryP( vSims, nWords * Abc_ObjId(pObj) ); + Abc_NtkFinSimOneWord( pObj, Type, vSims, nWords ); + vArray = Vec_WecEntry(vMap2, iObj); + if ( Vec_IntSize(vArray) > 0 ) + { + int k, iFin, Index, iObj, Type; + Vec_IntForEachEntryDouble( vArray, iFin, Index, k ) + { + assert( Index < 64 * nWords ); + iObj = Vec_IntEntry( vPairs, 2*iFin ); + assert( iObj == (int)Abc_ObjId(pObj) ); + Type = Vec_IntEntry( vPairs, 2*iFin+1 ); + if ( Type == ABC_FIN_NEG || Abc_InfoHasBit((unsigned *)pSim, Index) != Abc_NtkFinSimOneBit(pObj, Type, vSims, nWords, Index) ) + Abc_InfoXorBit( (unsigned *)pSim, Index ); + Counter++; + } + } + } + assert( nItems == 2*Counter ); + + // confirm no refinement + Vec_WecForEachLevelStop( vRes, vClass, i, iLevel+1 ) + { + int k, iFin, Index, Value; + int iFin0 = Vec_IntEntry( vClass, 0 ); + int Index0 = Vec_IntEntry( vClass, 1 ); + Vec_IntForEachEntryDoubleStart( vClass, iFin, Index, k, 2 ) + { + if ( i == iLevel && k/2 >= iItem ) + break; + //printf( "Double-checking pair %d and %d\n", iFin0, iFin ); + Value = Abc_NtkFinCompareSimTwo( pNtk, vCos, vSims, nWords, Index0, Index ); + assert( Value ); // the same value + } + } + + // check refinement + Vec_WecForEachLevelStart( vRes, vClass, i, iLevel ) + { + int k, iFin, Index, Value, Index0 = Vec_IntEntry(vClass, 1); + int j = (i == iLevel) ? 2*iItem : 2; + Vec_Int_t * vNewClass = NULL; + Vec_IntForEachEntryDoubleStart( vClass, iFin, Index, k, j ) + { + Value = Abc_NtkFinCompareSimTwo( pNtk, vCos, vSims, nWords, Index0, Index ); + if ( Value ) // the same value + { + Vec_IntWriteEntry( vClass, j++, iFin ); + Vec_IntWriteEntry( vClass, j++, Index ); + continue; + } + // create new class + vNewClass = vNewClass ? vNewClass : Vec_WecPushLevel( vRes ); + Vec_IntPushTwo( vNewClass, iFin, Index ); // index and first entry + vClass = Vec_WecEntry( vRes, i ); + } + Vec_IntShrink( vClass, j ); + } +} + +/**Function************************************************************* + + Synopsis [Check equivalence using SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkFinCheckPair( Abc_Ntk_t * pNtk, Vec_Int_t * vTypes, Vec_Int_t * vCos, Vec_Int_t * vCis, Vec_Int_t * vNodes, int iObjs[2], int Types[2], Vec_Int_t * vLits ) +{ + Gia_Man_t * pGia = Abc_NtkFinMiterToGia( pNtk, vTypes, vCos, vCis, vNodes, iObjs, Types, vLits ); + if ( Gia_ManAndNum(pGia) == 0 && Gia_ObjIsConst0(Gia_ObjFanin0(Gia_ManCo(pGia, 0))) ) + { + Vec_Int_t * vPat = Gia_ObjFaninC0(Gia_ManCo(pGia, 0)) ? Vec_IntStart(Vec_IntSize(vCis)) : NULL; + Gia_ManStop( pGia ); + return vPat; + } + else + { + extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); + Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( pGia, 8, 0, 1, 0 ); + sat_solver * pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + if ( pSat == NULL ) + { + Gia_ManStop( pGia ); + Cnf_DataFree( pCnf ); + return NULL; + } + else + { + int i, nConfLimit = 10000; + Vec_Int_t * vPat = NULL; + int status, iVarBeg = pCnf->nVars - Gia_ManPiNum(pGia);// - 1; + //Gia_AigerWrite( pGia, "temp_detect.aig", 0, 0 ); + Gia_ManStop( pGia ); + Cnf_DataFree( pCnf ); + status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, 0, 0, 0 ); + if ( status == l_Undef ) + vPat = Vec_IntAlloc(0); + else if ( status == l_True ) + { + vPat = Vec_IntAlloc( Vec_IntSize(vCis) ); + for ( i = 0; i < Vec_IntSize(vCis); i++ ) + Vec_IntPush( vPat, sat_solver_var_value(pSat, iVarBeg+i) ); + } + //printf( "%d ", sat_solver_nconflicts(pSat) ); + sat_solver_delete( pSat ); + return vPat; + } + } +} + + +/**Function************************************************************* + + Synopsis [Refinement of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFinLocalSetup( Vec_Int_t * vPairs, Vec_Int_t * vList, Vec_Wec_t * vMap2, Vec_Int_t * vResArray ) +{ + int i, iFin; + Vec_IntClear( vResArray ); + Vec_IntForEachEntry( vList, iFin, i ) + { + int iObj = Vec_IntEntry( vPairs, 2*iFin ); + int Type = Vec_IntEntry( vPairs, 2*iFin+1 ); + Vec_Int_t * vArray = Vec_WecEntry( vMap2, iObj ); + Vec_IntPushTwo( vArray, iFin, i ); + Vec_IntPushTwo( vResArray, iFin, i ); + } +} +void Abc_NtkFinLocalSetdown( Vec_Int_t * vPairs, Vec_Int_t * vList, Vec_Wec_t * vMap2 ) +{ + int i, iFin; + Vec_IntForEachEntry( vList, iFin, i ) + { + int iObj = Vec_IntEntry( vPairs, 2*iFin ); + Vec_Int_t * vArray = Vec_WecEntry( vMap2, iObj ); + Vec_IntClear( vArray ); + } +} +int Abc_NtkFinRefinement( Abc_Ntk_t * pNtk, Vec_Int_t * vTypes, Vec_Int_t * vCos, Vec_Int_t * vCis, Vec_Int_t * vNodes, + Vec_Int_t * vPairs, Vec_Int_t * vList, Vec_Wec_t * vMap2, Vec_Wec_t * vResult ) +{ + Vec_Wec_t * vRes = Vec_WecAlloc( 100 ); + int nWords = Abc_Bit6WordNum( Vec_IntSize(vList) ); + Vec_Wrd_t * vSims = Vec_WrdStart( nWords * Abc_NtkObjNumMax(pNtk) ); // simulation info for each object + Vec_Int_t * vLits = Vec_IntStart( 2*Abc_NtkObjNumMax(pNtk) ); // two literals for each object + Vec_Int_t * vPat, * vClass, * vArray; + int i, k, iFin, Index, nCalls = 0; + // prepare + vArray = Vec_WecPushLevel( vRes ); + Abc_NtkFinLocalSetup( vPairs, vList, vMap2, vArray ); + // try all-0/all-1 pattern + for ( i = 0; i < 2; i++ ) + { + vPat = Vec_IntAlloc( Vec_IntSize(vCis) ); + Vec_IntFill( vPat, Vec_IntSize(vCis), i ); + Abc_NtkFinSimulateOne( pNtk, vTypes, vCos, vCis, vNodes, vMap2, vPat, vSims, nWords, vPairs, vRes, 0, 1 ); + Vec_IntFree( vPat ); + } + // explore the classes + //Vec_WecPrint( vRes, 0 ); + Vec_WecForEachLevel( vRes, vClass, i ) + { + int iFin0 = Vec_IntEntry( vClass, 0 ); + int Index0 = Vec_IntEntry( vClass, 1 ); + Vec_IntForEachEntryDoubleStart( vClass, iFin, Index, k, 2 ) + { + int Objs[2] = { Vec_IntEntry(vPairs, 2*iFin0), Vec_IntEntry(vPairs, 2*iFin) }; + int Types[2] = { Vec_IntEntry(vPairs, 2*iFin0+1), Vec_IntEntry(vPairs, 2*iFin+1) }; + nCalls++; + //printf( "Checking pair %d and %d.\n", iFin0, iFin ); + vPat = Abc_NtkFinCheckPair( pNtk, vTypes, vCos, vCis, vNodes, Objs, Types, vLits ); + if ( vPat == NULL ) // proved + continue; + assert( Vec_IntEntry(vClass, k) == iFin ); + if ( Vec_IntSize(vPat) == 0 ) + { + Vec_Int_t * vNewClass = Vec_WecPushLevel( vRes ); + Vec_IntPushTwo( vNewClass, iFin, Index ); // index and first entry + vClass = Vec_WecEntry( vRes, i ); + Vec_IntDrop( vClass, k+1 ); + Vec_IntDrop( vClass, k ); + } + else // resimulate and refine + Abc_NtkFinSimulateOne( pNtk, vTypes, vCos, vCis, vNodes, vMap2, vPat, vSims, nWords, vPairs, vRes, i, k/2 ); + Vec_IntFree( vPat ); + // make sure refinement happened (k'th entry is now absent or different) + vClass = Vec_WecEntry( vRes, i ); + assert( Vec_IntSize(vClass) <= k || Vec_IntEntry(vClass, k) != iFin ); + k -= 2; + //Vec_WecPrint( vRes, 0 ); + } + } + // unprepare + Abc_NtkFinLocalSetdown( vPairs, vList, vMap2 ); + // reload proved equivs into the final array + Vec_WecForEachLevel( vRes, vArray, i ) + { + assert( Vec_IntSize(vArray) % 2 == 0 ); + if ( Vec_IntSize(vArray) <= 2 ) + continue; + vClass = Vec_WecPushLevel( vResult ); + Vec_IntForEachEntryDouble( vArray, iFin, Index, k ) + Vec_IntPush( vClass, iFin ); + } + Vec_WecFree( vRes ); + Vec_WrdFree( vSims ); + Vec_IntFree( vLits ); + return nCalls; +} + +/**Function************************************************************* + + Synopsis [Detecting classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_ObjFinGateType( Abc_Obj_t * pNode ) +{ + char * pSop = (char *)pNode->pData; + if ( !strcmp(pSop, "1 1\n") ) return ABC_FIN_RDOB_BUFF; + if ( !strcmp(pSop, "0 1\n") ) return ABC_FIN_RDOB_NOT; + if ( !strcmp(pSop, "11 1\n") ) return ABC_FIN_RDOB_AND; + if ( !strcmp(pSop, "11 0\n") ) return ABC_FIN_RDOB_NAND; + if ( !strcmp(pSop, "00 0\n") ) return ABC_FIN_RDOB_OR; + if ( !strcmp(pSop, "00 1\n") ) return ABC_FIN_RDOB_NOR; + if ( !strcmp(pSop, "01 1\n10 1\n") ) return ABC_FIN_RDOB_XOR; + if ( !strcmp(pSop, "11 1\n00 1\n") ) return ABC_FIN_RDOB_NXOR; + return ABC_FIN_NONE; +} +int Abc_NtkFinCheckTypesOk( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; int i; + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( Abc_ObjFinGateType(pObj) == ABC_FIN_NONE ) + return i; + return 0; +} +int Abc_NtkFinCheckTypesOk2( Abc_Ntk_t * pNtk ) +{ + Mio_Library_t * pLib = (Mio_Library_t *)pNtk->pManFunc; + int i, iObj, Type; + Vec_IntForEachEntryDoubleStart( pNtk->vFins, iObj, Type, i, 2 ) + { + Abc_Obj_t * pObj = Abc_NtkObj( pNtk, iObj ); + Mio_Gate_t * pGateFlt, * pGateObj = (Mio_Gate_t *)pObj->pData; + if ( Type < 0 ) // SA0, SA1, NEG + continue; + pGateFlt = Mio_LibraryReadGateById( pLib, Type ); + if ( Mio_GateReadPinNum(pGateFlt) < 1 ) + continue; + if ( Mio_GateReadPinNum(pGateObj) != Mio_GateReadPinNum(pGateFlt) ) + return iObj; + } + return 0; +} +Vec_Int_t * Abc_NtkFinComputeTypes( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; int i; + Vec_Int_t * vObjs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pObj, i ) + Vec_IntWriteEntry( vObjs, Abc_ObjId(pObj), Abc_ObjFinGateType(pObj) ); + return vObjs; +} +Vec_Int_t * Abc_NtkFinComputeObjects( Vec_Int_t * vPairs, Vec_Wec_t ** pvMap, int nObjs ) +{ + int i, iObj, Type; + Vec_Int_t * vObjs = Vec_IntAlloc( 100 ); + *pvMap = Vec_WecStart( nObjs ); + Vec_IntForEachEntryDoubleStart( vPairs, iObj, Type, i, 2 ) + { + Vec_IntPush( vObjs, iObj ); + Vec_WecPush( *pvMap, iObj, i/2 ); + } + Vec_IntUniqify( vObjs ); + return vObjs; +} +Vec_Int_t * Abc_NtkFinCreateList( Vec_Wec_t * vMap, Vec_Int_t * vClass ) +{ + int i, iObj; + Vec_Int_t * vList = Vec_IntAlloc( 100 ); + Vec_IntForEachEntry( vClass, iObj, i ) + Vec_IntAppend( vList, Vec_WecEntry(vMap, iObj) ); + return vList; +} +int Abc_NtkFinCountPairs( Vec_Wec_t * vClasses ) +{ + int i, Counter = 0; + Vec_Int_t * vLevel; + Vec_WecForEachLevel( vClasses, vLevel, i ) + Counter += Vec_IntSize(vLevel) - 1; + return Counter; +} +Vec_Wec_t * Abc_NtkDetectFinClasses( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Vec_Int_t * vTypes = NULL; // gate types + Vec_Int_t * vPairs; // original info as a set of pairs (ObjId, TypeId) + Vec_Int_t * vObjs; // all those objects that have some fin + Vec_Wec_t * vMap; // for each object, the set of fins + Vec_Wec_t * vMap2; // for each local object, the set of pairs (Info, Index) + Vec_Wec_t * vClasses; // classes of objects + Vec_Wec_t * vCoSets; // corresponding CO sets + Vec_Int_t * vClass; // one class + Vec_Int_t * vCoSet; // one set of COs + Vec_Int_t * vCiSet; // one set of CIs + Vec_Int_t * vNodeSet; // one set of nodes + Vec_Int_t * vList; // one info list + Vec_Wec_t * vResult; // resulting equivalences + int i, iObj, nCalls; + if ( pNtk->vFins == NULL ) + { + printf( "Current network does not have the required info.\n" ); + return NULL; + } + assert( Abc_NtkIsSopLogic(pNtk) || Abc_NtkIsMappedLogic(pNtk) ); + if ( Abc_NtkIsSopLogic(pNtk) ) + { + iObj = Abc_NtkFinCheckTypesOk(pNtk); + if ( iObj ) + { + printf( "Current network contains unsupported gate types (for example, see node \"%s\").\n", Abc_ObjName(Abc_NtkObj(pNtk, iObj)) ); + return NULL; + } + vTypes = Abc_NtkFinComputeTypes( pNtk ); + } + else if ( Abc_NtkIsMappedLogic(pNtk) ) + { + iObj = Abc_NtkFinCheckTypesOk2(pNtk); + if ( iObj ) + { + printf( "Current network has mismatch between mapped gate size and fault gate size (for example, see node \"%s\").\n", Abc_ObjName(Abc_NtkObj(pNtk, iObj)) ); + return NULL; + } + } + else assert( 0 ); + //Abc_NtkFrameExtend( pNtk ); + // collect data + vPairs = pNtk->vFins; + vObjs = Abc_NtkFinComputeObjects( vPairs, &vMap, Abc_NtkObjNumMax(pNtk) ); + vClasses = Abc_NtkDetectObjClasses( pNtk, vObjs, &vCoSets ); + // refine classes + vCiSet = Vec_IntAlloc( 1000 ); + vNodeSet = Vec_IntAlloc( 1000 ); + vMap2 = Vec_WecStart( Abc_NtkObjNumMax(pNtk) ); + vResult = Vec_WecAlloc( 1000 ); + Vec_WecForEachLevel( vClasses, vClass, i ) + { + // extract one window + vCoSet = Vec_WecEntry( vCoSets, i ); + Abc_NtkFinMiterCollect( pNtk, vCoSet, vCiSet, vNodeSet ); + // refine one class + vList = Abc_NtkFinCreateList( vMap, vClass ); + nCalls = Abc_NtkFinRefinement( pNtk, vTypes, vCoSet, vCiSet, vNodeSet, vPairs, vList, vMap2, vResult ); + if ( fVerbose ) + printf( "Group %4d : Obj =%4d. Fins =%4d. CI =%5d. CO =%5d. Node =%6d. SAT calls =%5d.\n", + i, Vec_IntSize(vClass), Vec_IntSize(vList), Vec_IntSize(vCiSet), Vec_IntSize(vCoSet), Vec_IntSize(vNodeSet), nCalls ); + Vec_IntFree( vList ); + } + // sort entries in each array + Vec_WecForEachLevel( vResult, vClass, i ) + Vec_IntSort( vClass, 0 ); + // sort by the index of the first entry + Vec_WecSortByFirstInt( vResult, 0 ); + // cleanup + Vec_IntFreeP( & vTypes ); + Vec_IntFree( vObjs ); + Vec_WecFree( vClasses ); + Vec_WecFree( vMap ); + Vec_WecFree( vMap2 ); + Vec_WecFree( vCoSets ); + Vec_IntFree( vCiSet ); + Vec_IntFree( vNodeSet ); + return vResult; +} + +/**Function************************************************************* + + Synopsis [Print results.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintFinResults( Vec_Wec_t * vClasses ) +{ + Vec_Int_t * vClass; + int i, k, Entry; + Vec_WecForEachLevel( vClasses, vClass, i ) + Vec_IntForEachEntryStart( vClass, Entry, k, 1 ) + printf( "%d %d\n", Vec_IntEntry(vClass, 0), Entry ); +} + /**Function************************************************************* Synopsis [Top-level procedure.] @@ -193,9 +1240,20 @@ finish: SeeAlso [] ***********************************************************************/ -void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fSeq, int fVerbose ) +void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fSeq, int fVerbose, int fVeryVerbose ) { - printf( "This procedure is currently not used.\n" ); + Vec_Wec_t * vResult; + abctime clk = Abc_Clock(); + if ( fSeq ) + Abc_NtkFrameExtend( pNtk ); + vResult = Abc_NtkDetectFinClasses( pNtk, fVerbose ); + printf( "Computed %d equivalence classes with %d item pairs. ", Vec_WecSize(vResult), Abc_NtkFinCountPairs(vResult) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + if ( fVeryVerbose ) + Vec_WecPrint( vResult, 1 ); +// if ( fVerbose ) +// Abc_NtkPrintFinResults( vResult ); + Vec_WecFree( vResult ); } diff --git a/src/map/mio/mio.h b/src/map/mio/mio.h index f45cce89..6e16a57f 100644 --- a/src/map/mio/mio.h +++ b/src/map/mio/mio.h @@ -112,6 +112,7 @@ extern char * Mio_LibraryReadName ( Mio_Library_t * pLib ); extern int Mio_LibraryReadGateNum ( Mio_Library_t * pLib ); extern Mio_Gate_t * Mio_LibraryReadGates ( Mio_Library_t * pLib ); extern Mio_Gate_t ** Mio_LibraryReadGateArray ( Mio_Library_t * pLib ); +extern Mio_Gate_t * Mio_LibraryReadGateById ( Mio_Library_t * pLib, int iD ); extern Mio_Gate_t * Mio_LibraryReadGateByName ( Mio_Library_t * pLib, char * pName, char * pOutName ); extern char * Mio_LibraryReadSopByName ( Mio_Library_t * pLib, char * pName ); extern Mio_Gate_t * Mio_LibraryReadGateByTruth( Mio_Library_t * pLib, word t ); diff --git a/src/map/mio/mioApi.c b/src/map/mio/mioApi.c index bb601a05..38e754a6 100644 --- a/src/map/mio/mioApi.c +++ b/src/map/mio/mioApi.c @@ -44,6 +44,7 @@ char * Mio_LibraryReadName ( Mio_Library_t * pLib ) { retur int Mio_LibraryReadGateNum ( Mio_Library_t * pLib ) { return pLib->nGates; } Mio_Gate_t * Mio_LibraryReadGates ( Mio_Library_t * pLib ) { return pLib->pGates; } Mio_Gate_t ** Mio_LibraryReadGateArray ( Mio_Library_t * pLib ) { return pLib->ppGatesName;} +Mio_Gate_t * Mio_LibraryReadGateById ( Mio_Library_t * pLib, int Id ) { assert( pLib->ppGates0[Id]->Cell == Id ); return pLib->ppGates0[Id];} Mio_Gate_t * Mio_LibraryReadBuf ( Mio_Library_t * pLib ) { return pLib->pGateBuf; } Mio_Gate_t * Mio_LibraryReadInv ( Mio_Library_t * pLib ) { return pLib->pGateInv; } Mio_Gate_t * Mio_LibraryReadConst0 ( Mio_Library_t * pLib ) { return pLib->pGate0; } diff --git a/src/map/mio/mioRead.c b/src/map/mio/mioRead.c index b170256d..798458f3 100644 --- a/src/map/mio/mioRead.c +++ b/src/map/mio/mioRead.c @@ -586,7 +586,10 @@ void Mio_LibrarySortGates( Mio_Library_t * pLib ) int i = 0; ppGates = ABC_ALLOC( Mio_Gate_t *, pLib->nGates ); Mio_LibraryForEachGate( pLib, pGate ) + { + pGate->Cell = i; ppGates[i++] = pGate; + } assert( i == pLib->nGates ); // sort gates by name pLib->ppGates0 = ABC_ALLOC( Mio_Gate_t *, pLib->nGates ); -- cgit v1.2.3 From 460a5700a5369a0cb46ae5c6d5bbc001deaf8ab4 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 9 Nov 2016 21:19:52 -0800 Subject: Compiler warnings. --- src/base/abci/abcDetect.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'src') diff --git a/src/base/abci/abcDetect.c b/src/base/abci/abcDetect.c index b1a598cd..0125a67e 100644 --- a/src/base/abci/abcDetect.c +++ b/src/base/abci/abcDetect.c @@ -842,7 +842,6 @@ void Abc_NtkFinSimulateOne( Abc_Ntk_t * pNtk, Vec_Int_t * vTypes, Vec_Int_t * vC Vec_WecForEachLevelStop( vRes, vClass, i, iLevel+1 ) { int k, iFin, Index, Value; - int iFin0 = Vec_IntEntry( vClass, 0 ); int Index0 = Vec_IntEntry( vClass, 1 ); Vec_IntForEachEntryDoubleStart( vClass, iFin, Index, k, 2 ) { @@ -952,7 +951,6 @@ void Abc_NtkFinLocalSetup( Vec_Int_t * vPairs, Vec_Int_t * vList, Vec_Wec_t * vM Vec_IntForEachEntry( vList, iFin, i ) { int iObj = Vec_IntEntry( vPairs, 2*iFin ); - int Type = Vec_IntEntry( vPairs, 2*iFin+1 ); Vec_Int_t * vArray = Vec_WecEntry( vMap2, iObj ); Vec_IntPushTwo( vArray, iFin, i ); Vec_IntPushTwo( vResArray, iFin, i ); @@ -993,7 +991,6 @@ int Abc_NtkFinRefinement( Abc_Ntk_t * pNtk, Vec_Int_t * vTypes, Vec_Int_t * vCos Vec_WecForEachLevel( vRes, vClass, i ) { int iFin0 = Vec_IntEntry( vClass, 0 ); - int Index0 = Vec_IntEntry( vClass, 1 ); Vec_IntForEachEntryDoubleStart( vClass, iFin, Index, k, 2 ) { int Objs[2] = { Vec_IntEntry(vPairs, 2*iFin0), Vec_IntEntry(vPairs, 2*iFin) }; -- cgit v1.2.3 From 71a52ae9e5e0572f93df9eb14cba8c7567d3e676 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 10 Nov 2016 09:38:07 -0800 Subject: Renaming command 'detect' to be 'faultclasses'. --- src/base/abci/abc.c | 20 +++++++++++--------- src/base/abci/abcDetect.c | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index b1c81cd5..07ea78b2 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -134,7 +134,7 @@ static int Abc_CommandRr ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandCascade ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandExtract ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandVarMin ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandDetect ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFaultClasses ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBmsStart ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBmsStop ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -778,7 +778,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "cascade", Abc_CommandCascade, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "extract", Abc_CommandExtract, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "varmin", Abc_CommandVarMin, 0 ); - Cmd_CommandAdd( pAbc, "Synthesis", "detect", Abc_CommandDetect, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "faultclasses", Abc_CommandFaultClasses, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "exact", Abc_CommandExact, 1 ); Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_start", Abc_CommandBmsStart, 0 ); @@ -7235,7 +7235,7 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandDetect( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandFaultClasses( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fSeq, int fVerbose, int fVeryVerbose ); extern void Abc_NtkGenFaultList( Abc_Ntk_t * pNtk, char * pFileName ); @@ -7285,12 +7285,14 @@ int Abc_CommandDetect( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: detect [-gsvwh]\n" ); - Abc_Print( -2, "\t detects properties of internal nodes\n" ); - Abc_Print( -2, "\t-g : toggle generating fault list for the given network [default = %s]\n", fGen? "yes": "no" ); - Abc_Print( -2, "\t-s : toggle using sequential circuit information [default = %s]\n", fSeq? "yes": "no" ); - Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-w : toggle printing equivalence classes [default = %s]\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "usage: faultclasses [-gsvwh]\n" ); + Abc_Print( -2, "\t computes equivalence classes of faults in the given mapped netlist;\n" ); + Abc_Print( -2, "\t the fault list with faults in the format: \n" ); + Abc_Print( -2, "\t should be read by command \"read_fins\" before calling this command\n" ); + Abc_Print( -2, "\t-g : toggle generating a fault list for the current mapped network [default = %s]\n", fGen? "yes": "no" ); + Abc_Print( -2, "\t-s : toggle detecting sequential equivalence classes [default = %s]\n", fSeq? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout during computation [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printing of resulting fault equivalence classes [default = %s]\n", fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } diff --git a/src/base/abci/abcDetect.c b/src/base/abci/abcDetect.c index 0125a67e..4325f49c 100644 --- a/src/base/abci/abcDetect.c +++ b/src/base/abci/abcDetect.c @@ -233,7 +233,7 @@ Vec_Int_t * Io_ReadFins( Abc_Ntk_t * pNtk, char * pFileName, int fVerbose ) Vec_IntPushTwo( vPairs, Vec_IntEntry(vMap, iObj), Type ); } assert( Vec_IntSize(vPairs) == 2 * nLines ); - printf( "Finished reading %d lines.\n", nLines - 1 ); + printf( "Finished reading %d lines from the fault list file \"%s\".\n", nLines - 1, pFileName ); // verify the reader by printing the results if ( fVerbose ) -- cgit v1.2.3 From 254ac2df8f74d627cdd21c958b65208dfe025097 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 17 Nov 2016 12:12:19 -0800 Subject: Fixed several compiler warnings. --- src/opt/dsc/dsc.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/opt/dsc/dsc.c b/src/opt/dsc/dsc.c index 409b040f..ce180fe3 100644 --- a/src/opt/dsc/dsc.c +++ b/src/opt/dsc/dsc.c @@ -59,17 +59,17 @@ inline void xorInPlace( word * pOut, word * pIn2, int nWords) } 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"); - int i; - for (i=1;i<=pNode->off[0];i++) { + 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<=pNode->on[0];i++) { + for (i=1;i<=(int)pNode->on[0];i++) { printf("%c%c", (pNode->on[i] & 1U) ? ' ' : '!', 'a'+(pNode->on[i] >> 1)); } printf("\n"); @@ -127,10 +127,10 @@ void merge(unsigned int * const pOut, const unsigned int * const pIn) { } 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 - unsigned int* xiOFF, * xiON, * xjOFF, * xjON; if (niPolarity) { xiOFF = ni->off; xiON = ni->on; @@ -151,14 +151,14 @@ void dsc_and_group(Dsc_node_t * pOut, Dsc_node_t * ni, int niPolarity, Dsc_node_ int xiOFFSize = xiOFF[0]; int xjOFFSize = xjOFF[0]; if (xiOFFSize <= xjOFFSize) { - pOut->off[0] = xiOFFSize; // set the number of elements int i; + pOut->off[0] = xiOFFSize; // set the number of elements for (i = 1; i <= xiOFFSize; i++) { pOut->off[i] = xiOFF[i]; } } else { - pOut->off[0] = xjOFFSize; // set the number of elements int i; + pOut->off[0] = xjOFFSize; // set the number of elements for (i = 1; i <= xjOFFSize; i++) { pOut->off[i] = xjOFF[i]; } @@ -168,15 +168,15 @@ void dsc_and_group(Dsc_node_t * pOut, Dsc_node_t * ni, int niPolarity, Dsc_node_ } // 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; - int i; - for (i = 1; i <= xiONSize; i++) { + for (i = 1; i <= (int)xiONSize; i++) { pOut->on[i] = xiON[i]; } - int j; - for (j = 1; j <= xjONSize; j++) { + for (j = 1; j <= (int)xjONSize; j++) { pOut->on[i++] = xjON[j]; } // set the positive cofactor of the new group @@ -194,13 +194,11 @@ void dsc_and_group(Dsc_node_t * pOut, Dsc_node_t * ni, int niPolarity, Dsc_node_ } void dsc_xor_group(Dsc_node_t * pOut, Dsc_node_t * ni, Dsc_node_t * nj, int nVars, const int TRUTH_WORDS) { - // expression - concat(pOut->exp, '[', ']', ni->exp, 1, nj->exp, 1); // - const unsigned int const * xiOFF = ni->off; - const unsigned int const * xiON = ni->on; - const unsigned int const * xjOFF = nj->off; - const unsigned int const * xjON = nj->on; + 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]; @@ -210,6 +208,8 @@ void dsc_xor_group(Dsc_node_t * pOut, Dsc_node_t * ni, Dsc_node_t * nj, int nVar 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; @@ -312,15 +312,18 @@ extern int Dsc_Decompose(word * pTruth, const int nVarsInit, char * const pRes, const int TRUTH_WORDS = Abc_TtWordNum(nVarsInit); const int NEED_POOL_ALLOC = (pool == NULL); - pRes[0] = '\0'; - pRes[1] = '\0'; - 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); @@ -375,10 +378,6 @@ extern int Dsc_Decompose(word * pTruth, const int nVarsInit, char * const pRes, return -1; } } - 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 while (n > 0) { int tempN = 0; int i, j, iPolarity, jPolarity; -- cgit v1.2.3 From 585f3a6407146b58acbc5cc880dde566c1292441 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 17 Nov 2016 12:16:14 -0800 Subject: New SAT-based optimization package. --- src/opt/sbd/module.make | 5 ++ src/opt/sbd/sbd.c | 53 ++++++++++++++++ src/opt/sbd/sbd.h | 104 +++++++++++++++++++++++++++++++ src/opt/sbd/sbdCnf.c | 147 +++++++++++++++++++++++++++++++++++++++++++ src/opt/sbd/sbdCore.c | 53 ++++++++++++++++ src/opt/sbd/sbdInt.h | 75 ++++++++++++++++++++++ src/opt/sbd/sbdSat.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++ src/opt/sbd/sbdWin.c | 52 ++++++++++++++++ 8 files changed, 650 insertions(+) create mode 100644 src/opt/sbd/module.make create mode 100644 src/opt/sbd/sbd.c create mode 100644 src/opt/sbd/sbd.h create mode 100644 src/opt/sbd/sbdCnf.c create mode 100644 src/opt/sbd/sbdCore.c create mode 100644 src/opt/sbd/sbdInt.h create mode 100644 src/opt/sbd/sbdSat.c create mode 100644 src/opt/sbd/sbdWin.c (limited to 'src') 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..946a2ee4 --- /dev/null +++ b/src/opt/sbd/sbd.h @@ -0,0 +1,104 @@ +/**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_Ntk_t_ Sbd_Ntk_t; +typedef struct Sbd_Par_t_ Sbd_Par_t; +struct Sbd_Par_t_ +{ + int nTfoLevMax; // the maximum fanout levels + int nTfiLevMax; // the maximum fanin levels + int nFanoutMax; // the maximum number of fanouts + int nDepthMax; // the maximum depth to try + int nVarMax; // the maximum variable count + int nMffcMin; // the minimum MFFC size + int nMffcMax; // the maximum MFFC size + int nDecMax; // the maximum number of decompositions + int nWinSizeMax; // the maximum window size + int nGrowthLevel; // the maximum allowed growth in level + int nBTLimit; // the maximum number of conflicts in one SAT run + int nNodesMax; // the maximum number of nodes to try + int iNodeOne; // one particular node to try + int nFirstFixed; // the number of first nodes to be treated as fixed + int nTimeWin; // the size of timing window in percents + int DeltaCrit; // delay delta in picoseconds + int DelAreaRatio; // delay/area tradeoff (how many ps we trade for a unit of area) + int fRrOnly; // perform redundance removal + int fArea; // performs optimization for area + int fAreaRev; // performs optimization for area in reverse order + int fMoreEffort; // performs high-affort minimization + int fUseAndOr; // enable internal detection of AND/OR gates + int fZeroCost; // enable zero-cost replacement + int fUseSim; // enable simulation + int fPrintDecs; // enable printing decompositions + int fAllBoxes; // enable preserving all boxes + int fLibVerbose; // enable library stats + int fDelayVerbose; // enable delay stats + int fVerbose; // enable basic stats + int fVeryVerbose; // enable detailed stats +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== sbdCnf.c ==========================================================*/ +/*=== sbdCore.c ==========================================================*/ +extern void Sbd_ParSetDefault( Sbd_Par_t * pPars ); +extern int Sbd_NtkPerform( Sbd_Ntk_t * p, Sbd_Par_t * pPars ); +/*=== sbdNtk.c ==========================================================*/ +extern Sbd_Ntk_t * Sbd_NtkConstruct( Vec_Wec_t * vFanins, int nPis, int nPos, Vec_Str_t * vFixed, Vec_Str_t * vEmpty, Vec_Wrd_t * vTruths ); +extern void Sbd_NtkFree( Sbd_Ntk_t * p ); +extern Vec_Int_t * Sbd_NodeReadFanins( Sbd_Ntk_t * p, int i ); +extern word * Sbd_NodeReadTruth( Sbd_Ntk_t * p, int i ); +extern int Sbd_NodeReadFixed( Sbd_Ntk_t * p, int i ); +extern int Sbd_NodeReadUsed( Sbd_Ntk_t * p, int i ); +/*=== sbdWin.c ==========================================================*/ +extern Vec_Int_t * Sbd_NtkDfs( Sbd_Ntk_t * p, Vec_Wec_t * vGroups, Vec_Int_t * vGroupMap, Vec_Int_t * vBoxesLeft, int fAllBoxes ); + + +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..4d86d2ee --- /dev/null +++ b/src/opt/sbd/sbdCore.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/sbdInt.h b/src/opt/sbd/sbdInt.h new file mode 100644 index 00000000..1157d02c --- /dev/null +++ b/src/opt/sbd/sbdInt.h @@ -0,0 +1,75 @@ +/**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 +#include +#include +#include + +#include "misc/vec/vec.h" +#include "sat/bsat/satSolver.h" +#include "misc/util/utilNam.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 + + +//////////////////////////////////////////////////////////////////////// +/// 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..16405c06 --- /dev/null +++ b/src/opt/sbd/sbdSat.c @@ -0,0 +1,161 @@ +/**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 /// +//////////////////////////////////////////////////////////////////////// + +#define MAX_M 12 // max inputs +#define MAX_N 20 // max nodes +#define MAX_K 6 // max lutsize + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**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] ) // inputs, nodes, lutsize +{ + sat_solver * pSat = NULL; + Vec_Int_t * vTemp = Vec_IntAlloc(100); + // assign vars + int RetValue, n, i, k, 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] = nVars++; + printf( "Number of vars = %d.\n", 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++ ) + Vec_IntPush( vTemp, Abc_Var2Lit(pVars[n][i][k], 0) ); + RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); + assert( RetValue ); + } + // each fanin of each node is connected + for ( n = 0; n < N; n++ ) + for ( k = 0; k < K; k++ ) + { + 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 ); + } + // each fanin is connected once; fanins are ordered; nodes are ordered + for ( n = 0; n < N; n++ ) + for ( i = 0; i < M+N; i++ ) + for ( k = 0; k < K; k++ ) + { + int n2, i2, k2; + for ( n2 = 0; n2 <=n; n2++ ) + for ( i2 = i; i2 < M+N; i2++ ) + for ( k2 = k; k2 < K; k2++ ) + { + if ( n2 == n && i2 == i && k2 == k ) + continue; + Vec_IntPushTwo( vTemp, Abc_Var2Lit(pVars[n][i][k], 1), Abc_Var2Lit(pVars[n2][i2][k2], 1) ); + 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" ); + for ( i = M+N-1; i >= 0; i-- ) + { + printf( "%2d %c : ", i, i < M ? 'i' : 'n' ); + for ( n = 0; n < N; n++ ) + { + for ( k = 0; k < K; k++ ) + printf( "%c", sat_solver_var_value(pSat, pVars[n][i][k]) ? '*' : '.' ); + printf( " " ); + } + printf( "\n" ); + } +} +void Sbd_SolverTopoTest() +{ + int M = 4; // inputs + int N = 3; // nodes + int K = 2; // lutsize + int status, nCalls, v, nVars; + int pVars[MAX_N][MAX_M+MAX_N][MAX_K]; // 20 x 32 x 6 = 3840 + Vec_Int_t * vLits = Vec_IntAlloc(100); + sat_solver * pSat = Sbd_SolverTopo( M, N, K, pVars ); + nVars = sat_solver_nvars( pSat ); + for ( nCalls = 0; nCalls < 1000000; nCalls++ ) + { + // 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 ); + // print solution + 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) ); + assert( status ); + } + printf( "Found %d solutions.\n", nCalls ); + sat_solver_delete( pSat ); + Vec_IntFree( vLits ); +} + + +//////////////////////////////////////////////////////////////////////// +/// 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..e8702f7d --- /dev/null +++ b/src/opt/sbd/sbdWin.c @@ -0,0 +1,52 @@ +/**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 + -- cgit v1.2.3 From 58476ea738e467894dc73a338e8b52165565da2c Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 17 Nov 2016 17:32:34 -0800 Subject: New SAT-based optimization package. --- src/opt/sbd/sbdSat.c | 247 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 232 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/opt/sbd/sbdSat.c b/src/opt/sbd/sbdSat.c index 16405c06..4ae8654c 100644 --- a/src/opt/sbd/sbdSat.c +++ b/src/opt/sbd/sbdSat.c @@ -19,6 +19,7 @@ ***********************************************************************/ #include "sbdInt.h" +#include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START @@ -51,7 +52,7 @@ sat_solver * Sbd_SolverTopo( int M, int N, int K, int pVars[MAX_N][MAX_M+MAX_N][ sat_solver * pSat = NULL; Vec_Int_t * vTemp = Vec_IntAlloc(100); // assign vars - int RetValue, n, i, k, nVars = 0; + int RetValue, n, i, j, k, nVars = 0; for ( n = 0; n < N; n++ ) for ( i = 0; i < M+N; i++ ) for ( k = 0; k < K; k++ ) @@ -85,14 +86,32 @@ sat_solver * Sbd_SolverTopo( int M, int N, int K, int pVars[MAX_N][MAX_M+MAX_N][ for ( i = 0; i < M+N; i++ ) for ( k = 0; k < K; k++ ) { - int n2, i2, k2; - for ( n2 = 0; n2 <=n; n2++ ) - for ( i2 = i; i2 < M+N; i2++ ) - for ( k2 = k; k2 < K; k2++ ) + int n2 = n, i2 = i, k2 = k; + for ( n2 = 0; n2 <= n; n2++ ) + for ( i2 = i; i2 < M+N; i2++ ) + for ( k2 = 0; k2 <= k; k2++ ) { if ( n2 == n && i2 == i && k2 == k ) continue; - Vec_IntPushTwo( vTemp, Abc_Var2Lit(pVars[n][i][k], 1), Abc_Var2Lit(pVars[n2][i2][k2], 1) ); + Vec_IntFillTwo( vTemp, 2, Abc_Var2Lit(pVars[n][i][k], 1), Abc_Var2Lit(pVars[n2][i2][k2], 1) ); + RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); + assert( RetValue ); + } + } + // exclude fanins of two-input nodes + if ( K == 2 ) + for ( n = 0; n < N; n++ ) + for ( i = M; i < M+N; i++ ) + for ( k = 0; k < K; k++ ) + { + int k2; + for ( j = 0; j < i; j++ ) + for ( k2 = 0; k2 < K; k2++ ) + { + Vec_IntClear( vTemp ); + Vec_IntPush( vTemp, Abc_Var2Lit(pVars[n][i][k], 1) ); + Vec_IntPush( vTemp, Abc_Var2Lit(pVars[n][j][!k], 1) ); + Vec_IntPush( vTemp, Abc_Var2Lit(pVars[i-M][j][k2], 1) ); RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); assert( RetValue ); } @@ -104,9 +123,13 @@ void Sbd_SolverTopoPrint( sat_solver * pSat, int M, int N, int K, int pVars[MAX_ { int n, i, k; printf( "Solution:\n" ); - for ( i = M+N-1; i >= 0; i-- ) + 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' : 'n' ); + printf( "%2d %c | ", i, i < M ? 'i' : ' ' ); for ( n = 0; n < N; n++ ) { for ( k = 0; k < K; k++ ) @@ -118,15 +141,15 @@ void Sbd_SolverTopoPrint( sat_solver * pSat, int M, int N, int K, int pVars[MAX_ } void Sbd_SolverTopoTest() { - int M = 4; // inputs - int N = 3; // nodes - int K = 2; // lutsize - int status, nCalls, v, nVars; + int M = 4; // 6; // inputs + int N = 4; // 16; // nodes + int K = 2; // 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 Vec_Int_t * vLits = Vec_IntAlloc(100); sat_solver * pSat = Sbd_SolverTopo( M, N, K, pVars ); nVars = sat_solver_nvars( pSat ); - for ( nCalls = 0; nCalls < 1000000; nCalls++ ) + for ( nIter = 0; nIter < 1000000; nIter++ ) { // find onset minterm status = sat_solver_solve( pSat, NULL, NULL, 0, 0, 0, 0 ); @@ -135,6 +158,7 @@ void Sbd_SolverTopoTest() if ( status == l_False ) break; assert( status == l_True ); + nSols++; // print solution Sbd_SolverTopoPrint( pSat, M, N, K, pVars ); // remember variable values @@ -144,14 +168,207 @@ void Sbd_SolverTopoTest() Vec_IntPush( vLits, Abc_Var2Lit(v, 1) ); // add breaking clause status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits) ); - assert( status ); + if ( status == 0 ) + break; } - printf( "Found %d solutions.\n", nCalls ); + printf( "Found %d solutions.\n", nSols ); sat_solver_delete( pSat ); Vec_IntFree( vLits ); } + +/**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<> v) & 1) ? Truths[pLuts[i][v]] : ~Truths[pLuts[i][v]]; + Truth |= Mint; + } + Truths[M+i] = Truth; + } + return Truths[M+N-1]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sbd_SolverFunc( int M, int N, int K, int pLuts[MAX_N][MAX_K], word TruthInit, int * pValues ) +{ + int fVerbose = 0; + sat_solver * pSat = NULL; + 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)(TruthInit & 1); + word TruthNew, Truth = (TruthInit & 1) ? ~TruthInit : TruthInit; + word Mask = M < 6 ? Abc_Tt6Mask(1 << M) : ~(word)0; + printf( "Number of parameters %d x %d = %d.\n", N, nLutPars, nVars ); + // create solver + pSat = sat_solver_new(); + sat_solver_setnvars( pSat, nVars ); + // start with the last minterm + iMint = (1 << M) - 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( "\nIter %3d : Minterm %d\n", Iter, iMint ); + 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 || ((TruthInit >> iMint) & 1) != fCompl ) + { + status = sat_solver_addclause( pSat, pLits2, pLits2 + nLits ); + if ( status == 0 ) + { + fCompl = -1; + goto finish; + } + } + if ( (i != N - 1 || ((TruthInit >> iMint) & 1) == 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); + TruthNew = Sbd_SolverTruth( M, N, K, pLuts, pValues ); + 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 *)&Truth, (1 << M) ); printf( "\n" ); + Extra_PrintBinary( stdout, (unsigned *)&TruthNew, (1 << M) ); printf( "\n" ); + } + if ( (Truth & Mask) == (Mask & TruthNew) ) + break; + + // get new minterm + iMint = Abc_Tt6FirstBit( Truth ^ TruthNew ); + } +finish: + printf( "Finished after %d iterations and %d conflicts.\n", Iter, sat_solver_nconflicts(pSat) ); + sat_solver_delete( pSat ); + return fCompl; +} +void Sbd_SolverFuncTest() +{ +// int M = 4; // 6; // inputs +// int N = 3; // 16; // nodes +// int K = 2; // 2; // lutsize + int M = 6; // 6; // inputs + int N = 5; // 16; // nodes + int K = 2; // 2; // lutsize +// word Truth = ~(word)(1 << 0); + word Truth = ~(word)(23423); + int pLuts[MAX_N][MAX_K] = { {0,1}, {2,3}, {4,5}, {6,7}, {8,9} }; + int pValues[MAX_N*((1<= 0; k-- ) + printf( "%d", pValues[i*nLutPars+k] ); + printf( "0\n" ); + } +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// -- cgit v1.2.3 From a703052bc535280de6f7ce01b796a5982e22f5a1 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 19 Nov 2016 18:15:06 -0800 Subject: New SAT-based optimization package. --- src/misc/util/utilTruth.h | 8 + src/opt/sbd/sbdSat.c | 376 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 319 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/misc/util/utilTruth.h b/src/misc/util/utilTruth.h index cb567096..5a4ef545 100644 --- a/src/misc/util/utilTruth.h +++ b/src/misc/util/utilTruth.h @@ -1603,6 +1603,14 @@ static inline int Abc_TtFindFirstBit( word * pIn, int nVars ) return 64*w + Abc_Tt6FirstBit(pIn[w]); return -1; } +static inline int Abc_TtFindFirstDiffBit( word * pIn1, word * pIn2, int nVars ) +{ + int w, nWords = Abc_TtWordNum(nVars); + for ( w = 0; w < nWords; w++ ) + if ( pIn1[w] ^ pIn2[w] ) + return 64*w + Abc_Tt6FirstBit(pIn1[w] ^ pIn2[w]); + return -1; +} static inline int Abc_TtFindFirstZero( word * pIn, int nVars ) { int w, nWords = Abc_TtWordNum(nVars); diff --git a/src/opt/sbd/sbdSat.c b/src/opt/sbd/sbdSat.c index 4ae8654c..bd49c50e 100644 --- a/src/opt/sbd/sbdSat.c +++ b/src/opt/sbd/sbdSat.c @@ -28,9 +28,10 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -#define MAX_M 12 // max inputs -#define MAX_N 20 // max nodes +#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 /// @@ -47,17 +48,22 @@ ABC_NAMESPACE_IMPL_START SeeAlso [] ***********************************************************************/ -sat_solver * Sbd_SolverTopo( int M, int N, int K, int pVars[MAX_N][MAX_M+MAX_N][MAX_K] ) // inputs, nodes, lutsize +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, k, nVars = 0; - for ( n = 0; n < N; n++ ) + 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++ ) + 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 vars = %d.\n", nVars ); + printf( "Number of topo vars = %d.\n", nVars ); + *pnVars = nVars; // add constraints pSat = sat_solver_new(); sat_solver_setnvars( pSat, nVars ); @@ -67,55 +73,128 @@ sat_solver * Sbd_SolverTopo( int M, int N, int K, int pVars[MAX_N][MAX_M+MAX_N][ Vec_IntClear( vTemp ); for ( n = 0; n < N; n++ ) for ( k = 0; k < K; k++ ) - Vec_IntPush( vTemp, Abc_Var2Lit(pVars[n][i][k], 0) ); + 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 ); } - // each fanin of each node is connected + 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++; + } } - // each fanin is connected once; fanins are ordered; nodes are ordered + 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 ( 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++ ) { - int n2 = n, i2 = i, k2 = k; - for ( n2 = 0; n2 <= n; n2++ ) - for ( i2 = i; i2 < M+N; i2++ ) - for ( k2 = 0; k2 <= k; k2++ ) + // first of n cannot be smaller than first of n-1 (but can be equal) + for ( j = i+1; j < M+n-1; j++ ) { - if ( n2 == n && i2 == i && k2 == k ) - continue; - Vec_IntFillTwo( vTemp, 2, Abc_Var2Lit(pVars[n][i][k], 1), Abc_Var2Lit(pVars[n2][i2][k2], 1) ); + 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 = M; i < M+N; i++ ) + for ( i = 0; i < M+n; i++ ) for ( k = 0; k < K; k++ ) + for ( d = 0; d < MAX_D-1; d++ ) { - int k2; - for ( j = 0; j < i; j++ ) - for ( k2 = 0; k2 < K; k2++ ) - { - Vec_IntClear( vTemp ); - Vec_IntPush( vTemp, Abc_Var2Lit(pVars[n][i][k], 1) ); - Vec_IntPush( vTemp, Abc_Var2Lit(pVars[n][j][!k], 1) ); - Vec_IntPush( vTemp, Abc_Var2Lit(pVars[i-M][j][k2], 1) ); - RetValue = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); - assert( RetValue ); - } + 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; } @@ -132,8 +211,11 @@ void Sbd_SolverTopoPrint( sat_solver * pSat, int M, int N, int K, int pVars[MAX_ printf( "%2d %c | ", i, i < M ? 'i' : ' ' ); for ( n = 0; n < N; n++ ) { - for ( k = 0; k < K; k++ ) - printf( "%c", sat_solver_var_value(pSat, pVars[n][i][k]) ? '*' : '.' ); + 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" ); @@ -141,14 +223,16 @@ void Sbd_SolverTopoPrint( sat_solver * pSat, int M, int N, int K, int pVars[MAX_ } void Sbd_SolverTopoTest() { - int M = 4; // 6; // inputs - int N = 4; // 16; // nodes - int K = 2; // 2; // lutsize + 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 ); - nVars = sat_solver_nvars( pSat ); + sat_solver * pSat = Sbd_SolverTopo( M, N, K, pVars, pVars2, pDelays, 2, &nVars ); for ( nIter = 0; nIter < 1000000; nIter++ ) { // find onset minterm @@ -160,7 +244,8 @@ void Sbd_SolverTopoTest() assert( status == l_True ); nSols++; // print solution - Sbd_SolverTopoPrint( pSat, M, N, K, pVars ); + if ( nIter < 5 ) + Sbd_SolverTopoPrint( pSat, M, N, K, pVars ); // remember variable values Vec_IntClear( vLits ); for ( v = 0; v < nVars; v++ ) @@ -170,14 +255,93 @@ void Sbd_SolverTopoTest() status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits) ); if ( status == 0 ) break; + //if ( nIter == 5 ) + // break; } - printf( "Found %d solutions.\n", nSols ); 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.] @@ -191,10 +355,9 @@ void Sbd_SolverTopoTest() ***********************************************************************/ word Sbd_SolverTruth( int M, int N, int K, int pLuts[MAX_N][MAX_K], int pValues[MAX_N*((1<> v) & 1) == 0 ); + } + Abc_TtOr( pTruth, pTruth, pMint, nWords ); + } + } + if ( fCompl ) + Abc_TtNot( pRes, nWords ); + return pRes; +} + /**Function************************************************************* @@ -225,30 +417,34 @@ word Sbd_SolverTruth( int M, int N, int K, int pLuts[MAX_N][MAX_K], int pValues[ SeeAlso [] ***********************************************************************/ -int Sbd_SolverFunc( int M, int N, int K, int pLuts[MAX_N][MAX_K], word TruthInit, int * pValues ) +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)(TruthInit & 1); - word TruthNew, Truth = (TruthInit & 1) ? ~TruthInit : TruthInit; - word Mask = M < 6 ? Abc_Tt6Mask(1 << M) : ~(word)0; - printf( "Number of parameters %d x %d = %d.\n", N, nLutPars, nVars ); + 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 << 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( "\nIter %3d : Minterm %d\n", Iter, iMint ); + //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++ ) { @@ -284,7 +480,7 @@ int Sbd_SolverFunc( int M, int N, int K, int pLuts[MAX_N][MAX_K], word TruthInit nLits++; } // add clauses - if ( i != N - 1 || ((TruthInit >> iMint) & 1) != fCompl ) + if ( i != N - 1 || Abc_TtGetBit(pTruthInit, iMint) != fCompl ) { status = sat_solver_addclause( pSat, pLits2, pLits2 + nLits ); if ( status == 0 ) @@ -293,7 +489,7 @@ int Sbd_SolverFunc( int M, int N, int K, int pLuts[MAX_N][MAX_K], word TruthInit goto finish; } } - if ( (i != N - 1 || ((TruthInit >> iMint) & 1) == fCompl) && m > 0 ) + if ( (i != N - 1 || Abc_TtGetBit(pTruthInit, iMint) == fCompl) && m > 0 ) { status = sat_solver_addclause( pSat, pLits, pLits + nLits ); if ( status == 0 ) @@ -318,7 +514,11 @@ int Sbd_SolverFunc( int M, int N, int K, int pLuts[MAX_N][MAX_K], word TruthInit // collect values for ( i = 0; i < nVars; i++ ) pValues[i] = sat_solver_var_value(pSat, i); - TruthNew = Sbd_SolverTruth( M, N, K, pLuts, pValues ); + + 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++ ) @@ -327,18 +527,21 @@ int Sbd_SolverFunc( int M, int N, int K, int pLuts[MAX_N][MAX_K], word TruthInit 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 *)&Truth, (1 << M) ); printf( "\n" ); - Extra_PrintBinary( stdout, (unsigned *)&TruthNew, (1 << M) ); printf( "\n" ); + Extra_PrintBinary( stdout, (unsigned *)pTruthInit, (1 << M) ); printf( "\n" ); + Extra_PrintBinary( stdout, (unsigned *)pTruthNew, (1 << M) ); printf( "\n" ); } - if ( (Truth & Mask) == (Mask & TruthNew) ) + if ( Abc_TtEqual(pTruthInit, pTruthNew, nWords) ) break; // get new minterm - iMint = Abc_Tt6FirstBit( Truth ^ TruthNew ); + iMint = Abc_TtFindFirstDiffBit( pTruthInit, pTruthNew, M ); } finish: - printf( "Finished after %d iterations and %d conflicts.\n", Iter, sat_solver_nconflicts(pSat) ); + 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() @@ -346,15 +549,58 @@ 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 = 2; // 2; // lutsize -// word Truth = ~(word)(1 << 0); - word Truth = ~(word)(23423); - int pLuts[MAX_N][MAX_K] = { {0,1}, {2,3}, {4,5}, {6,7}, {8,9} }; + 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< Date: Mon, 21 Nov 2016 11:52:50 -0800 Subject: Minor bug fixes. --- src/aig/gia/giaSatMap.c | 2 +- src/base/abci/abc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/aig/gia/giaSatMap.c b/src/aig/gia/giaSatMap.c index 0ddd4a39..5c17b74e 100644 --- a/src/aig/gia/giaSatMap.c +++ b/src/aig/gia/giaSatMap.c @@ -489,7 +489,7 @@ int Sbm_ManTestSat( void * pMan ) StartSol = Vec_IntSize(p->vSolCuts); // StartSol = 30; - while ( fKeepTrying ) + while ( fKeepTrying && StartSol-fKeepTrying > 0 ) { printf( "Trying to find mapping with %d gates.\n", StartSol-fKeepTrying ); // for ( i = Vec_IntSize(p->vSolCuts)-5; i < nVars; i++ ) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 689c21b5..3efc41c9 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -7463,7 +7463,7 @@ usage: Abc_Print( -2, "\t finds optimum networks using SAT-based exact synthesis for hex truth tables ...\n" ); Abc_Print( -2, "\t-D : constrain maximum depth (if too low, algorithm may not terminate)\n" ); Abc_Print( -2, "\t-A : input arrival times (comma separated list)\n" ); - Abc_Print( -2, "\t-S : number of start gates in search [default = %s]\n", nStartGates ); + Abc_Print( -2, "\t-S : number of start gates in search [default = %d]\n", nStartGates ); Abc_Print( -2, "\t-C : the limit on the number of conflicts; turn off with 0 [default = %d]\n", nBTLimit ); Abc_Print( -2, "\t-a : toggle create AIG [default = %s]\n", fMakeAIG ? "yes" : "no" ); Abc_Print( -2, "\t-t : run test suite\n" ); -- cgit v1.2.3 From 64bdbe1a74fcf6343e06caa0dc4f6dae0e621e76 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 22 Nov 2016 20:09:25 -0800 Subject: Adding switch '-c' to generate only stuck-at faults in 'faultclasses -g'. --- src/base/abci/abc.c | 14 +++++++++----- src/base/abci/abcDetect.c | 8 +++++--- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 3efc41c9..4dcea33a 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -7241,18 +7241,21 @@ usage: int Abc_CommandFaultClasses( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fSeq, int fVerbose, int fVeryVerbose ); - extern void Abc_NtkGenFaultList( Abc_Ntk_t * pNtk, char * pFileName ); + extern void Abc_NtkGenFaultList( Abc_Ntk_t * pNtk, char * pFileName, int fStuckAt ); Abc_Ntk_t * pNtk; - int c, fGen = 0, fSeq = 0, fVerbose = 0, fVeryVerbose = 0; + int c, fGen = 0, fStuckAt = 0, fSeq = 0, fVerbose = 0, fVeryVerbose = 0; pNtk = Abc_FrameReadNtk(pAbc); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "gsvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "gcsvwh" ) ) != EOF ) { switch ( c ) { case 'g': fGen ^= 1; break; + case 'c': + fStuckAt ^= 1; + break; case 's': fSeq ^= 1; break; @@ -7281,18 +7284,19 @@ int Abc_CommandFaultClasses( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( fGen ) { char * pFileName = Extra_FileNameGenericAppend(Abc_NtkSpec(pNtk), "_faults.txt"); - Abc_NtkGenFaultList( pNtk, pFileName ); + Abc_NtkGenFaultList( pNtk, pFileName, fStuckAt ); } else Abc_NtkDetectClassesTest( pNtk, fSeq, fVerbose, fVeryVerbose ); return 0; usage: - Abc_Print( -2, "usage: faultclasses [-gsvwh]\n" ); + Abc_Print( -2, "usage: faultclasses [-gcsvwh]\n" ); Abc_Print( -2, "\t computes equivalence classes of faults in the given mapped netlist;\n" ); Abc_Print( -2, "\t the fault list with faults in the format: \n" ); Abc_Print( -2, "\t should be read by command \"read_fins\" before calling this command\n" ); Abc_Print( -2, "\t-g : toggle generating a fault list for the current mapped network [default = %s]\n", fGen? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle using only stuck-at faults in the generated fault list [default = %s]\n", fStuckAt? "yes": "no" ); Abc_Print( -2, "\t-s : toggle detecting sequential equivalence classes [default = %s]\n", fSeq? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout during computation [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing of resulting fault equivalence classes [default = %s]\n", fVeryVerbose? "yes": "no" ); diff --git a/src/base/abci/abcDetect.c b/src/base/abci/abcDetect.c index 4325f49c..8b8bba64 100644 --- a/src/base/abci/abcDetect.c +++ b/src/base/abci/abcDetect.c @@ -63,7 +63,7 @@ typedef enum { SeeAlso [] ***********************************************************************/ -void Abc_NtkGenFaultList( Abc_Ntk_t * pNtk, char * pFileName ) +void Abc_NtkGenFaultList( Abc_Ntk_t * pNtk, char * pFileName, int fStuckAt ) { Mio_Library_t * pLib = (Mio_Library_t *)pNtk->pManFunc; Mio_Gate_t * pGate; @@ -84,14 +84,16 @@ void Abc_NtkGenFaultList( Abc_Ntk_t * pNtk, char * pFileName ) fprintf( pFile, "%d %s %s\n", Count, Abc_ObjName(pObj), "SA0" ), Count++; fprintf( pFile, "%d %s %s\n", Count, Abc_ObjName(pObj), "SA1" ), Count++; fprintf( pFile, "%d %s %s\n", Count, Abc_ObjName(pObj), "NEG" ), Count++; + if ( fStuckAt ) + continue; // add other faults, which correspond to changing the given gate // by another gate with the same support-size from the same library Mio_LibraryForEachGate( pLib, pGate ) if ( pGate != pGateObj && Mio_GateReadPinNum(pGate) == nInputs ) fprintf( pFile, "%d %s %s\n", Count, Abc_ObjName(pObj), Mio_GateReadName(pGate) ), Count++; } - printf( "Generated fault list \"%s\" for network \"%s\" with %d nodes and %d faults.\n", - pFileName, Abc_NtkName(pNtk), Abc_NtkNodeNum(pNtk), Count-1 ); + printf( "Generated fault list \"%s\" for network \"%s\" with %d nodes and %d %sfaults.\n", + pFileName, Abc_NtkName(pNtk), Abc_NtkNodeNum(pNtk), Count-1, fStuckAt ? "stuck-at ":"" ); fclose( pFile ); } -- cgit v1.2.3 From 6b55bf0205f414ca711d92baea115a808fff3dc9 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 26 Nov 2016 14:28:12 -0800 Subject: New SAT-based optimization package. --- src/base/abci/abc.c | 129 +++++++++++++ src/base/io/ioWriteDot.c | 2 +- src/misc/util/utilTruth.h | 28 +++ src/opt/sbd/sbd.h | 52 ++--- src/opt/sbd/sbdCore.c | 479 +++++++++++++++++++++++++++++++++++++++++++++- src/opt/sbd/sbdInt.h | 1 + src/opt/sbd/sbdSat.c | 173 +++++++++++++++++ 7 files changed, 821 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 4dcea33a..25bcc306 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -55,6 +55,7 @@ #include "sat/bmc/bmc.h" #include "proof/ssc/ssc.h" #include "opt/sfm/sfm.h" +#include "opt/sbd/sbd.h" #include "bool/rpo/rpo.h" #include "map/mpm/mpm.h" #include "opt/fret/fretime.h" @@ -481,6 +482,7 @@ static int Abc_CommandAbc9Acec ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Esop ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Exorcism ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Mfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Mfsd ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandAbc9PoPart2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandAbc9CexCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandAbc9CexMerge ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -1122,6 +1124,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&esop", Abc_CommandAbc9Esop, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&exorcism", Abc_CommandAbc9Exorcism, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&mfs", Abc_CommandAbc9Mfs, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&mfsd", Abc_CommandAbc9Mfsd, 0 ); // Cmd_CommandAdd( pAbc, "ABC9", "&popart2", Abc_CommandAbc9PoPart2, 0 ); // Cmd_CommandAdd( pAbc, "ABC9", "&cexcut", Abc_CommandAbc9CexCut, 0 ); // Cmd_CommandAdd( pAbc, "ABC9", "&cexmerge", Abc_CommandAbc9CexMerge, 0 ); @@ -40824,6 +40827,132 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Mfsd( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Sbd_NtkPerform( Gia_Man_t * pGia, Sbd_Par_t * pPars ); + Gia_Man_t * pTemp; int c; + Sbd_Par_t Pars, * pPars = &Pars; + Sbd_ParSetDefault( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KWFMCavwh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLutSize < 0 ) + goto usage; + break; + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nTfoLevels = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nTfoLevels < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nTfoFanMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nTfoFanMax < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nWinSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nWinSizeMax < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nBTLimit < 0 ) + goto usage; + break; + case 'a': + pPars->fArea ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Mfs(): There is no AIG.\n" ); + return 0; + } + if ( Gia_ManBufNum(pAbc->pGia) ) + { + Abc_Print( -1, "Abc_CommandAbc9Mfs(): This command does not work with barrier buffers.\n" ); + return 1; + } + if ( Gia_ManHasMapping(pAbc->pGia) ) + { + Abc_Print( -1, "Abc_CommandAbc9Mfs(): The current AIG has mapping (run &st to unmap).\n" ); + return 0; + } + pTemp = Sbd_NtkPerform( pAbc->pGia, pPars ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &mfsd [-KWFMC ] [-avwh]\n" ); + Abc_Print( -2, "\t performs SAT-based delay-oriented AIG optimization\n" ); + Abc_Print( -2, "\t-K : the LUT size for delay minimization (2 <= num <= 6) [default = %d]\n", pPars->nLutSize ); + Abc_Print( -2, "\t-W : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nTfoLevels ); + Abc_Print( -2, "\t-F : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nTfoFanMax ); + Abc_Print( -2, "\t-M : the max node count of windows to consider (0 = no limit) [default = %d]\n", pPars->nWinSizeMax ); + Abc_Print( -2, "\t-C : the max number of conflicts in one SAT run (0 = no limit) [default = %d]\n", pPars->nBTLimit ); + Abc_Print( -2, "\t-a : toggle minimizing area or area+edges [default = %s]\n", pPars->fArea? "area": "area+edges" ); + Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] diff --git a/src/base/io/ioWriteDot.c b/src/base/io/ioWriteDot.c index 7de6bd81..3431c761 100644 --- a/src/base/io/ioWriteDot.c +++ b/src/base/io/ioWriteDot.c @@ -74,7 +74,7 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho Abc_Obj_t * pNode, * pFanin; char * pSopString; int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl, Prev; - int Limit = 300; + int Limit = 500; assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); diff --git a/src/misc/util/utilTruth.h b/src/misc/util/utilTruth.h index 5a4ef545..b8a34da7 100644 --- a/src/misc/util/utilTruth.h +++ b/src/misc/util/utilTruth.h @@ -266,6 +266,28 @@ static inline void Abc_TtAnd( word * pOut, word * pIn1, word * pIn2, int nWords, for ( w = 0; w < nWords; w++ ) pOut[w] = pIn1[w] & pIn2[w]; } +static inline void Abc_TtAndCompl( word * pOut, word * pIn1, int fCompl1, word * pIn2, int fCompl2, int nWords ) +{ + int w; + if ( fCompl1 ) + { + if ( fCompl2 ) + for ( w = 0; w < nWords; w++ ) + pOut[w] = ~pIn1[w] & ~pIn2[w]; + else + for ( w = 0; w < nWords; w++ ) + pOut[w] = ~pIn1[w] & pIn2[w]; + } + else + { + if ( fCompl2 ) + for ( w = 0; w < nWords; w++ ) + pOut[w] = pIn1[w] & ~pIn2[w]; + else + for ( w = 0; w < nWords; w++ ) + pOut[w] = pIn1[w] & pIn2[w]; + } +} static inline void Abc_TtAndSharp( word * pOut, word * pIn1, word * pIn2, int nWords, int fCompl ) { int w; @@ -288,6 +310,12 @@ static inline void Abc_TtOr( word * pOut, word * pIn1, word * pIn2, int nWords ) for ( w = 0; w < nWords; w++ ) pOut[w] = pIn1[w] | pIn2[w]; } +static inline void Abc_TtOrXor( word * pOut, word * pIn1, word * pIn2, int nWords ) +{ + int w; + for ( w = 0; w < nWords; w++ ) + pOut[w] |= pIn1[w] ^ pIn2[w]; +} static inline void Abc_TtXor( word * pOut, word * pIn1, word * pIn2, int nWords, int fCompl ) { int w; diff --git a/src/opt/sbd/sbd.h b/src/opt/sbd/sbd.h index 946a2ee4..e1e39a3b 100644 --- a/src/opt/sbd/sbd.h +++ b/src/opt/sbd/sbd.h @@ -35,42 +35,21 @@ ABC_NAMESPACE_HEADER_START /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// -typedef struct Sbd_Ntk_t_ Sbd_Ntk_t; typedef struct Sbd_Par_t_ Sbd_Par_t; struct Sbd_Par_t_ { - int nTfoLevMax; // the maximum fanout levels - int nTfiLevMax; // the maximum fanin levels - int nFanoutMax; // the maximum number of fanouts - int nDepthMax; // the maximum depth to try - int nVarMax; // the maximum variable count - int nMffcMin; // the minimum MFFC size - int nMffcMax; // the maximum MFFC size - int nDecMax; // the maximum number of decompositions - int nWinSizeMax; // the maximum window size - int nGrowthLevel; // the maximum allowed growth in level - int nBTLimit; // the maximum number of conflicts in one SAT run - int nNodesMax; // the maximum number of nodes to try - int iNodeOne; // one particular node to try - int nFirstFixed; // the number of first nodes to be treated as fixed - int nTimeWin; // the size of timing window in percents - int DeltaCrit; // delay delta in picoseconds - int DelAreaRatio; // delay/area tradeoff (how many ps we trade for a unit of area) - int fRrOnly; // perform redundance removal - int fArea; // performs optimization for area - int fAreaRev; // performs optimization for area in reverse order - int fMoreEffort; // performs high-affort minimization - int fUseAndOr; // enable internal detection of AND/OR gates - int fZeroCost; // enable zero-cost replacement - int fUseSim; // enable simulation - int fPrintDecs; // enable printing decompositions - int fAllBoxes; // enable preserving all boxes - int fLibVerbose; // enable library stats - int fDelayVerbose; // enable delay stats - int fVerbose; // enable basic stats - int fVeryVerbose; // enable detailed stats + 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 fVerbose; // verbose flag + int fVeryVerbose; // verbose flag }; + //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -82,16 +61,7 @@ struct Sbd_Par_t_ /*=== sbdCnf.c ==========================================================*/ /*=== sbdCore.c ==========================================================*/ extern void Sbd_ParSetDefault( Sbd_Par_t * pPars ); -extern int Sbd_NtkPerform( Sbd_Ntk_t * p, Sbd_Par_t * pPars ); -/*=== sbdNtk.c ==========================================================*/ -extern Sbd_Ntk_t * Sbd_NtkConstruct( Vec_Wec_t * vFanins, int nPis, int nPos, Vec_Str_t * vFixed, Vec_Str_t * vEmpty, Vec_Wrd_t * vTruths ); -extern void Sbd_NtkFree( Sbd_Ntk_t * p ); -extern Vec_Int_t * Sbd_NodeReadFanins( Sbd_Ntk_t * p, int i ); -extern word * Sbd_NodeReadTruth( Sbd_Ntk_t * p, int i ); -extern int Sbd_NodeReadFixed( Sbd_Ntk_t * p, int i ); -extern int Sbd_NodeReadUsed( Sbd_Ntk_t * p, int i ); -/*=== sbdWin.c ==========================================================*/ -extern Vec_Int_t * Sbd_NtkDfs( Sbd_Ntk_t * p, Vec_Wec_t * vGroups, Vec_Int_t * vGroupMap, Vec_Int_t * vBoxesLeft, int fAllBoxes ); +extern Gia_Man_t * Sbd_NtkPerform( Gia_Man_t * p, Sbd_Par_t * pPars ); ABC_NAMESPACE_HEADER_END diff --git a/src/opt/sbd/sbdCore.c b/src/opt/sbd/sbdCore.c index 4d86d2ee..2120a8f9 100644 --- a/src/opt/sbd/sbdCore.c +++ b/src/opt/sbd/sbdCore.c @@ -19,14 +19,44 @@ ***********************************************************************/ #include "sbdInt.h" +#include "opt/dau/dau.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[3]; // simulation information (main, backup, controlability) + Vec_Int_t * vCover; // temporary + // target node + int Pivot; // target node + int nTfiLeaves; // TFI leaves + int nTfiNodes; // TFI nodes + Vec_Int_t * vTfo; // TFO (excludes node, includes roots) + Vec_Int_t * vLeaves; // leaves (TFI leaves + extended leaves) + Vec_Int_t * vTfi; // TFI (TFI + node + extended TFI) + Vec_Int_t * vCounts[2]; // counters of zeros and ones +}; + +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 ); } + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -42,7 +72,454 @@ ABC_NAMESPACE_IMPL_START SeeAlso [] ***********************************************************************/ +void Sbd_ParSetDefault( Sbd_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Sbd_Par_t) ); + pPars->nLutSize = 4; // target LUT size + pPars->nTfoLevels = 4; // 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->fVerbose = 0; // verbose flag + pPars->fVeryVerbose = 0; // verbose flag +} + +/**Function************************************************************* + + Synopsis [Computes window roots for all nodes.] + + Description [] + + 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; + 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_ManForEachAndId( p, Id ) + { + int fAlwaysRoot = 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( vNodes, vNodes0, vNodes1 ); + 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 ); + Vec_IntPush( vNodes, Id ); + } + Vec_WecFree( vTemp ); + // print the results + 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->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 < 3; i++ ) + p->vSims[i] = Vec_WrdStart( Gia_ManObjNum(pGia) * p->pPars->nWords ); + // target node + p->vCover = Vec_IntStart( 100 ); + p->vLeaves = Vec_IntAlloc( Gia_ManCiNum(pGia) ); + p->vTfi = Vec_IntAlloc( Gia_ManAndNum(pGia) ); + p->vCounts[0] = Vec_IntAlloc( 100 ); + p->vCounts[1] = Vec_IntAlloc( 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 < 3; i++ ) + Vec_WrdFree( p->vSims[i] ); + Vec_IntFree( p->vCover ); + Vec_IntFree( p->vLeaves ); + Vec_IntFree( p->vTfi ); + Vec_IntFree( p->vCounts[0] ); + Vec_IntFree( p->vCounts[1] ); +} + + +/**Function************************************************************* + + Synopsis [Constructing window.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sbd_ManWindowSim_rec( Sbd_Man_t * p, int Node ) +{ + Gia_Obj_t * pObj; + if ( Vec_IntEntry(p->vMirrors, Node) >= 0 ) + Node = Abc_Lit2Var( Vec_IntEntry(p->vMirrors, Node) ); + if ( Gia_ObjIsTravIdCurrentId(p->pGia, Node) || Node == 0 ) + return; + Gia_ObjSetTravIdCurrentId(p->pGia, Node); + pObj = Gia_ManObj( p->pGia, Node ); + if ( Gia_ObjIsCi(pObj) ) + { + Vec_IntPush( p->vLeaves, Node ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Sbd_ManWindowSim_rec( p, Gia_ObjFaninId0(pObj, Node) ); + Sbd_ManWindowSim_rec( p, Gia_ObjFaninId1(pObj, Node) ); + Vec_IntPush( p->vTfi, Node ); + // simulate + 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_ObjFanin0(pObj)->fMark0 ? Sbd_ObjSim1(p, Gia_ObjFaninId0(pObj, Node)) : Sbd_ObjSim0(p, Gia_ObjFaninId1(pObj, Node)), Gia_ObjFaninC1(pObj), + p->pPars->nWords ); +} +void Sbd_ManPropagateControl( Sbd_Man_t * p, int Node ) +{ + int iObj0 = Gia_ObjFaninId0(Gia_ManObj(p->pGia, Node), Node); + int iObj1 = Gia_ObjFaninId1(Gia_ManObj(p->pGia, Node), Node); + word * pCtrl = Sbd_ObjSim2(p, Node); + word * pCtrl0 = Sbd_ObjSim2(p, iObj0); + word * pCtrl1 = Sbd_ObjSim2(p, iObj1); + word * pSims = Sbd_ObjSim0(p, Node); + word * pSims0 = Sbd_ObjSim0(p, iObj0); + word * pSims1 = Sbd_ObjSim0(p, iObj1); + int w; + for ( w = 0; w < p->pPars->nWords; w++ ) + { + pCtrl0[w] = pCtrl[w] & (pSims[w] | pSims1[w]); + pCtrl1[w] = pCtrl[w] & (pSims[w] | pSims0[w] | (~pSims0[w] & ~pSims1[w])); + } +} +void Sbd_ManWindow( Sbd_Man_t * p, int Pivot ) +{ + int i, Node; + // assign pivot and TFO (assume siminfo is assigned at the PIs) + p->Pivot = Pivot; + p->vTfo = Vec_WecEntry( p->vTfos, Pivot ); + Vec_IntClear( p->vLeaves ); + Vec_IntClear( p->vTfi ); + // simulate TFI cone + Gia_ManIncrementTravId( p->pGia ); + Sbd_ManWindowSim_rec( p, Pivot ); + p->nTfiLeaves = Vec_IntSize( p->vLeaves ); + p->nTfiNodes = Vec_IntSize( p->vTfi ); + // simulate node + Gia_ManObj(p->pGia, Pivot)->fMark0 = 1; + Abc_TtCopy( Sbd_ObjSim1(p, Pivot), Sbd_ObjSim0(p, Pivot), p->pPars->nWords, 1 ); + // simulate extended TFI cone + Vec_IntForEachEntry( p->vTfo, Node, i ) + { + Gia_ManObj(p->pGia, Abc_Lit2Var(Node))->fMark0 = 1; + if ( Abc_LitIsCompl(Node) ) + Sbd_ManWindowSim_rec( p, Node ); + } + // remove marks + Gia_ManObj(p->pGia, Pivot)->fMark0 = 0; + Vec_IntForEachEntry( p->vTfo, Node, i ) + Gia_ManObj(p->pGia, Abc_Lit2Var(Node))->fMark0 = 0; + // compute controlability for node + 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, Node), Sbd_ObjSim1(p, Node), p->pPars->nWords ); + // propagate controlability to TFI + for ( i = p->nTfiNodes; i >= 0 && (Node = Vec_IntEntry(p->vTfi, i)); i-- ) + Sbd_ManPropagateControl( p, Node ); +} + +/**Function************************************************************* + + Synopsis [Profiling divisor candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sbd_ManPrintObj( Sbd_Man_t * p, int Pivot ) +{ + int i, k, k0, k1, Id, Bit0, Bit1; + assert( p->Pivot == Pivot ); + Vec_IntClear( p->vCounts[0] ); + Vec_IntClear( p->vCounts[1] ); + // sampling matrix + for ( k = 0; k < p->pPars->nWords * 64; k++ ) + { + printf( "%3d : ", k ); + Vec_IntForEachEntry( p->vTfi, Id, i ) + { + word * pSims = Sbd_ObjSim0( p, Id ); + word * pCtrl = Sbd_ObjSim2( p, Id ); + if ( i == Vec_IntSize(p->vTfi)-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" ); + } + // covering table + printf( "Exploring %d x %d covering table.\n", Vec_IntSize(p->vCounts[0]), Vec_IntSize(p->vCounts[1]) ); + Vec_IntForEachEntry( p->vCounts[0], Bit0, k0 ) + Vec_IntForEachEntry( p->vCounts[1], Bit1, k1 ) + { + printf( "%3d %3d : ", Bit0, Bit1 ); + Vec_IntForEachEntry( p->vTfi, Id, i ) + { + word * pSims = Sbd_ObjSim0( p, Id ); + word * pCtrl = Sbd_ObjSim2( p, Id ); + if ( i == Vec_IntSize(p->vTfi)-1 ) + printf( " " ); + printf( "%c", (Abc_TtGetBit(pCtrl, Bit0) && Abc_TtGetBit(pCtrl, Bit1) && Abc_TtGetBit(pSims, Bit0) != Abc_TtGetBit(pSims, Bit1)) ? '1' : '.' ); + } + printf( "\n" ); + } +} +int Sbd_ManExplore( Sbd_Man_t * p, int Pivot, int * pCut, word * pTruth ) +{ + Sbd_ManPrintObj( p, Pivot ); + return 0; +} + +/**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_ManComputeCut( Sbd_Man_t * p, int Node ) +{ + int pCut[2*SBD_MAX_LUTSIZE]; + 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 = Abc_MaxInt( Level0, Level1 ); + int * pCut0 = Sbd_ObjCut( p, iFan0 ); + int * pCut1 = Sbd_ObjCut( p, iFan1 ); + int Cut0[2] = {1, iFan0}, * pCut0Temp = Level0 < LevMax ? Cut0 : pCut0; + int Cut1[2] = {1, iFan1}, * pCut1Temp = Level1 < LevMax ? Cut1 : pCut1; + int nSize = Sbd_CutMergeSimple( p, pCut0Temp, pCut1Temp, pCut ); + int Result = 1; // no need to resynthesize + assert( iFan0 != iFan1 ); + 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( Vec_IntEntry(p->vLutLevs, Node) == 0 ); + Vec_IntWriteEntry( p->vLutLevs, Node, LevMax ); + memcpy( Sbd_ObjCut(p, Node), pCut, sizeof(int) * (pCut[0] + 1) ); + return Result; +} +int Sbd_ManImplement( Sbd_Man_t * p, int Pivot, int * pCut, word Truth ) +{ + Vec_Int_t vLeaves = { pCut[0], pCut[0], pCut+1 }; + int iLit = Dsm_ManTruthToGia( p->pGia, &Truth, &vLeaves, p->vCover ); + int i, k, w, iObjLast = Gia_ManObjNum(p->pGia); + assert( Vec_IntEntry(p->vMirrors, Pivot) == -1 ); + Vec_IntWriteEntry( p->vMirrors, Pivot, iLit ); + assert( Vec_IntSize(p->vLutLevs) == iObjLast ); + for ( i = iObjLast; i < Gia_ManObjNum(p->pGia); i++ ) + { + Vec_IntPush( p->vLutLevs, 0 ); + Vec_IntFillExtra( p->vLutCuts, Vec_IntSize(p->vLutCuts) + p->pPars->nLutSize + 1, 0 ); + Sbd_ManComputeCut( p, i ); + for ( k = 0; k < 3; k++ ) + for ( w = 0; w < p->pPars->nWords; w++ ) + Vec_WrdPush( p->vSims[k], 0 ); + } + 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 ) + return; + 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 ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachAndId( p, i ) + Sbd_ManDerive_rec( pNew, p, i, vMirrors ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Performs delay optimization for the given LUT size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Sbd_NtkPerform( Gia_Man_t * pGia, Sbd_Par_t * pPars ) +{ + Gia_Man_t * pNew; word Truth; + Sbd_Man_t * p = Sbd_ManStart( pGia, pPars ); + int Pivot, pCut[2*SBD_MAX_LUTSIZE]; + assert( pPars->nLutSize <= 6 ); + Gia_ManForEachAndId( pGia, Pivot ) + { + if ( Sbd_ManComputeCut( p, Pivot ) ) + continue; + Sbd_ManWindow( p, Pivot ); + if ( Sbd_ManExplore( p, Pivot, pCut, &Truth ) ) + Sbd_ManImplement( p, Pivot, pCut, Truth ); + } + pNew = Sbd_ManDerive( pGia, p->vMirrors ); + Sbd_ManStop( p ); + return pNew; +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/opt/sbd/sbdInt.h b/src/opt/sbd/sbdInt.h index 1157d02c..8211610c 100644 --- a/src/opt/sbd/sbdInt.h +++ b/src/opt/sbd/sbdInt.h @@ -34,6 +34,7 @@ #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" diff --git a/src/opt/sbd/sbdSat.c b/src/opt/sbd/sbdSat.c index bd49c50e..ae865627 100644 --- a/src/opt/sbd/sbdSat.c +++ b/src/opt/sbd/sbdSat.c @@ -37,6 +37,179 @@ ABC_NAMESPACE_IMPL_START /// 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<= 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 [] -- cgit v1.2.3 From de71ef44cd679a4277c869e759bc9bccc3dbb417 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 26 Nov 2016 17:06:54 -0800 Subject: New command to profile arithmetic logic cones. --- src/base/wlc/module.make | 1 + src/base/wlc/wlc.h | 6 ++ src/base/wlc/wlcCom.c | 48 +++++++++++++- src/base/wlc/wlcNtk.c | 73 ++++++++++++++++----- src/base/wlc/wlcWin.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 278 insertions(+), 16 deletions(-) create mode 100644 src/base/wlc/wlcWin.c (limited to 'src') diff --git a/src/base/wlc/module.make b/src/base/wlc/module.make index 081be200..5a95a63f 100644 --- a/src/base/wlc/module.make +++ b/src/base/wlc/module.make @@ -8,4 +8,5 @@ SRC += src/base/wlc/wlcAbs.c \ src/base/wlc/wlcReadVer.c \ src/base/wlc/wlcSim.c \ src/base/wlc/wlcStdin.c \ + src/base/wlc/wlcWin.c \ src/base/wlc/wlcWriteVer.c diff --git a/src/base/wlc/wlc.h b/src/base/wlc/wlc.h index 90596093..1df3e5e9 100644 --- a/src/base/wlc/wlc.h +++ b/src/base/wlc/wlc.h @@ -244,6 +244,8 @@ static inline Wlc_Obj_t * Wlc_ObjFoToFi( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ) #define Wlc_ObjForEachFanin( pObj, iFanin, i ) \ for ( i = 0; (i < Wlc_ObjFaninNum(pObj)) && (((iFanin) = Wlc_ObjFaninId(pObj, i)), 1); i++ ) +#define Wlc_ObjForEachFaninObj( p, pObj, pFanin, i ) \ + for ( i = 0; (i < Wlc_ObjFaninNum(pObj)) && (((pFanin) = Wlc_NtkObj(p, Wlc_ObjFaninId(pObj, i))), 1); i++ ) #define Wlc_ObjForEachFaninReverse( pObj, iFanin, i ) \ for ( i = Wlc_ObjFaninNum(pObj) - 1; (i >= 0) && (((iFanin) = Wlc_ObjFaninId(pObj, i)), 1); i-- ) @@ -272,6 +274,8 @@ extern char * Wlc_ObjName( Wlc_Ntk_t * p, int iObj ); extern void Wlc_ObjUpdateType( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, int Type ); extern void Wlc_ObjAddFanins( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, Vec_Int_t * vFanins ); extern void Wlc_NtkFree( Wlc_Ntk_t * p ); +extern void Wlc_NtkPrintNode( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ); +extern void Wlc_NtkPrintNodeArray( Wlc_Ntk_t * p, Vec_Int_t * vArray ); extern void Wlc_NtkPrintNodes( Wlc_Ntk_t * p, int Type ); extern void Wlc_NtkPrintStats( Wlc_Ntk_t * p, int fDistrib, int fVerbose ); extern Wlc_Ntk_t * Wlc_NtkDupDfs( Wlc_Ntk_t * p ); @@ -287,6 +291,8 @@ extern void Wlc_NtkDeleteSim( Vec_Ptr_t * p ); extern int Wlc_StdinProcessSmt( Abc_Frame_t * pAbc, char * pCmd ); /*=== wlcReadVer.c ========================================================*/ extern Wlc_Ntk_t * Wlc_ReadVer( char * pFileName, char * pStr ); +/*=== wlcWin.c =============================================================*/ +extern void Wlc_WinProfileArith( Wlc_Ntk_t * p ); /*=== wlcWriteVer.c ========================================================*/ extern void Wlc_WriteVer( Wlc_Ntk_t * p, char * pFileName, int fAddCos, int fNoFlops ); diff --git a/src/base/wlc/wlcCom.c b/src/base/wlc/wlcCom.c index 7856fae8..f3eb6dd7 100644 --- a/src/base/wlc/wlcCom.c +++ b/src/base/wlc/wlcCom.c @@ -34,6 +34,7 @@ static int Abc_CommandPs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBlast ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPsInv ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandGetInv ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandProfile ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); static inline Wlc_Ntk_t * Wlc_AbcGetNtk( Abc_Frame_t * pAbc ) { return (Wlc_Ntk_t *)pAbc->pAbcWlc; } @@ -67,6 +68,7 @@ void Wlc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Word level", "%blast", Abc_CommandBlast, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%psinv", Abc_CommandPsInv, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%getinv", Abc_CommandGetInv, 0 ); + Cmd_CommandAdd( pAbc, "Word level", "%profile", Abc_CommandProfile, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%test", Abc_CommandTest, 0 ); } @@ -543,6 +545,50 @@ int Abc_CommandGetInv( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Abc_CommandProfile( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc); + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( 1, "Abc_CommandProfile(): There is no current design.\n" ); + return 0; + } + Wlc_WinProfileArith( pNtk ); + return 0; +usage: + Abc_Print( -2, "usage: %%profile [-vh]\n" ); + Abc_Print( -2, "\t profiles arithmetic components in the word-level networks\n" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function******************************************************************** Synopsis [] @@ -575,7 +621,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) } if ( pNtk == NULL ) { - Abc_Print( 1, "Abc_CommandBlast(): There is no current design.\n" ); + Abc_Print( 1, "Abc_CommandTest(): There is no current design.\n" ); return 0; } // transform diff --git a/src/base/wlc/wlcNtk.c b/src/base/wlc/wlcNtk.c index 5a08cd99..6f396771 100644 --- a/src/base/wlc/wlcNtk.c +++ b/src/base/wlc/wlcNtk.c @@ -44,8 +44,8 @@ static char * Wlc_Names[WLC_OBJ_NUMBER+1] = { ">>>", // 10: shift right (arithmetic) "<<", // 11: shift left "<<<", // 12: shift left (arithmetic) - "rotateR", // 13: rotate right - "rotateL", // 14: rotate left + "rotR", // 13: rotate right + "rotL", // 14: rotate left "~", // 15: bitwise NOT "&", // 16: bitwise AND "|", // 17: bitwise OR @@ -55,8 +55,8 @@ static char * Wlc_Names[WLC_OBJ_NUMBER+1] = { "~^", // 21: bitwise NXOR "[:]", // 22: bit selection "{,}", // 23: bit concatenation - "zeroPad", // 24: zero padding - "signExt", // 25: sign extension + "zPad", // 24: zero padding + "sExt", // 25: sign extension "!", // 26: logic NOT "=>", // 27: logic implication "&&", // 28: logic AND @@ -83,7 +83,7 @@ static char * Wlc_Names[WLC_OBJ_NUMBER+1] = { "**", // 49: arithmetic power "-", // 50: arithmetic minus "sqrt", // 51: integer square root - "square", // 52: integer square + "squar", // 52: integer square "table", // 53: bit table NULL // 54: unused }; @@ -471,6 +471,57 @@ void Wlc_NtkPrintDistrib( Wlc_Ntk_t * p, int fVerbose ) Vec_VecFree( (Vec_Vec_t *)vOccurs ); Vec_IntFree( vAnds ); } +void Wlc_NtkPrintNode( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ) +{ + printf( "%8d : ", Wlc_ObjId(p, pObj) ); + printf( "%3d%s", Wlc_ObjRange(pObj), Wlc_ObjIsSigned(pObj) ? "s" : " " ); + if ( pObj->Type == WLC_OBJ_CONST ) + printf( " " ); + else + { + printf( " = %3d%s %5s ", Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Wlc_ObjIsSigned(Wlc_ObjFanin0(p, pObj)) ? "s" : " ", Wlc_Names[(int)pObj->Type] ); + if ( Wlc_ObjFaninNum(pObj) > 1 ) + printf( "%3d%s ", Wlc_ObjRange(Wlc_ObjFanin1(p, pObj)), Wlc_ObjIsSigned(Wlc_ObjFanin1(p, pObj)) ? "s" : " " ); + else + printf( " " ); + if ( Wlc_ObjFaninNum(pObj) > 2 ) + printf( "%3d%s ", Wlc_ObjRange(Wlc_ObjFanin2(p, pObj)), Wlc_ObjIsSigned(Wlc_ObjFanin2(p, pObj)) ? "s" : " " ); + else + printf( " " ); + } + printf( " : " ); + printf( "%-12s", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) ); + if ( pObj->Type == WLC_OBJ_CONST ) + { + printf( " = %d\'%sh", Wlc_ObjRange(pObj), Wlc_ObjIsSigned(pObj) ? "s":"" ); + if ( pObj->fXConst ) + { + int k; + for ( k = 0; k < (Wlc_ObjRange(pObj) + 3) / 4; k++ ) + printf( "x" ); + } + else + Abc_TtPrintHexArrayRev( stdout, (word *)Wlc_ObjConstValue(pObj), (Wlc_ObjRange(pObj) + 3) / 4 ); + } + else + { + printf( " = %-12s %5s ", Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)), Wlc_Names[(int)pObj->Type] ); + if ( Wlc_ObjFaninNum(pObj) > 1 ) + printf( "%-12s ", Wlc_ObjName(p, Wlc_ObjFaninId1(pObj)) ); + else + printf( " " ); + if ( Wlc_ObjFaninNum(pObj) > 2 ) + printf( "%-12s ", Wlc_ObjName(p, Wlc_ObjFaninId2(pObj)) ); + } + printf( "\n" ); +} +void Wlc_NtkPrintNodeArray( Wlc_Ntk_t * p, Vec_Int_t * vArray ) +{ + Wlc_Obj_t * pObj; + int i; + Wlc_NtkForEachObjVec( vArray, p, pObj, i ) + Wlc_NtkPrintNode( p, pObj ); +} void Wlc_NtkPrintNodes( Wlc_Ntk_t * p, int Type ) { Wlc_Obj_t * pObj; @@ -480,16 +531,8 @@ void Wlc_NtkPrintNodes( Wlc_Ntk_t * p, int Type ) { if ( (int)pObj->Type != Type ) continue; - printf( "%8d :", Counter++ ); - printf( "%8d : ", i ); - printf( "%3d%s = ", Wlc_ObjRange(pObj), Wlc_ObjIsSigned(pObj) ? "s" : " " ); - printf( "%3d%s %s ", Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Wlc_ObjIsSigned(Wlc_ObjFanin0(p, pObj)) ? "s" : " ", Wlc_Names[Type] ); - printf( "%3d%s ", Wlc_ObjRange(Wlc_ObjFanin1(p, pObj)), Wlc_ObjIsSigned(Wlc_ObjFanin1(p, pObj)) ? "s" : " " ); - printf( " : " ); - printf( "%-12s = ", Wlc_ObjName(p, i) ); - printf( "%-12s %s ", Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)), Wlc_Names[Type] ); - printf( "%-12s ", Wlc_ObjName(p, Wlc_ObjFaninId1(pObj)) ); - printf( "\n" ); + printf( "%8d :", Counter++ ); + Wlc_NtkPrintNode( p, pObj ); } } void Wlc_NtkPrintStats( Wlc_Ntk_t * p, int fDistrib, int fVerbose ) diff --git a/src/base/wlc/wlcWin.c b/src/base/wlc/wlcWin.c new file mode 100644 index 00000000..4dc748f4 --- /dev/null +++ b/src/base/wlc/wlcWin.c @@ -0,0 +1,166 @@ +/**CFile**************************************************************** + + FileName [wlcWin.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Parses several flavors of word-level Verilog.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 22, 2014.] + + Revision [$Id: wlcWin.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "wlc.h" +#include "base/abc/abc.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collect arithmetic nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Wlc_ObjIsArithm( Wlc_Obj_t * pObj ) +{ + return pObj->Type == WLC_OBJ_CONST || + pObj->Type == WLC_OBJ_BUF || pObj->Type == WLC_OBJ_BIT_NOT || + pObj->Type == WLC_OBJ_BIT_ZEROPAD || pObj->Type == WLC_OBJ_BIT_SIGNEXT || +// pObj->Type == WLC_OBJ_BIT_SELECT || pObj->Type == WLC_OBJ_BIT_CONCAT || + pObj->Type == WLC_OBJ_ARI_ADD || pObj->Type == WLC_OBJ_ARI_SUB || + pObj->Type == WLC_OBJ_ARI_MULTI || pObj->Type == WLC_OBJ_ARI_MINUS; +} +int Wlc_ObjIsArithmReal( Wlc_Obj_t * pObj ) +{ + return pObj->Type == WLC_OBJ_BIT_NOT || + pObj->Type == WLC_OBJ_ARI_ADD || pObj->Type == WLC_OBJ_ARI_SUB || + pObj->Type == WLC_OBJ_ARI_MULTI || pObj->Type == WLC_OBJ_ARI_MINUS; +} +int Wlc_ManCountArithmReal( Wlc_Ntk_t * p, Vec_Int_t * vNodes ) +{ + Wlc_Obj_t * pObj; + int i, Counter = 0; + Wlc_NtkForEachObjVec( vNodes, p, pObj, i ) + Counter += Wlc_ObjIsArithmReal( pObj ); + return Counter; +} +int Wlc_ObjHasArithm_rec( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ) +{ + if ( pObj->Type == WLC_OBJ_CONST ) + return 0; + if ( pObj->Type == WLC_OBJ_BUF || pObj->Type == WLC_OBJ_BIT_NOT || + pObj->Type == WLC_OBJ_BIT_ZEROPAD || pObj->Type == WLC_OBJ_BIT_SIGNEXT ) + return Wlc_ObjHasArithm_rec( p, Wlc_ObjFanin0(p, pObj) ); + return pObj->Type == WLC_OBJ_ARI_ADD || pObj->Type == WLC_OBJ_ARI_SUB || + pObj->Type == WLC_OBJ_ARI_MULTI || pObj->Type == WLC_OBJ_ARI_MINUS; +} +int Wlc_ObjHasArithmFanins( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ) +{ + Wlc_Obj_t * pFanin; int i; + assert( !Wlc_ObjHasArithm_rec(p, pObj) ); + Wlc_ObjForEachFaninObj( p, pObj, pFanin, i ) + if ( Wlc_ObjHasArithm_rec(p, pFanin) ) + return 1; + return 0; +} +void Wlc_WinCompute_rec( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ) +{ + Wlc_Obj_t * pFanin; int i; + if ( pObj->Mark ) + return; + pObj->Mark = 1; + if ( !Wlc_ObjIsArithm(pObj) ) + { + Vec_IntPush( vLeaves, Wlc_ObjId(p, pObj) ); + return; + } + Wlc_ObjForEachFaninObj( p, pObj, pFanin, i ) + Wlc_WinCompute_rec( p, pFanin, vLeaves, vNodes ); + Vec_IntPush( vNodes, Wlc_ObjId(p, pObj) ); +} +void Wlc_WinCleanMark_rec( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ) +{ + Wlc_Obj_t * pFanin; int i; + if ( !pObj->Mark ) + return; + pObj->Mark = 0; + Wlc_ObjForEachFaninObj( p, pObj, pFanin, i ) + Wlc_WinCleanMark_rec( p, pFanin ); +} +void Wlc_WinCompute( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ) +{ + Vec_IntClear( vLeaves ); + Vec_IntClear( vNodes ); + if ( Wlc_ObjHasArithm_rec(p, pObj) ) + { + Wlc_WinCompute_rec( p, pObj, vLeaves, vNodes ); + Wlc_WinCleanMark_rec( p, pObj ); + } + else if ( Wlc_ObjHasArithmFanins(p, pObj) ) + { + Wlc_Obj_t * pFanin; int i; + Wlc_ObjForEachFaninObj( p, pObj, pFanin, i ) + if ( Wlc_ObjHasArithm_rec(p, pFanin) ) + Wlc_WinCompute_rec( p, pFanin, vLeaves, vNodes ); + Wlc_ObjForEachFaninObj( p, pObj, pFanin, i ) + if ( Wlc_ObjHasArithm_rec(p, pFanin) ) + Wlc_WinCleanMark_rec( p, pFanin ); + } + else assert( 0 ); +} +void Wlc_WinProfileArith( Wlc_Ntk_t * p ) +{ + Vec_Int_t * vLeaves = Vec_IntAlloc( 1000 ); + Vec_Int_t * vNodes = Vec_IntAlloc( 1000 ); + Wlc_Obj_t * pObj; int i, Count = 0; + Wlc_NtkForEachObj( p, pObj, i ) + pObj->Mark = 0; + Wlc_NtkForEachObj( p, pObj, i ) + if ( Wlc_ObjHasArithm_rec(p, pObj) ? Wlc_ObjIsCo(pObj) : Wlc_ObjHasArithmFanins(p, pObj) ) + { + Wlc_WinCompute( p, pObj, vLeaves, vNodes ); + if ( Wlc_ManCountArithmReal(p, vNodes) < 2 ) + continue; + + printf( "Arithmetic cone of node %d (%s):\n", Wlc_ObjId(p, pObj), Wlc_ObjName(p, Wlc_ObjId(p, pObj)) ); + Wlc_NtkPrintNode( p, pObj ); + Vec_IntReverseOrder( vNodes ); + Wlc_NtkPrintNodeArray( p, vNodes ); + printf( "\n" ); + Count++; + } + Wlc_NtkForEachObj( p, pObj, i ) + assert( pObj->Mark == 0 ); + printf( "Finished printing %d arithmetic cones.\n", Count ); + Vec_IntFree( vLeaves ); + Vec_IntFree( vNodes ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + -- cgit v1.2.3 From 53adc97675511f41fd9c40c31dcb9b3506f75daf Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 27 Nov 2016 11:56:40 -0800 Subject: New SAT-based optimization package. --- src/opt/sbd/sbdCore.c | 93 ++++++++++----- src/opt/sbd/sbdSim.c | 310 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 376 insertions(+), 27 deletions(-) create mode 100644 src/opt/sbd/sbdSim.c (limited to 'src') diff --git a/src/opt/sbd/sbdCore.c b/src/opt/sbd/sbdCore.c index 2120a8f9..6b311e01 100644 --- a/src/opt/sbd/sbdCore.c +++ b/src/opt/sbd/sbdCore.c @@ -48,6 +48,7 @@ struct Sbd_Man_t_ Vec_Int_t * vTfo; // TFO (excludes node, includes roots) Vec_Int_t * vLeaves; // leaves (TFI leaves + extended leaves) Vec_Int_t * vTfi; // TFI (TFI + node + extended TFI) + Vec_Int_t * vDivs; // divisors Vec_Int_t * vCounts[2]; // counters of zeros and ones }; @@ -76,7 +77,7 @@ void Sbd_ParSetDefault( Sbd_Par_t * pPars ) { memset( pPars, 0, sizeof(Sbd_Par_t) ); pPars->nLutSize = 4; // target LUT size - pPars->nTfoLevels = 4; // the number of TFO levels (windowing) + pPars->nTfoLevels = 3; // 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 @@ -102,6 +103,7 @@ 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 ); @@ -112,13 +114,15 @@ Vec_Wec_t * Sbd_ManWindowRoots( Gia_Man_t * p, int nTfoLevels, int nTfoFanMax ) Vec_IntGrow( vNodes, 1 ); Vec_IntPush( vNodes, Id ); } + Gia_ManForEachCoDriverId( p, Id, i ) + Vec_BitWriteEntry( vPoDrivers, Id, 1 ); Gia_ManForEachAndId( p, Id ) { - int fAlwaysRoot = Gia_ObjRefNumId(p, Id) >= nTfoFanMax; + 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( vNodes, vNodes0, vNodes1 ); + Vec_IntTwoMerge2( vNodes0, vNodes1, vNodes ); k2 = 0; Vec_IntForEachEntry( vNodes, Fan, k ) { @@ -127,10 +131,16 @@ Vec_Wec_t * Sbd_ManWindowRoots( Gia_Man_t * p, int nTfoLevels, int nTfoFanMax ) if ( !fRoot ) Vec_IntWriteEntry( vNodes, k2++, Fan ); } Vec_IntShrink( vNodes, k2 ); - Vec_IntPush( vNodes, Id ); + if ( fAlwaysRoot ) + Vec_WecPush( vTfos, Id, Abc_Var2Lit(Id, 1) ); + else + Vec_IntPush( vNodes, Id ); } Vec_WecFree( vTemp ); + Vec_BitFree( vPoDrivers ); + // print the results + if ( 1 ) Vec_WecForEachLevel( vTfos, vNodes, i ) { if ( !Gia_ObjIsAnd(Gia_ManObj(p, i)) ) @@ -139,8 +149,8 @@ Vec_Wec_t * Sbd_ManWindowRoots( Gia_Man_t * p, int nTfoLevels, int nTfoFanMax ) Vec_IntForEachEntry( vNodes, Fan, k ) printf( "%d%s ", Abc_Lit2Var(Fan), Abc_LitIsCompl(Fan)? "*":"" ); printf( "\n" ); - } + return vTfos; } @@ -171,6 +181,7 @@ Sbd_Man_t * Sbd_ManStart( Gia_Man_t * pGia, Sbd_Par_t * pPars ) p->vCover = Vec_IntStart( 100 ); p->vLeaves = Vec_IntAlloc( Gia_ManCiNum(pGia) ); p->vTfi = Vec_IntAlloc( Gia_ManAndNum(pGia) ); + p->vDivs = Vec_IntAlloc( Gia_ManObjNum(pGia) ); p->vCounts[0] = Vec_IntAlloc( 100 ); p->vCounts[1] = Vec_IntAlloc( 100 ); // start input cuts @@ -199,8 +210,10 @@ void Sbd_ManStop( Sbd_Man_t * p ) Vec_IntFree( p->vCover ); Vec_IntFree( p->vLeaves ); Vec_IntFree( p->vTfi ); + Vec_IntFree( p->vDivs ); Vec_IntFree( p->vCounts[0] ); Vec_IntFree( p->vCounts[1] ); + ABC_FREE( p ); } @@ -234,20 +247,38 @@ void Sbd_ManWindowSim_rec( Sbd_Man_t * p, int Node ) Sbd_ManWindowSim_rec( p, Gia_ObjFaninId1(pObj, Node) ); Vec_IntPush( p->vTfi, Node ); // simulate - 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_ObjFanin0(pObj)->fMark0 ? Sbd_ObjSim1(p, Gia_ObjFaninId0(pObj, Node)) : Sbd_ObjSim0(p, Gia_ObjFaninId1(pObj, Node)), Gia_ObjFaninC1(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 ); + } } void Sbd_ManPropagateControl( Sbd_Man_t * p, int Node ) { - int iObj0 = Gia_ObjFaninId0(Gia_ManObj(p->pGia, Node), Node); - int iObj1 = Gia_ObjFaninId1(Gia_ManObj(p->pGia, Node), Node); + Gia_Obj_t * pNode = Gia_ManObj(p->pGia, Node); + int iObj0 = Gia_ObjFaninId0(pNode, Node); + int iObj1 = Gia_ObjFaninId1(pNode, Node); word * pCtrl = Sbd_ObjSim2(p, Node); word * pCtrl0 = Sbd_ObjSim2(p, iObj0); word * pCtrl1 = Sbd_ObjSim2(p, iObj1); @@ -255,10 +286,13 @@ void Sbd_ManPropagateControl( Sbd_Man_t * p, int Node ) word * pSims0 = Sbd_ObjSim0(p, iObj0); word * pSims1 = Sbd_ObjSim0(p, iObj1); int w; +// printf( "Node %2d : %d %d\n", Node, (int)(pSims[0] & 1), (int)(pCtrl[0] & 1) ); for ( w = 0; w < p->pPars->nWords; w++ ) { - pCtrl0[w] = pCtrl[w] & (pSims[w] | pSims1[w]); - pCtrl1[w] = pCtrl[w] & (pSims[w] | pSims0[w] | (~pSims0[w] & ~pSims1[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); } } void Sbd_ManWindow( Sbd_Man_t * p, int Pivot ) @@ -269,11 +303,14 @@ void Sbd_ManWindow( Sbd_Man_t * p, int Pivot ) p->vTfo = Vec_WecEntry( p->vTfos, Pivot ); Vec_IntClear( p->vLeaves ); Vec_IntClear( p->vTfi ); + Vec_IntClear( p->vDivs ); // simulate TFI cone Gia_ManIncrementTravId( p->pGia ); Sbd_ManWindowSim_rec( p, Pivot ); p->nTfiLeaves = Vec_IntSize( p->vLeaves ); p->nTfiNodes = Vec_IntSize( p->vTfi ); + Vec_IntAppend( p->vDivs, p->vLeaves ); + Vec_IntAppend( p->vDivs, p->vTfi ); // simulate node Gia_ManObj(p->pGia, Pivot)->fMark0 = 1; Abc_TtCopy( Sbd_ObjSim1(p, Pivot), Sbd_ObjSim0(p, Pivot), p->pPars->nWords, 1 ); @@ -282,7 +319,7 @@ void Sbd_ManWindow( Sbd_Man_t * p, int Pivot ) { Gia_ManObj(p->pGia, Abc_Lit2Var(Node))->fMark0 = 1; if ( Abc_LitIsCompl(Node) ) - Sbd_ManWindowSim_rec( p, Node ); + Sbd_ManWindowSim_rec( p, Abc_Lit2Var(Node) ); } // remove marks Gia_ManObj(p->pGia, Pivot)->fMark0 = 0; @@ -292,9 +329,9 @@ void Sbd_ManWindow( Sbd_Man_t * p, int Pivot ) 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, Node), Sbd_ObjSim1(p, Node), p->pPars->nWords ); - // propagate controlability to TFI - for ( i = p->nTfiNodes; i >= 0 && (Node = Vec_IntEntry(p->vTfi, i)); i-- ) + Abc_TtOrXor( Sbd_ObjSim2(p, Pivot), Sbd_ObjSim0(p, Abc_Lit2Var(Node)), Sbd_ObjSim1(p, Abc_Lit2Var(Node)), p->pPars->nWords ); + // propagate controlability to fanins for the TFI nodes starting from the pivot + for ( i = p->nTfiLeaves + p->nTfiNodes - 1; i >= p->nTfiLeaves && ((Node = Vec_IntEntry(p->vDivs, i)), 1); i-- ) Sbd_ManPropagateControl( p, Node ); } @@ -319,11 +356,11 @@ void Sbd_ManPrintObj( Sbd_Man_t * p, int Pivot ) for ( k = 0; k < p->pPars->nWords * 64; k++ ) { printf( "%3d : ", k ); - Vec_IntForEachEntry( p->vTfi, Id, i ) + Vec_IntForEachEntry( p->vDivs, Id, i ) { word * pSims = Sbd_ObjSim0( p, Id ); word * pCtrl = Sbd_ObjSim2( p, Id ); - if ( i == Vec_IntSize(p->vTfi)-1 ) + if ( i == Vec_IntSize(p->vDivs)-1 ) { if ( Abc_TtGetBit(pCtrl, k) ) Vec_IntPush( p->vCounts[Abc_TtGetBit(pSims, k)], k ); @@ -335,15 +372,15 @@ void Sbd_ManPrintObj( Sbd_Man_t * p, int Pivot ) } // covering table printf( "Exploring %d x %d covering table.\n", Vec_IntSize(p->vCounts[0]), Vec_IntSize(p->vCounts[1]) ); - Vec_IntForEachEntry( p->vCounts[0], Bit0, k0 ) - Vec_IntForEachEntry( p->vCounts[1], Bit1, k1 ) + Vec_IntForEachEntryStop( p->vCounts[0], Bit0, k0, 5 ) + Vec_IntForEachEntryStop( p->vCounts[1], Bit1, k1, 5 ) { printf( "%3d %3d : ", Bit0, Bit1 ); - Vec_IntForEachEntry( p->vTfi, Id, i ) + Vec_IntForEachEntry( p->vDivs, Id, i ) { word * pSims = Sbd_ObjSim0( p, Id ); word * pCtrl = Sbd_ObjSim2( p, Id ); - if ( i == Vec_IntSize(p->vTfi)-1 ) + if ( i == Vec_IntSize(p->vDivs)-1 ) printf( " " ); printf( "%c", (Abc_TtGetBit(pCtrl, Bit0) && Abc_TtGetBit(pCtrl, Bit1) && Abc_TtGetBit(pSims, Bit0) != Abc_TtGetBit(pSims, Bit1)) ? '1' : '.' ); } @@ -512,9 +549,11 @@ Gia_Man_t * Sbd_NtkPerform( Gia_Man_t * pGia, Sbd_Par_t * pPars ) { if ( Sbd_ManComputeCut( p, Pivot ) ) continue; + printf( "Looking at node %d\n", Pivot ); Sbd_ManWindow( p, Pivot ); if ( Sbd_ManExplore( p, Pivot, pCut, &Truth ) ) Sbd_ManImplement( p, Pivot, pCut, Truth ); + break; } pNew = Sbd_ManDerive( pGia, p->vMirrors ); Sbd_ManStop( p ); 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 + -- cgit v1.2.3 From 5d61e53c7a09d544e4cdbb74e31fc919680f0e4e Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 28 Nov 2016 15:50:15 -0800 Subject: New SAT-based optimization package. --- src/opt/dau/dauGia.c | 42 ++++-- src/opt/sbd/sbdCore.c | 377 +++++++++++++++++++++++++++++++++++++++++--------- src/opt/sbd/sbdInt.h | 2 + src/opt/sbd/sbdWin.c | 151 +++++++++++++++++++- 4 files changed, 491 insertions(+), 81 deletions(-) (limited to 'src') diff --git a/src/opt/dau/dauGia.c b/src/opt/dau/dauGia.c index b75ded61..c7f5c11f 100644 --- a/src/opt/dau/dauGia.c +++ b/src/opt/dau/dauGia.c @@ -238,12 +238,24 @@ 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 ) + iFan = Gia_ManAppendXorReal( pGia, iFan0, iFan1 ); + 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,10 +352,20 @@ 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) ) { @@ -377,7 +399,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++ ) diff --git a/src/opt/sbd/sbdCore.c b/src/opt/sbd/sbdCore.c index 6b311e01..d83ed231 100644 --- a/src/opt/sbd/sbdCore.c +++ b/src/opt/sbd/sbdCore.c @@ -39,17 +39,21 @@ struct Sbd_Man_t_ 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[3]; // simulation information (main, backup, controlability) + Vec_Wrd_t * vSims[4]; // simulation information (main, backup, controlability) Vec_Int_t * vCover; // temporary + Vec_Int_t * vLits; // temporary // target node int Pivot; // target node - int nTfiLeaves; // TFI leaves - int nTfiNodes; // TFI nodes - Vec_Int_t * vTfo; // TFO (excludes node, includes roots) - Vec_Int_t * vLeaves; // leaves (TFI leaves + extended leaves) - Vec_Int_t * vTfi; // TFI (TFI + node + extended TFI) - Vec_Int_t * vDivs; // divisors + 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 ); } @@ -57,6 +61,7 @@ static inline int * Sbd_ObjCut( Sbd_Man_t * p, int i ) { return Vec_IntEntryP( 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 /// @@ -89,9 +94,11 @@ void Sbd_ParSetDefault( Sbd_Par_t * pPars ) /**Function************************************************************* - Synopsis [Computes window roots for all nodes.] + Synopsis [Computes TFO and window roots for all nodes.] - Description [] + 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 [] @@ -131,9 +138,7 @@ Vec_Wec_t * Sbd_ManWindowRoots( Gia_Man_t * p, int nTfoLevels, int nTfoFanMax ) if ( !fRoot ) Vec_IntWriteEntry( vNodes, k2++, Fan ); } Vec_IntShrink( vNodes, k2 ); - if ( fAlwaysRoot ) - Vec_WecPush( vTfos, Id, Abc_Var2Lit(Id, 1) ); - else + if ( !fAlwaysRoot ) Vec_IntPush( vNodes, Id ); } Vec_WecFree( vTemp ); @@ -175,15 +180,20 @@ Sbd_Man_t * Sbd_ManStart( Gia_Man_t * pGia, Sbd_Par_t * pPars ) 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 < 3; i++ ) + for ( i = 0; i < 4; i++ ) p->vSims[i] = Vec_WrdStart( Gia_ManObjNum(pGia) * p->pPars->nWords ); // target node - p->vCover = Vec_IntStart( 100 ); - p->vLeaves = Vec_IntAlloc( Gia_ManCiNum(pGia) ); - p->vTfi = Vec_IntAlloc( Gia_ManAndNum(pGia) ); - p->vDivs = Vec_IntAlloc( Gia_ManObjNum(pGia) ); + 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 ) { @@ -205,14 +215,20 @@ void Sbd_ManStop( Sbd_Man_t * p ) Vec_IntFree( p->vLutLevs ); Vec_IntFree( p->vLutCuts ); Vec_IntFree( p->vMirrors ); - for ( i = 0; i < 3; i++ ) + for ( i = 0; i < 4; i++ ) Vec_WrdFree( p->vSims[i] ); - Vec_IntFree( p->vCover ); - Vec_IntFree( p->vLeaves ); - Vec_IntFree( p->vTfi ); - Vec_IntFree( p->vDivs ); + 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 ); } @@ -237,16 +253,20 @@ void Sbd_ManWindowSim_rec( Sbd_Man_t * p, int Node ) return; Gia_ObjSetTravIdCurrentId(p->pGia, Node); pObj = Gia_ManObj( p->pGia, Node ); - if ( Gia_ObjIsCi(pObj) ) + if ( Gia_ObjIsAnd(pObj) ) { - Vec_IntPush( p->vLeaves, Node ); - return; + Sbd_ManWindowSim_rec( p, Gia_ObjFaninId0(pObj, Node) ); + Sbd_ManWindowSim_rec( p, Gia_ObjFaninId1(pObj, Node) ); } - assert( Gia_ObjIsAnd(pObj) ); - Sbd_ManWindowSim_rec( p, Gia_ObjFaninId0(pObj, Node) ); - Sbd_ManWindowSim_rec( p, Gia_ObjFaninId1(pObj, Node) ); - Vec_IntPush( p->vTfi, 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), @@ -254,6 +274,7 @@ void Sbd_ManWindowSim_rec( Sbd_Man_t * p, int 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)), @@ -267,6 +288,7 @@ void Sbd_ManWindowSim_rec( Sbd_Man_t * p, int 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), @@ -279,20 +301,57 @@ void Sbd_ManPropagateControl( Sbd_Man_t * p, int Node ) Gia_Obj_t * pNode = Gia_ManObj(p->pGia, Node); int iObj0 = Gia_ObjFaninId0(pNode, Node); int iObj1 = Gia_ObjFaninId1(pNode, Node); - word * pCtrl = Sbd_ObjSim2(p, Node); - word * pCtrl0 = Sbd_ObjSim2(p, iObj0); - word * pCtrl1 = Sbd_ObjSim2(p, iObj1); + word * pSims = Sbd_ObjSim0(p, Node); word * pSims0 = Sbd_ObjSim0(p, iObj0); word * pSims1 = Sbd_ObjSim0(p, iObj1); - int w; + + 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); + // printf( "Node %2d : %d %d\n", Node, (int)(pSims[0] & 1), (int)(pCtrl[0] & 1) ); + int w; 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); + + pDtrl0[w] = pDtrl[w] & (pSims[w] | Sim1); + pDtrl1[w] = pDtrl[w] & (pSims[w] | Sim0 | (~Sim0 & ~Sim1)); + } +} +void Sbd_ManUpdateOrder( Sbd_Man_t * p, int Pivot ) +{ + int i, k, Node; + Vec_Int_t * vLevel; + // 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 ); + } + // detect useful divisors + if ( i == LevelMax - 2 ) + Vec_IntFill( p->vDivValues, Vec_IntSize(p->vWinObjs), 0 ); } } void Sbd_ManWindow( Sbd_Man_t * p, int Pivot ) @@ -301,38 +360,45 @@ void Sbd_ManWindow( Sbd_Man_t * p, int Pivot ) // assign pivot and TFO (assume siminfo is assigned at the PIs) p->Pivot = Pivot; p->vTfo = Vec_WecEntry( p->vTfos, Pivot ); - Vec_IntClear( p->vLeaves ); - Vec_IntClear( p->vTfi ); - Vec_IntClear( p->vDivs ); // simulate TFI cone + Vec_IntClear( p->vWinObjs ); Gia_ManIncrementTravId( p->pGia ); Sbd_ManWindowSim_rec( p, Pivot ); - p->nTfiLeaves = Vec_IntSize( p->vLeaves ); - p->nTfiNodes = Vec_IntSize( p->vTfi ); - Vec_IntAppend( p->vDivs, p->vLeaves ); - Vec_IntAppend( p->vDivs, p->vTfi ); + 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 ); - // simulate extended TFI cone + // 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) ) - Sbd_ManWindowSim_rec( p, Abc_Lit2Var(Node) ); + if ( !Abc_LitIsCompl(Node) ) + continue; + Sbd_ManWindowSim_rec( p, Abc_Lit2Var(Node) ); + Vec_IntPush( p->vRoots, Abc_Lit2Var(Node) ); } - // remove marks + // 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 - Abc_TtClear( Sbd_ObjSim2(p, Pivot), p->pPars->nWords ); + 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 ); + Abc_TtCopy( Sbd_ObjSim3(p, Pivot), Sbd_ObjSim2(p, Pivot), p->pPars->nWords, 0 ); // propagate controlability to fanins for the TFI nodes starting from the pivot - for ( i = p->nTfiLeaves + p->nTfiNodes - 1; i >= p->nTfiLeaves && ((Node = Vec_IntEntry(p->vDivs, i)), 1); i-- ) - Sbd_ManPropagateControl( p, Node ); + 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_ManPropagateControl( p, Node ); } /**Function************************************************************* @@ -348,19 +414,89 @@ void Sbd_ManWindow( Sbd_Man_t * p, int Pivot ) ***********************************************************************/ 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( "%d : ", 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_IntForEachEntry( p->vDivs, Id, i ) + Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs ) { word * pSims = Sbd_ObjSim0( p, Id ); word * pCtrl = Sbd_ObjSim2( p, Id ); - if ( i == Vec_IntSize(p->vDivs)-1 ) + 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 ); @@ -369,28 +505,109 @@ void Sbd_ManPrintObj( Sbd_Man_t * p, int Pivot ) 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, 5 ) - Vec_IntForEachEntryStop( p->vCounts[1], Bit1, k1, 5 ) +/* + 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_IntForEachEntry( p->vDivs, Id, i ) + Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs ) { word * pSims = Sbd_ObjSim0( p, Id ); word * pCtrl = Sbd_ObjSim2( p, Id ); - if ( i == Vec_IntSize(p->vDivs)-1 ) + 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 ) ) + Extra_PrintBinary( stdout, (unsigned *)&Row, nDivs ), printf( "\n" ); + } + } -int Sbd_ManExplore( Sbd_Man_t * p, int Pivot, int * pCut, word * pTruth ) +int Sbd_ManExplore( Sbd_Man_t * p, int Pivot, word * pTruth ) { - Sbd_ManPrintObj( p, Pivot ); - return 0; + extern sat_solver * Sbd_ManSatSolver( sat_solver * pSat, Gia_Man_t * p, int Pivot, Vec_Int_t * vWinObjs, Vec_Int_t * vObj2Var, Vec_Int_t * vTfo, Vec_Int_t * vRoots ); + extern word Sbd_ManSolve( sat_solver * pSat, int PivotVar, int FreeVar, Vec_Int_t * vDivVars, Vec_Int_t * vValues, Vec_Int_t * vTemp ); + + int PivotVar = Vec_IntEntry(p->vObj2Var, Pivot); + int FreeVar = Vec_IntSize(p->vWinObjs) + Vec_IntSize(p->vTfo) + Vec_IntSize(p->vRoots); + int RetValue = 0; + +// Sbd_ManPrintObj( p, Pivot ); + Vec_IntPrint( p->vObj2Var ); + + Vec_IntClear( p->vDivVars ); + Vec_IntPush( p->vDivVars, 0 ); + Vec_IntPush( p->vDivVars, 1 ); + Vec_IntPush( p->vDivVars, 2 ); + Vec_IntPush( p->vDivVars, 4 ); + + p->pSat = Sbd_ManSatSolver( p->pSat, p->pGia, Pivot, p->vWinObjs, p->vObj2Var, p->vTfo, p->vRoots ); + *pTruth = Sbd_ManSolve( p->pSat, PivotVar, FreeVar, p->vDivVars, p->vDivValues, p->vLits ); + if ( *pTruth == SBD_SAT_UNDEC ) + printf( "Node %d: Undecided.\n", Pivot ); + else if ( *pTruth == SBD_SAT_SAT ) + { + int i; + printf( "Node %d: SAT.\n", Pivot ); + for ( i = 0; i < Vec_IntSize(p->vDivValues); i++ ) + printf( "%d", Vec_IntEntry(p->vDivValues, i) & 1 ); + printf( "\n" ); + for ( i = 0; i < Vec_IntSize(p->vDivValues); i++ ) + printf( "%d", Vec_IntEntry(p->vDivValues, i) >> 1 ); + printf( "\n" ); + } + else + { + printf( "Node %d: UNSAT.\n", Pivot ); + RetValue = 1; + } + + Extra_PrintBinary( stdout, (unsigned *)pTruth, 1 << Vec_IntSize(p->vDivVars) ), printf( "\n" ); + + return RetValue; } /**Function************************************************************* @@ -433,7 +650,7 @@ int Sbd_ManComputeCut( Sbd_Man_t * p, int 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 = Abc_MaxInt( Level0, Level1 ); + int LevMax = (Level0 || Level1) ? Abc_MaxInt(Level0, Level1) : 1; int * pCut0 = Sbd_ObjCut( p, iFan0 ); int * pCut1 = Sbd_ObjCut( p, iFan1 ); int Cut0[2] = {1, iFan0}, * pCut0Temp = Level0 < LevMax ? Cut0 : pCut0; @@ -452,25 +669,47 @@ int Sbd_ManComputeCut( Sbd_Man_t * p, int Node ) 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_ManImplement( Sbd_Man_t * p, int Pivot, int * pCut, word Truth ) +int Sbd_ManImplement( Sbd_Man_t * p, int Pivot, word Truth ) { - Vec_Int_t vLeaves = { pCut[0], pCut[0], pCut+1 }; - int iLit = Dsm_ManTruthToGia( p->pGia, &Truth, &vLeaves, p->vCover ); - int i, k, w, iObjLast = Gia_ManObjNum(p->pGia); + int i, k, w, iLit, Node; + int iObjLast = Gia_ManObjNum(p->pGia); + int iCurLev = Vec_IntEntry(p->vLutLevs, Pivot); + // 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 = (unsigned *)p; + // derive new function of the node + iLit = Dsm_ManTruthToGia( p->pGia, &Truth, p->vLits, p->vCover ); + p->pGia->pMuxes = NULL; + // remember this function assert( Vec_IntEntry(p->vMirrors, Pivot) == -1 ); Vec_IntWriteEntry( p->vMirrors, Pivot, iLit ); + // extend data-structure for new nodes assert( Vec_IntSize(p->vLutLevs) == iObjLast ); for ( i = iObjLast; i < Gia_ManObjNum(p->pGia); i++ ) { Vec_IntPush( p->vLutLevs, 0 ); Vec_IntFillExtra( p->vLutCuts, Vec_IntSize(p->vLutCuts) + p->pPars->nLutSize + 1, 0 ); Sbd_ManComputeCut( p, i ); - for ( k = 0; k < 3; k++ ) + for ( k = 0; k < 4; k++ ) for ( w = 0; w < p->pPars->nWords; w++ ) Vec_WrdPush( p->vSims[k], 0 ); } + // make sure delay reduction is achieved + assert( Vec_IntEntry(p->vLutLevs, Abc_Lit2Var(iLit)) < iCurLev ); return 0; } @@ -489,7 +728,7 @@ void Sbd_ManDerive_rec( Gia_Man_t * pNew, Gia_Man_t * p, int Node, Vec_Int_t * v { Gia_Obj_t * pObj; int Obj = Node; - if ( Vec_IntEntry(vMirrors, Node) >= 0 ) + if ( Node < Vec_IntSize(vMirrors) && Vec_IntEntry(vMirrors, Node) >= 0 ) Obj = Abc_Lit2Var( Vec_IntEntry(vMirrors, Node) ); pObj = Gia_ManObj( p, Obj ); if ( ~pObj->Value ) @@ -518,8 +757,8 @@ Gia_Man_t * Sbd_ManDerive( Gia_Man_t * p, Vec_Int_t * vMirrors ) Gia_ManHashAlloc( pNew ); Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); - Gia_ManForEachAndId( p, i ) - Sbd_ManDerive_rec( pNew, p, i, vMirrors ); + 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 ); @@ -541,9 +780,9 @@ Gia_Man_t * Sbd_ManDerive( Gia_Man_t * p, Vec_Int_t * vMirrors ) ***********************************************************************/ Gia_Man_t * Sbd_NtkPerform( Gia_Man_t * pGia, Sbd_Par_t * pPars ) { - Gia_Man_t * pNew; word Truth; + Gia_Man_t * pNew; Sbd_Man_t * p = Sbd_ManStart( pGia, pPars ); - int Pivot, pCut[2*SBD_MAX_LUTSIZE]; + int Pivot; word Truth = 0; assert( pPars->nLutSize <= 6 ); Gia_ManForEachAndId( pGia, Pivot ) { @@ -551,8 +790,8 @@ Gia_Man_t * Sbd_NtkPerform( Gia_Man_t * pGia, Sbd_Par_t * pPars ) continue; printf( "Looking at node %d\n", Pivot ); Sbd_ManWindow( p, Pivot ); - if ( Sbd_ManExplore( p, Pivot, pCut, &Truth ) ) - Sbd_ManImplement( p, Pivot, pCut, Truth ); + if ( Sbd_ManExplore( p, Pivot, &Truth ) ) + Sbd_ManImplement( p, Pivot, Truth ); break; } pNew = Sbd_ManDerive( pGia, p->vMirrors ); diff --git a/src/opt/sbd/sbdInt.h b/src/opt/sbd/sbdInt.h index 8211610c..4c553fb4 100644 --- a/src/opt/sbd/sbdInt.h +++ b/src/opt/sbd/sbdInt.h @@ -49,6 +49,8 @@ ABC_NAMESPACE_HEADER_START +#define SBD_SAT_UNDEC 0x1234567812345678 +#define SBD_SAT_SAT 0x8765432187654321 //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// diff --git a/src/opt/sbd/sbdWin.c b/src/opt/sbd/sbdWin.c index e8702f7d..8f320038 100644 --- a/src/opt/sbd/sbdWin.c +++ b/src/opt/sbd/sbdWin.c @@ -33,15 +33,162 @@ ABC_NAMESPACE_IMPL_START /**Function************************************************************* - Synopsis [] + 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, int Pivot, Vec_Int_t * vWinObjs, Vec_Int_t * vObj2Var, Vec_Int_t * vTfo, Vec_Int_t * vRoots ) +{ + Gia_Obj_t * pObj; + int i, iObj, Fan0, Fan1, Node, fCompl0, fCompl1, RetValue; + int PivotVar = Vec_IntEntry(vObj2Var, Pivot); + // 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 ); + // add clauses for all nodes + Vec_IntForEachEntry( vWinObjs, iObj, i ) + { + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + continue; + assert( Gia_ObjIsAnd(pObj) ); + Node = Vec_IntEntry( vObj2Var, iObj ); + Fan0 = Vec_IntEntry( vObj2Var, Gia_ObjFaninId0(pObj, iObj) ); + Fan1 = Vec_IntEntry( vObj2Var, Gia_ObjFaninId1(pObj, iObj) ); + fCompl0 = Gia_ObjFaninC0(pObj); + fCompl1 = Gia_ObjFaninC1(pObj); + 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, Vec_IntSize(vWinObjs) - Vec_IntSize(vTfo) ) + { + pObj = Gia_ManObj( p, iObj ); + assert( Gia_ObjIsAnd(pObj) ); + Node = Vec_IntEntry( vObj2Var, iObj ) + Vec_IntSize(vTfo); + Fan0 = Vec_IntEntry( vObj2Var, Gia_ObjFaninId0(pObj, iObj) ); + Fan1 = Vec_IntEntry( vObj2Var, Gia_ObjFaninId1(pObj, iObj) ); + Fan0 = Fan0 <= PivotVar ? Fan0 : Fan0 + Vec_IntSize(vTfo); + Fan1 = Fan1 <= PivotVar ? Fan1 : Fan1 + Vec_IntSize(vTfo); + fCompl0 = Gia_ObjFaninC0(pObj) ^ (Fan0 == PivotVar); + fCompl1 = Gia_ObjFaninC1(pObj) ^ (Fan1 == PivotVar); + 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 ) + { + Vec_IntPush( vFaninVars, Abc_Var2Lit(nVars, 0) ); + Node = Vec_IntEntry( vObj2Var, iObj ); + 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 ) + return 0; + 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 [] + 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; + pLits[0] = Abc_Var2Lit( PivotVar, 0 ); // F = 1 + pLits[1] = Abc_Var2Lit( FreeVar, 0 ); // iNewLit + assert( Vec_IntSize(vValues) <= sat_solver_nvars(pSat) ); + 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, 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, 2*sat_solver_var_value(pSat, i) ); + return SBD_SAT_SAT; +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// -- cgit v1.2.3 From 329cee498196f8751f5ca111ed786e3fc1211c86 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 30 Nov 2016 11:30:38 -0800 Subject: Small changes in handling arithmetic logic. --- src/base/wlc/wlcBlast.c | 11 ++++++++++- src/proof/acec/acecCo.c | 10 ++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/base/wlc/wlcBlast.c b/src/base/wlc/wlcBlast.c index c86c7cf0..ec3b040d 100644 --- a/src/base/wlc/wlcBlast.c +++ b/src/base/wlc/wlcBlast.c @@ -292,6 +292,10 @@ int Wlc_BlastLessSigned( Gia_Man_t * pNew, int * pArg0, int * pArg1, int nBits ) void Wlc_BlastFullAdder( Gia_Man_t * pNew, int a, int b, int c, int * pc, int * ps ) { int fUseXor = 0; + int fCompl = (a == 1 || b == 1 || c == 1); + // propagate complement through the FA - helps generate less redundant logic + if ( fCompl ) + a = Abc_LitNot(a), b = Abc_LitNot(b), c = Abc_LitNot(c); if ( fUseXor ) { int Xor = Gia_ManHashXor(pNew, a, b); @@ -310,6 +314,8 @@ void Wlc_BlastFullAdder( Gia_Man_t * pNew, int a, int b, int c, int * pc, int * *ps = Gia_ManHashAnd(pNew, Abc_LitNot(And2), Abc_LitNot(And2_)); *pc = Gia_ManHashOr (pNew, And1, And2); } + if ( fCompl ) + *ps = Abc_LitNot(*ps), *pc = Abc_LitNot(*pc); } void Wlc_BlastAdder( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits ) // result is in pAdd0 { @@ -412,6 +418,7 @@ void Wlc_BlastMultiplier( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, assert( fSigned == 0 || fSigned == 1 ); // prepare result Vec_IntFill( vRes, nArgA + nArgB, 0 ); + //Vec_IntFill( vRes, nArgA + nArgB + 1, 0 ); pRes = Vec_IntArray( vRes ); // prepare intermediate storage Vec_IntFill( vTemp, 2 * nArgA, 0 ); @@ -426,6 +433,7 @@ void Wlc_BlastMultiplier( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, pArgS[nArgA-1] = fSigned; for ( a = 0; a < nArgA; a++ ) Wlc_BlastFullAdderCtrl( pNew, 1, pArgC[a], pArgS[a], Carry, &Carry, &pRes[nArgB+a], 0 ); + //Vec_IntWriteEntry( vRes, nArgA + nArgB, Carry ); } void Wlc_BlastDivider( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes ) { @@ -804,7 +812,7 @@ void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int Vec_WecPush( vLevels, k, 0 ); } //Vec_WecPrint( vProds, 0 ); - + //printf( "Cutoff ID for partial products = %d.\n", Gia_ManObjNum(pNew) ); Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes ); Vec_WecFree( vProds ); @@ -1360,6 +1368,7 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int iOutput, in { pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManDupRemapLiterals( vBits, pTemp ); + //printf( "Cutoff ID %d became %d.\n", 75, Abc_Lit2Var(Gia_ManObj(pTemp, 73)->Value) ); Gia_ManStop( pTemp ); } // transform AIG with init state diff --git a/src/proof/acec/acecCo.c b/src/proof/acec/acecCo.c index 000f530a..1b73c36f 100644 --- a/src/proof/acec/acecCo.c +++ b/src/proof/acec/acecCo.c @@ -44,11 +44,14 @@ ABC_NAMESPACE_IMPL_START ***********************************************************************/ void Gia_PolynCoreNonXors_rec( Gia_Man_t * pGia, Gia_Obj_t * pObj, Vec_Int_t * vXorPairs ) { + extern int Gia_ManSuppSizeOne( Gia_Man_t * p, Gia_Obj_t * pObj ); Gia_Obj_t * pFan0, * pFan1; if ( !Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) return; Gia_PolynCoreNonXors_rec( pGia, Gia_Regular(pFan0), vXorPairs ); Gia_PolynCoreNonXors_rec( pGia, Gia_Regular(pFan1), vXorPairs ); + //if ( Gia_ManSuppSizeOne(pGia, pObj) > 4 ) + //if ( Gia_ObjId(pGia, pObj) >= 73 ) Vec_IntPushTwo( vXorPairs, Gia_ObjId(pGia, Gia_Regular(pFan0)), Gia_ObjId(pGia, Gia_Regular(pFan1)) ); } Vec_Int_t * Gia_PolynAddHaRoots( Gia_Man_t * pGia ) @@ -95,7 +98,7 @@ Vec_Int_t * Gia_PolynCoreOrder( Gia_Man_t * pGia, Vec_Int_t * vAdds, Vec_Int_t * Vec_Int_t * vLeaves = Vec_IntAlloc( 2 * Gia_ManCiNum(pGia) ); Vec_Wec_t * vMap = Vec_WecStart( Gia_ManObjNum(pGia) ); int i, k, Index, Driver, Entry1, Entry2 = -1; - // nodes driven by adders into adder indexes + // map nodes driven by adders into adder indexes for ( i = 0; 5*i < Vec_IntSize(vAdds); i++ ) { Entry1 = Vec_IntEntry( vAdds, 5*i + 3 ); @@ -318,8 +321,11 @@ Gia_Man_t * Gia_PolynCoreDetectTest_int( Gia_Man_t * pGia, Vec_Int_t * vAddCos, Vec_Int_t * vAdds = Ree_ManComputeCuts( pGia, 1 ); Vec_Int_t * vLeaves, * vRoots, * vOrder = Gia_PolynCoreOrder( pGia, vAdds, vAddCos, &vLeaves, &vRoots ); Vec_Int_t * vNodes = Gia_PolynCoreCollect( pGia, vAdds, vOrder ); + + //Gia_ManShow( pGia, vNodes, 0 ); + printf( "Detected %d FAs/HAs. Roots = %d. Leaves = %d. Nodes = %d. Adds = %d. ", - Vec_IntSize(vAdds), Vec_IntSize(vLeaves), Vec_IntSize(vRoots), Vec_IntSize(vNodes), Vec_IntSize(vOrder) ); + Vec_IntSize(vAdds)/5, Vec_IntSize(vLeaves), Vec_IntSize(vRoots), Vec_IntSize(vNodes), Vec_IntSize(vOrder) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Gia_PolynCorePrintCones( pGia, vLeaves, fVerbose ); -- cgit v1.2.3 From b3514ee7e000972ecb43603eb08bf56368c0d634 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 30 Nov 2016 12:07:08 -0800 Subject: Commenting out bailout in 'print_cex' when CEX has latches initialized to 1. --- src/base/io/io.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/base/io/io.c b/src/base/io/io.c index b181bc1d..093eccca 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -2378,6 +2378,7 @@ int IoCommandWriteCex( Abc_Frame_t * pAbc, int argc, char **argv ) Abc_Obj_t * pObj; FILE * pFile; int i, f; + /* Abc_NtkForEachLatch( pNtk, pObj, i ) if ( !Abc_LatchIsInit0(pObj) ) { @@ -2385,7 +2386,7 @@ int IoCommandWriteCex( Abc_Frame_t * pAbc, int argc, char **argv ) fprintf( stdout, "Run commands \"undc\" and \"zero\" and then rerun the equivalence check.\n" ); return 1; } - + */ pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { -- cgit v1.2.3 From 3b5527b620c943d84ee4ba38d969c114c042ae89 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 30 Nov 2016 20:56:43 -0800 Subject: New SAT-based optimization package. --- src/opt/sbd/sbdCore.c | 516 +++++++++++++++++++++++++++++++++++++++----------- src/opt/sbd/sbdWin.c | 91 +++++++-- 2 files changed, 485 insertions(+), 122 deletions(-) (limited to 'src') diff --git a/src/opt/sbd/sbdCore.c b/src/opt/sbd/sbdCore.c index d83ed231..cf46651e 100644 --- a/src/opt/sbd/sbdCore.c +++ b/src/opt/sbd/sbdCore.c @@ -42,6 +42,8 @@ struct Sbd_Man_t_ 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 // target node int Pivot; // target node Vec_Int_t * vTfo; // TFO (excludes node, includes roots) - precomputed @@ -82,7 +84,7 @@ void Sbd_ParSetDefault( Sbd_Par_t * pPars ) { memset( pPars, 0, sizeof(Sbd_Par_t) ); pPars->nLutSize = 4; // target LUT size - pPars->nTfoLevels = 3; // the number of TFO levels (windowing) + 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 @@ -145,7 +147,7 @@ Vec_Wec_t * Sbd_ManWindowRoots( Gia_Man_t * p, int nTfoLevels, int nTfoFanMax ) Vec_BitFree( vPoDrivers ); // print the results - if ( 1 ) + if ( 0 ) Vec_WecForEachLevel( vTfos, vNodes, i ) { if ( !Gia_ObjIsAnd(Gia_ManObj(p, i)) ) @@ -244,61 +246,9 @@ void Sbd_ManStop( Sbd_Man_t * p ) SeeAlso [] ***********************************************************************/ -void Sbd_ManWindowSim_rec( Sbd_Man_t * p, int Node ) +void Sbd_ManPropagateControlOne( Sbd_Man_t * p, int Node ) { - Gia_Obj_t * pObj; - if ( Vec_IntEntry(p->vMirrors, Node) >= 0 ) - Node = Abc_Lit2Var( Vec_IntEntry(p->vMirrors, Node) ); - if ( Gia_ObjIsTravIdCurrentId(p->pGia, Node) || Node == 0 ) - 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 ); - } -} -void Sbd_ManPropagateControl( Sbd_Man_t * p, int Node ) -{ - Gia_Obj_t * pNode = Gia_ManObj(p->pGia, Node); + Gia_Obj_t * pNode = Gia_ManObj(p->pGia, Node); int w; int iObj0 = Gia_ObjFaninId0(pNode, Node); int iObj1 = Gia_ObjFaninId1(pNode, Node); @@ -314,20 +264,37 @@ void Sbd_ManPropagateControl( Sbd_Man_t * p, int Node ) word * pDtrl0 = Sbd_ObjSim3(p, iObj0); word * pDtrl1 = Sbd_ObjSim3(p, iObj1); -// printf( "Node %2d : %d %d\n", Node, (int)(pSims[0] & 1), (int)(pCtrl[0] & 1) ); - int w; +// 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); + pCtrl0[w] |= pCtrl[w] & (pSims[w] | Sim1 | (~Sim0 & ~Sim1)); + pCtrl1[w] |= pCtrl[w] & (pSims[w] | Sim0); - pDtrl0[w] = pDtrl[w] & (pSims[w] | Sim1); - pDtrl1[w] = pDtrl[w] & (pSims[w] | Sim0 | (~Sim0 & ~Sim1)); + pDtrl0[w] |= pDtrl[w] & (pSims[w] | Sim1); + pDtrl1[w] |= pDtrl[w] & (pSims[w] | Sim0 | (~Sim0 & ~Sim1)); } } +void Sbd_ManPropagateControl( Sbd_Man_t * p, int Pivot ) +{ + 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 ); +} void Sbd_ManUpdateOrder( Sbd_Man_t * p, int Pivot ) { int i, k, Node; @@ -354,7 +321,62 @@ void Sbd_ManUpdateOrder( Sbd_Man_t * p, int Pivot ) Vec_IntFill( p->vDivValues, Vec_IntSize(p->vWinObjs), 0 ); } } -void Sbd_ManWindow( Sbd_Man_t * p, int Pivot ) +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 ) { int i, Node; // assign pivot and TFO (assume siminfo is assigned at the PIs) @@ -362,7 +384,10 @@ void Sbd_ManWindow( Sbd_Man_t * p, int Pivot ) p->vTfo = Vec_WecEntry( p->vTfos, Pivot ); // simulate TFI cone Vec_IntClear( p->vWinObjs ); + Vec_IntWriteEntry( p->vObj2Var, 0, Vec_IntSize(p->vWinObjs) ); + Vec_IntPush( p->vWinObjs, 0 ); Gia_ManIncrementTravId( p->pGia ); + Gia_ObjSetTravIdCurrentId(p->pGia, 0); Sbd_ManWindowSim_rec( p, Pivot ); Sbd_ManUpdateOrder( p, Pivot ); // simulate node @@ -394,11 +419,143 @@ void Sbd_ManWindow( Sbd_Man_t * p, int Pivot ) 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 ); - Abc_TtCopy( Sbd_ObjSim3(p, Pivot), Sbd_ObjSim2(p, Pivot), p->pPars->nWords, 0 ); // 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_ManPropagateControl( p, Node ); + Sbd_ManPropagateControl( p, Pivot ); + // return 1 if window is too large + if ( p->pPars->fVerbose && Vec_IntSize(p->vDivValues) >= 64 ) + printf( "Window is too large.\n" ); + 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 = 16; + 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}; + 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 ); + //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 ); + 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************************************************************* @@ -418,7 +575,7 @@ void Sbd_ManPrintObj( Sbd_Man_t * p, int Pivot ) int i, k, k0, k1, Id, Bit0, Bit1; Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs ) - printf( "%d : ", Id ), Extra_PrintBinary( stdout, (unsigned *)Sbd_ObjSim0(p, Id), 64 ), printf( "\n" ); + printf( "%3d : ", Id ), Extra_PrintBinary( stdout, (unsigned *)Sbd_ObjSim0(p, Id), 64 ), printf( "\n" ); assert( p->Pivot == Pivot ); Vec_IntClear( p->vCounts[0] ); @@ -561,52 +718,182 @@ void Sbd_ManPrintObj( Sbd_Man_t * p, int Pivot ) 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 ) ) - Extra_PrintBinary( stdout, (unsigned *)&Row, nDivs ), printf( "\n" ); + if ( Vec_WrdPushUnique( p->vMatrix, Row ) ) + continue; + for ( i = 0; i < nDivs; i++ ) + printf( "%d", (int)((Row >> i) & 1) ); + printf( "\n" ); } - } + + int Sbd_ManExplore( Sbd_Man_t * p, int Pivot, word * pTruth ) { - extern sat_solver * Sbd_ManSatSolver( sat_solver * pSat, Gia_Man_t * p, int Pivot, Vec_Int_t * vWinObjs, Vec_Int_t * vObj2Var, Vec_Int_t * vTfo, Vec_Int_t * vRoots ); + int fVerbose = 0; 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, Cube0, Cube1, Target; + int c0, c1, c2, c3, i, k, n, Index, nCubes[2] = {0}, nRows = 0, fFound = 0; + int PivotVar = Vec_IntEntry(p->vObj2Var, Pivot); int FreeVar = Vec_IntSize(p->vWinObjs) + Vec_IntSize(p->vTfo) + Vec_IntSize(p->vRoots); int RetValue = 0; -// Sbd_ManPrintObj( p, Pivot ); - Vec_IntPrint( p->vObj2Var ); + if ( fVerbose ) + Sbd_ManPrintObj( p, Pivot ); + + // collect bit-matrices + for ( i = 0; i < Vec_IntSize(p->vDivValues); 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], Vec_IntSize(p->vDivValues)) == Abc_TtGetBit(&MatrC[1][i], Vec_IntSize(p->vDivValues)) ); + if ( !Abc_TtGetBit(&MatrC[0][i], Vec_IntSize(p->vDivValues)) ) + continue; + Index = Abc_TtGetBit(&MatrS[i], Vec_IntSize(p->vDivValues)); // 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] ); + Cube0 = ~MatrS[i] & MatrC[n][i]; + Cube1 = MatrS[i] & MatrC[n][i]; + assert( Cube0 || Cube1 ); + for ( k = 0; k < nCubes[Index]; k++ ) + if ( Cubes[Index][0][k] == Cube0 && Cubes[Index][1][k] == Cube1 ) + break; + if ( k == nCubes[Index] && k < 64 ) + { + Cubes[Index][0][nCubes[Index]] = Cube0; + Cubes[Index][1][nCubes[Index]] = Cube1; + nCubes[Index]++; + } + } + } + + if ( p->pPars->fVerbose ) + printf( "Generated matrix with %d x %d entries.\n", nCubes[0], nCubes[1] ); + + if ( 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" ); + } + + // collect cover + for ( i = 0; i < nCubes[0]; i++ ) + for ( k = 0; k < nCubes[1]; k++ ) + { + Cube = (Cubes[0][1][i] & Cubes[1][0][k]) | (Cubes[0][0][i] & Cubes[1][1][k]); + assert( Cube ); + for ( n = 0; n < nRows; n++ ) + if ( Cover[63-n] == Cube ) + break; + if ( n == nRows && n < 64 ) + Cover[63-nRows++] = Cube; + } + + if ( p->pPars->fVerbose ) + printf( "Generated cover with %d entries.\n", nRows ); + + + //Sbd_PrintMatrix64( Cover ); + Sbd_TransposeMatrix64( Cover ); + //Sbd_PrintMatrix64( Cover ); + + // swap + for ( i = 0; i < 32; i++ ) + { + Cube = Cover[i]; + Cover[i] = Cover[63-i]; + Cover[63-i] = Cube; + } + + if ( fVerbose ) + { + for ( i = 0; i <= nRows; i++, printf( "\n") ) + for ( k = 0; k < 64; k++ ) + printf( "%d", (int)((Cover[i] >> k) & 1) ); + } + + Target = Cover[Vec_IntSize(p->vDivValues)]; + for ( c0 = 0; c0 < Vec_IntSize(p->vDivValues); c0++ ) + for ( c1 = c0+1; c1 < Vec_IntSize(p->vDivValues); c1++ ) + for ( c2 = c1+1; c2 < Vec_IntSize(p->vDivValues); c2++ ) + for ( c3 = c2+1; c3 < Vec_IntSize(p->vDivValues); c3++ ) + { + if ( (Cover[c0] | Cover[c1] | Cover[c2] | Cover[c3]) == Target ) + goto finish; + } +finish: + if ( c0 == Vec_IntSize(p->vDivValues) ) + { + if ( p->pPars->fVerbose ) + printf( "Cannot find a feasible cover.\n" ); + return RetValue; + } Vec_IntClear( p->vDivVars ); - Vec_IntPush( p->vDivVars, 0 ); - Vec_IntPush( p->vDivVars, 1 ); - Vec_IntPush( p->vDivVars, 2 ); - Vec_IntPush( p->vDivVars, 4 ); + Vec_IntPush( p->vDivVars, c0 ); + Vec_IntPush( p->vDivVars, c1 ); + Vec_IntPush( p->vDivVars, c2 ); + Vec_IntPush( p->vDivVars, c3 ); + + if ( p->pPars->fVerbose ) + printf( "Feasible cover: " ); + if ( p->pPars->fVerbose ) + Vec_IntPrint( p->vDivVars ); - p->pSat = Sbd_ManSatSolver( p->pSat, p->pGia, Pivot, p->vWinObjs, p->vObj2Var, p->vTfo, p->vRoots ); *pTruth = Sbd_ManSolve( p->pSat, PivotVar, FreeVar, p->vDivVars, p->vDivValues, p->vLits ); if ( *pTruth == SBD_SAT_UNDEC ) printf( "Node %d: Undecided.\n", Pivot ); else if ( *pTruth == SBD_SAT_SAT ) { - int i; - printf( "Node %d: SAT.\n", Pivot ); - for ( i = 0; i < Vec_IntSize(p->vDivValues); i++ ) - printf( "%d", Vec_IntEntry(p->vDivValues, i) & 1 ); - printf( "\n" ); - for ( i = 0; i < Vec_IntSize(p->vDivValues); i++ ) - printf( "%d", Vec_IntEntry(p->vDivValues, i) >> 1 ); - printf( "\n" ); + if ( p->pPars->fVerbose ) + { + int i; + printf( "Node %d: SAT.\n", Pivot ); + for ( i = 0; i < Vec_IntSize(p->vDivValues); i++ ) + printf( "%d", Vec_IntEntry(p->vDivValues, i) & 1 ); + printf( "\n" ); + for ( i = 0; i < Vec_IntSize(p->vDivValues); i++ ) + printf( "%d", Vec_IntEntry(p->vDivValues, i) >> 1 ); + printf( "\n" ); + } } else { - printf( "Node %d: UNSAT.\n", Pivot ); + if ( p->pPars->fVerbose ) + printf( "Node %d: UNSAT.\n", Pivot ); + if ( p->pPars->fVerbose ) + Extra_PrintBinary( stdout, (unsigned *)pTruth, 1 << Vec_IntSize(p->vDivVars) ), printf( "\n" ); RetValue = 1; } - Extra_PrintBinary( stdout, (unsigned *)pTruth, 1 << Vec_IntSize(p->vDivVars) ), printf( "\n" ); - return RetValue; } @@ -669,7 +956,7 @@ int Sbd_ManComputeCut( Sbd_Man_t * p, int Node ) 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 ); + //printf( "Setting node %d with delay %d (result = %d).\n", Node, LevMax, Result ); return Result; } int Sbd_ManImplement( Sbd_Man_t * p, int Pivot, word Truth ) @@ -697,11 +984,15 @@ int Sbd_ManImplement( Sbd_Man_t * p, int Pivot, word Truth ) // 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 ); // extend data-structure for 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_ManComputeCut( p, i ); for ( k = 0; k < 4; k++ ) @@ -710,6 +1001,7 @@ int Sbd_ManImplement( Sbd_Man_t * p, int Pivot, word Truth ) } // make sure delay reduction is achieved assert( Vec_IntEntry(p->vLutLevs, Abc_Lit2Var(iLit)) < iCurLev ); + p->nChanges++; return 0; } @@ -728,18 +1020,19 @@ void Sbd_ManDerive_rec( Gia_Man_t * pNew, Gia_Man_t * p, int Node, Vec_Int_t * v { Gia_Obj_t * pObj; int Obj = Node; - if ( Node < Vec_IntSize(vMirrors) && Vec_IntEntry(vMirrors, Node) >= 0 ) + if ( Vec_IntEntry(vMirrors, Node) >= 0 ) Obj = Abc_Lit2Var( Vec_IntEntry(vMirrors, Node) ); pObj = Gia_ManObj( p, Obj ); - if ( ~pObj->Value ) - return; - 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) ); + 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)) ); @@ -766,7 +1059,6 @@ Gia_Man_t * Sbd_ManDerive( Gia_Man_t * p, Vec_Int_t * vMirrors ) return pNew; } - /**Function************************************************************* Synopsis [Performs delay optimization for the given LUT size.] @@ -782,18 +1074,28 @@ Gia_Man_t * Sbd_NtkPerform( Gia_Man_t * pGia, Sbd_Par_t * pPars ) { Gia_Man_t * pNew; Sbd_Man_t * p = Sbd_ManStart( pGia, pPars ); - int Pivot; word Truth = 0; + int nNodesOld = Gia_ManObjNum(pGia); + int RetValue, Pivot; word Truth = 0; assert( pPars->nLutSize <= 6 ); Gia_ManForEachAndId( pGia, Pivot ) { + if ( Pivot >= nNodesOld ) + break; if ( Sbd_ManComputeCut( p, Pivot ) ) continue; - printf( "Looking at node %d\n", Pivot ); - Sbd_ManWindow( p, Pivot ); - if ( Sbd_ManExplore( p, Pivot, &Truth ) ) + //if ( Pivot != 313 ) + // continue; + if ( p->pPars->fVerbose ) + printf( "\nLooking at node %d\n", Pivot ); + if ( Sbd_ManWindow( p, Pivot ) ) + continue; + 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 ); - break; } + printf( "Found %d constants and %d replacements.\n", p->nConsts, p->nChanges ); pNew = Sbd_ManDerive( pGia, p->vMirrors ); Sbd_ManStop( p ); return pNew; diff --git a/src/opt/sbd/sbdWin.c b/src/opt/sbd/sbdWin.c index 8f320038..50837e1f 100644 --- a/src/opt/sbd/sbdWin.c +++ b/src/opt/sbd/sbdWin.c @@ -46,46 +46,62 @@ ABC_NAMESPACE_IMPL_START SeeAlso [] ***********************************************************************/ -sat_solver * Sbd_ManSatSolver( sat_solver * pSat, Gia_Man_t * p, int Pivot, Vec_Int_t * vWinObjs, Vec_Int_t * vObj2Var, Vec_Int_t * vTfo, Vec_Int_t * vRoots ) +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, iObj, Fan0, Fan1, Node, fCompl0, fCompl1, RetValue; + 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_IntForEachEntry( vWinObjs, iObj, i ) + 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 ); - Fan0 = Vec_IntEntry( vObj2Var, Gia_ObjFaninId0(pObj, iObj) ); - Fan1 = Vec_IntEntry( vObj2Var, Gia_ObjFaninId1(pObj, iObj) ); - fCompl0 = Gia_ObjFaninC0(pObj); - fCompl1 = Gia_ObjFaninC1(pObj); + 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, Vec_IntSize(vWinObjs) - Vec_IntSize(vTfo) ) + 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); - Fan0 = Vec_IntEntry( vObj2Var, Gia_ObjFaninId0(pObj, iObj) ); - Fan1 = Vec_IntEntry( vObj2Var, Gia_ObjFaninId1(pObj, iObj) ); - Fan0 = Fan0 <= PivotVar ? Fan0 : Fan0 + Vec_IntSize(vTfo); - Fan1 = Fan1 <= PivotVar ? Fan1 : Fan1 + Vec_IntSize(vTfo); - fCompl0 = Gia_ObjFaninC0(pObj) ^ (Fan0 == PivotVar); - fCompl1 = Gia_ObjFaninC1(pObj) ^ (Fan1 == PivotVar); + 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 @@ -98,8 +114,9 @@ sat_solver * Sbd_ManSatSolver( sat_solver * pSat, Gia_Man_t * p, int Pivot, Vec_ Vec_Int_t * vFaninVars = Vec_IntAlloc( Vec_IntSize(vRoots) ); Vec_IntForEachEntry( vRoots, iObj, i ) { - Vec_IntPush( vFaninVars, Abc_Var2Lit(nVars, 0) ); + 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 @@ -190,6 +207,50 @@ word Sbd_ManSolve( sat_solver * pSat, int PivotVar, int FreeVar, Vec_Int_t * vDi 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 /// //////////////////////////////////////////////////////////////////////// -- cgit v1.2.3 From 2ff522df455bf4835981d2348bb4c2cc3565073e Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 30 Nov 2016 20:58:53 -0800 Subject: New SAT-based optimization package. --- src/opt/sbd/sbdCore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/opt/sbd/sbdCore.c b/src/opt/sbd/sbdCore.c index cf46651e..b391eefa 100644 --- a/src/opt/sbd/sbdCore.c +++ b/src/opt/sbd/sbdCore.c @@ -733,7 +733,7 @@ int Sbd_ManExplore( Sbd_Man_t * p, int Pivot, word * pTruth ) 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, Cube0, Cube1, Target; - int c0, c1, c2, c3, i, k, n, Index, nCubes[2] = {0}, nRows = 0, fFound = 0; + int c0 = 0, c1 = 0, c2 = 0, c3 = 0, i, k, n, Index, nCubes[2] = {0}, nRows = 0; int PivotVar = Vec_IntEntry(p->vObj2Var, Pivot); int FreeVar = Vec_IntSize(p->vWinObjs) + Vec_IntSize(p->vTfo) + Vec_IntSize(p->vRoots); -- cgit v1.2.3 From 1bf289c774eca7ead1edfba51c0e86255e2730e7 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Fri, 2 Dec 2016 21:12:57 -0800 Subject: Changes to arithmetic logic detection. --- src/proof/acec/acecCl.c | 55 +++++++++ src/proof/acec/acecCo.c | 146 +++++++++++++++++------ src/proof/acec/acecPa.c | 282 +++++++++++++++++++++++++++++++++++++++++++++ src/proof/acec/acecPool.c | 132 +++++++++++++++++++++ src/proof/acec/acecRe.c | 163 ++++++++++++++++++++++---- src/proof/acec/module.make | 5 +- 6 files changed, 724 insertions(+), 59 deletions(-) create mode 100644 src/proof/acec/acecCl.c create mode 100644 src/proof/acec/acecPa.c create mode 100644 src/proof/acec/acecPool.c (limited to 'src') diff --git a/src/proof/acec/acecCl.c b/src/proof/acec/acecCl.c new file mode 100644 index 00000000..32be3b30 --- /dev/null +++ b/src/proof/acec/acecCl.c @@ -0,0 +1,55 @@ +/**CFile**************************************************************** + + FileName [acecCl.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [CEC for arithmetic circuits.] + + Synopsis [Core procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: acecCl.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "acecInt.h" +#include "misc/vec/vecWec.h" +#include "misc/extra/extra.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/acec/acecCo.c b/src/proof/acec/acecCo.c index 1b73c36f..39f092b2 100644 --- a/src/proof/acec/acecCo.c +++ b/src/proof/acec/acecCo.c @@ -90,38 +90,30 @@ Vec_Int_t * Gia_PolynAddHaRoots( Gia_Man_t * pGia ) SeeAlso [] ***********************************************************************/ -Vec_Int_t * Gia_PolynCoreOrder( Gia_Man_t * pGia, Vec_Int_t * vAdds, Vec_Int_t * vAddCos, Vec_Int_t ** pvIns, Vec_Int_t ** pvOuts ) +Vec_Wec_t * Gia_PolynComputeMap( Vec_Int_t * vAdds, int nObjs ) { - Vec_Int_t * vOrder = Vec_IntAlloc( 1000 ); - Vec_Bit_t * vIsRoot = Vec_BitStart( Gia_ManObjNum(pGia) ); - Vec_Int_t * vRoots = Vec_IntAlloc( 5 * Gia_ManCoNum(pGia) ); - Vec_Int_t * vLeaves = Vec_IntAlloc( 2 * Gia_ManCiNum(pGia) ); - Vec_Wec_t * vMap = Vec_WecStart( Gia_ManObjNum(pGia) ); - int i, k, Index, Driver, Entry1, Entry2 = -1; // map nodes driven by adders into adder indexes - for ( i = 0; 5*i < Vec_IntSize(vAdds); i++ ) + Vec_Wec_t * vMap = Vec_WecStart( nObjs ); int i; + for ( i = 0; 6*i < Vec_IntSize(vAdds); i++ ) { - Entry1 = Vec_IntEntry( vAdds, 5*i + 3 ); - Entry2 = Vec_IntEntry( vAdds, 5*i + 4 ); + int Entry1 = Vec_IntEntry( vAdds, 6*i + 3 ); + int Entry2 = Vec_IntEntry( vAdds, 6*i + 4 ); Vec_WecPush( vMap, Entry1, i ); Vec_WecPush( vMap, Entry1, Entry2 ); Vec_WecPush( vMap, Entry2, i ); Vec_WecPush( vMap, Entry2, Entry1 ); } - // collect roots - Gia_ManForEachCoDriverId( pGia, Driver, i ) - { - Vec_IntPush( vRoots, Driver ); - Vec_BitWriteEntry( vIsRoot, Driver, 1 ); - } - // collect additional outputs - Vec_IntForEachEntry( vAddCos, Driver, i ) - { - Vec_IntPush( vRoots, Driver ); + return vMap; +} +Vec_Int_t * Gia_PolynCoreOrder_int( Gia_Man_t * pGia, Vec_Int_t * vAdds, Vec_Wec_t * vMap, Vec_Int_t * vRoots, Vec_Int_t ** pvIns ) +{ + Vec_Int_t * vOrder = Vec_IntAlloc( 1000 ); + Vec_Bit_t * vIsRoot = Vec_BitStart( Gia_ManObjNum(pGia) ); + int i, k, Index, Driver, Entry1, Entry2 = -1; + // mark roots + Vec_IntForEachEntry( vRoots, Driver, i ) Vec_BitWriteEntry( vIsRoot, Driver, 1 ); - } - // detect full adder tree - *pvOuts = Vec_IntDup( vRoots ); + // collect boxes while ( 1 ) { // iterate through boxes driving this one @@ -143,9 +135,9 @@ Vec_Int_t * Gia_PolynCoreOrder( Gia_Man_t * pGia, Vec_Int_t * vAdds, Vec_Int_t * Vec_IntRemove( vRoots, Entry1 ); Vec_IntRemove( vRoots, Entry2 ); // set new marks - Entry1 = Vec_IntEntry( vAdds, 5*Index + 0 ); - Entry2 = Vec_IntEntry( vAdds, 5*Index + 1 ); - Driver = Vec_IntEntry( vAdds, 5*Index + 2 ); + Entry1 = Vec_IntEntry( vAdds, 6*Index + 0 ); + Entry2 = Vec_IntEntry( vAdds, 6*Index + 1 ); + Driver = Vec_IntEntry( vAdds, 6*Index + 2 ); Vec_BitWriteEntry( vIsRoot, Entry1, 1 ); Vec_BitWriteEntry( vIsRoot, Entry2, 1 ); Vec_BitWriteEntry( vIsRoot, Driver, 1 ); @@ -158,17 +150,97 @@ Vec_Int_t * Gia_PolynCoreOrder( Gia_Man_t * pGia, Vec_Int_t * vAdds, Vec_Int_t * break; } // collect remaining leaves - Vec_BitForEachEntryStart( vIsRoot, Driver, i, 1 ) - if ( Driver ) - Vec_IntPush( vLeaves, i ); - *pvIns = vLeaves; - // cleanup + if ( pvIns ) + { + *pvIns = Vec_IntAlloc( Vec_BitSize(vIsRoot) ); + Vec_BitForEachEntryStart( vIsRoot, Driver, i, 1 ) + if ( Driver ) + Vec_IntPush( *pvIns, i ); + } Vec_BitFree( vIsRoot ); + return vOrder; +} +Vec_Int_t * Gia_PolynCoreOrder( Gia_Man_t * pGia, Vec_Int_t * vAdds, Vec_Int_t * vAddCos, Vec_Int_t ** pvIns, Vec_Int_t ** pvOuts ) +{ + Vec_Int_t * vOrder; + Vec_Wec_t * vMap = Gia_PolynComputeMap( vAdds, Gia_ManObjNum(pGia) ); + Vec_Int_t * vRoots = Vec_IntAlloc( Gia_ManCoNum(pGia) ); + int i, Driver; + // collect roots + Gia_ManForEachCoDriverId( pGia, Driver, i ) + Vec_IntPush( vRoots, Driver ); + // collect additional outputs + if ( vAddCos ) + Vec_IntForEachEntry( vAddCos, Driver, i ) + Vec_IntPush( vRoots, Driver ); + // remember roots + if ( pvOuts ) + *pvOuts = Vec_IntDup( vRoots ); + // create order + vOrder = Gia_PolynCoreOrder_int( pGia, vAdds, vMap, vRoots, pvIns ); Vec_IntFree( vRoots ); Vec_WecFree( vMap ); + printf( "Collected %d boxes.\n", Vec_IntSize(vOrder) ); return vOrder; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_PolyCollectRoots_rec( Vec_Int_t * vAdds, Vec_Wec_t * vMap, Vec_Bit_t * vMarks, int iBox, Vec_Int_t * vRoots ) +{ + int k; + for ( k = 0; k < 3; k++ ) + { + int i, Index, Sum, Carry = Vec_IntEntry( vAdds, 6*iBox+k ); + Vec_Int_t * vLevel = Vec_WecEntry( vMap, Carry ); + if ( Carry == 0 ) + continue; + Vec_IntForEachEntryDouble( vLevel, Index, Sum, i ) + if ( Vec_IntEntry(vAdds, 6*Index+4) == Carry && !Vec_BitEntry(vMarks, Sum) ) + { + Vec_IntPush( vRoots, Sum ); + Gia_PolyCollectRoots_rec( vAdds, vMap, vMarks, Index, vRoots ); + } + } +} +void Gia_PolyCollectRoots( Vec_Int_t * vAdds, Vec_Wec_t * vMap, Vec_Bit_t * vMarks, int iBox, Vec_Int_t * vRoots ) +{ + Vec_IntClear( vRoots ); + Vec_IntPush( vRoots, Vec_IntEntry(vAdds, 6*iBox+3) ); + Vec_IntPush( vRoots, Vec_IntEntry(vAdds, 6*iBox+4) ); + Gia_PolyCollectRoots_rec( vAdds, vMap, vMarks, iBox, vRoots ); +} +Vec_Wec_t * Gia_PolynCoreOrderArray( Gia_Man_t * pGia, Vec_Int_t * vAdds, Vec_Int_t * vRootBoxes ) +{ + extern Vec_Bit_t * Acec_ManPoolGetPointed( Gia_Man_t * p, Vec_Int_t * vAdds ); + Vec_Bit_t * vMarks = Acec_ManPoolGetPointed( pGia, vAdds ); + Vec_Wec_t * vMap = Gia_PolynComputeMap( vAdds, Gia_ManObjNum(pGia) ); + Vec_Wec_t * vRes = Vec_WecStart( Vec_IntSize(vRootBoxes) ); + Vec_Int_t * vRoots = Vec_IntAlloc( 64 ); + Vec_Int_t * vOrder; + int i, iBox; + Vec_IntForEachEntry( vRootBoxes, iBox, i ) + { + Gia_PolyCollectRoots( vAdds, vMap, vMarks, iBox, vRoots ); + vOrder = Gia_PolynCoreOrder_int( pGia, vAdds, vMap, vRoots, NULL ); + Vec_IntAppend( Vec_WecEntry(vRes, i), vOrder ); + Vec_IntFree( vOrder ); + } + Vec_BitFree( vMarks ); + Vec_IntFree( vRoots ); + Vec_WecFree( vMap ); + return vRes; +} + /**Function************************************************************* Synopsis [Collect internal node order.] @@ -197,15 +269,15 @@ Vec_Int_t * Gia_PolynCoreCollect( Gia_Man_t * pGia, Vec_Int_t * vAdds, Vec_Int_t Vec_IntForEachEntryReverse( vOrder, Index, i ) { // mark inputs - Entry1 = Vec_IntEntry( vAdds, 5*Index + 0 ); - Entry2 = Vec_IntEntry( vAdds, 5*Index + 1 ); - Entry3 = Vec_IntEntry( vAdds, 5*Index + 2 ); + Entry1 = Vec_IntEntry( vAdds, 6*Index + 0 ); + Entry2 = Vec_IntEntry( vAdds, 6*Index + 1 ); + Entry3 = Vec_IntEntry( vAdds, 6*Index + 2 ); Vec_BitWriteEntry( vVisited, Entry1, 1 ); Vec_BitWriteEntry( vVisited, Entry2, 1 ); Vec_BitWriteEntry( vVisited, Entry3, 1 ); // traverse from outputs - Entry1 = Vec_IntEntry( vAdds, 5*Index + 3 ); - Entry2 = Vec_IntEntry( vAdds, 5*Index + 4 ); + Entry1 = Vec_IntEntry( vAdds, 6*Index + 3 ); + Entry2 = Vec_IntEntry( vAdds, 6*Index + 4 ); Gia_PolynCoreCollect_rec( pGia, Entry1, vNodes, vVisited ); Gia_PolynCoreCollect_rec( pGia, Entry2, vNodes, vVisited ); } @@ -325,7 +397,7 @@ Gia_Man_t * Gia_PolynCoreDetectTest_int( Gia_Man_t * pGia, Vec_Int_t * vAddCos, //Gia_ManShow( pGia, vNodes, 0 ); printf( "Detected %d FAs/HAs. Roots = %d. Leaves = %d. Nodes = %d. Adds = %d. ", - Vec_IntSize(vAdds)/5, Vec_IntSize(vLeaves), Vec_IntSize(vRoots), Vec_IntSize(vNodes), Vec_IntSize(vOrder) ); + Vec_IntSize(vAdds)/6, Vec_IntSize(vLeaves), Vec_IntSize(vRoots), Vec_IntSize(vNodes), Vec_IntSize(vOrder) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Gia_PolynCorePrintCones( pGia, vLeaves, fVerbose ); diff --git a/src/proof/acec/acecPa.c b/src/proof/acec/acecPa.c new file mode 100644 index 00000000..11d68d37 --- /dev/null +++ b/src/proof/acec/acecPa.c @@ -0,0 +1,282 @@ +/**CFile**************************************************************** + + FileName [acecPa.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [CEC for arithmetic circuits.] + + Synopsis [Core procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: acecPa.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "acecInt.h" +#include "misc/vec/vecWec.h" +#include "misc/extra/extra.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pas_ManVerifyPhaseOne_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + int Truth0, Truth1; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return pObj->Value; + Gia_ObjSetTravIdCurrent(p, pObj); + assert( Gia_ObjIsAnd(pObj) ); + assert( !Gia_ObjIsXor(pObj) ); + Truth0 = Pas_ManVerifyPhaseOne_rec( p, Gia_ObjFanin0(pObj) ); + Truth1 = Pas_ManVerifyPhaseOne_rec( p, Gia_ObjFanin1(pObj) ); + Truth0 = Gia_ObjFaninC0(pObj) ? 0xFF & ~Truth0 : Truth0; + Truth1 = Gia_ObjFaninC1(pObj) ? 0xFF & ~Truth1 : Truth1; + return (pObj->Value = Truth0 & Truth1); +} +void Pas_ManVerifyPhaseOne( Gia_Man_t * p, Vec_Int_t * vAdds, int iBox, Vec_Bit_t * vPhase ) +{ + Gia_Obj_t * pObj; + unsigned TruthXor, TruthMaj, Truths[3] = { 0xAA, 0xCC, 0xF0 }; + int k, iObj, fFadd = Vec_IntEntry(vAdds, 6*iBox+2) > 0; + + if ( !fFadd ) + return; + + Gia_ManIncrementTravId( p ); + for ( k = 0; k < 3; k++ ) + { + iObj = Vec_IntEntry( vAdds, 6*iBox+k ); + if ( iObj == 0 ) + continue; + pObj = Gia_ManObj( p, iObj ); + pObj->Value = Vec_BitEntry(vPhase, iObj) ? 0xFF & ~Truths[k] : Truths[k]; + Gia_ObjSetTravIdCurrent( p, pObj ); + } + + iObj = Vec_IntEntry( vAdds, 6*iBox+3 ); + TruthXor = Pas_ManVerifyPhaseOne_rec( p, Gia_ManObj(p, iObj) ); + TruthXor = Vec_BitEntry(vPhase, iObj) ? 0xFF & ~TruthXor : TruthXor; + + iObj = Vec_IntEntry( vAdds, 6*iBox+4 ); + TruthMaj = Pas_ManVerifyPhaseOne_rec( p, Gia_ManObj(p, iObj) ); + TruthMaj = Vec_BitEntry(vPhase, iObj) ? 0xFF & ~TruthMaj : TruthMaj; + + if ( fFadd ) // FADD + { + if ( TruthXor != 0x96 ) + printf( "Fadd %d sum is wrong.\n", iBox ); + if ( TruthMaj != 0xE8 ) + printf( "Fadd %d carry is wrong.\n", iBox ); + } + else + { + if ( TruthXor != 0x66 ) + printf( "Hadd %d sum is wrong.\n", iBox ); + if ( TruthMaj != 0x88 ) + printf( "Hadd %d carry is wrong.\n", iBox ); + } +} +void Pas_ManVerifyPhase( Gia_Man_t * p, Vec_Int_t * vAdds, Vec_Int_t * vOrder, Vec_Bit_t * vPhase ) +{ + int k, iBox; + Vec_IntForEachEntry( vOrder, iBox, k ) + Pas_ManVerifyPhaseOne( p, vAdds, iBox, vPhase ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pas_ManPhase_rec( Gia_Man_t * p, Vec_Int_t * vAdds, Vec_Int_t * vMap, Gia_Obj_t * pObj, int fPhase, Vec_Bit_t * vPhase, Vec_Bit_t * vConstPhase ) +{ + int k, iBox, iXor, Sign, fXorPhase; + assert( pObj != Gia_ManConst0(p) ); + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( fPhase ) + Vec_BitWriteEntry( vPhase, Gia_ObjId(p, pObj), fPhase ); + if ( !Gia_ObjIsAnd(pObj) ) + return; + iBox = Vec_IntEntry( vMap, Gia_ObjId(p, pObj) ); + if ( iBox == -1 ) + return; + iXor = Vec_IntEntry( vAdds, 6*iBox+3 ); + Sign = Vec_IntEntry( vAdds, 6*iBox+5 ); + fXorPhase = ((Sign >> 3) & 1); + // remember complemented HADD + if ( Vec_IntEntry(vAdds, 6*iBox+2) == 0 && fPhase ) + Vec_BitWriteEntry( vConstPhase, iBox, 1 ); + for ( k = 0; k < 3; k++ ) + { + int iObj = Vec_IntEntry( vAdds, 6*iBox+k ); + int fPhaseThis = ((Sign >> k) & 1) ^ fPhase; + fXorPhase ^= fPhaseThis; + if ( iObj == 0 ) + continue; + Pas_ManPhase_rec( p, vAdds, vMap, Gia_ManObj(p, iObj), fPhaseThis, vPhase, vConstPhase ); + } + Vec_BitWriteEntry( vPhase, iXor, fXorPhase ); +} +Vec_Bit_t * Pas_ManPhase( Gia_Man_t * p, Vec_Int_t * vAdds, Vec_Int_t * vMap, Vec_Int_t * vRoots, Vec_Bit_t ** pvConstPhase ) +{ + Vec_Bit_t * vPhase = Vec_BitStart( Vec_IntSize(vMap) ); + Vec_Bit_t * vConstPhase = Vec_BitStart( Vec_IntSize(vAdds)/6 ); + int i, iRoot; + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vRoots, iRoot, i ) + Pas_ManPhase_rec( p, vAdds, vMap, Gia_ManObj(p, iRoot), 1, vPhase, vConstPhase ); + *pvConstPhase = vConstPhase; + return vPhase; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pas_ManComputeCuts( Gia_Man_t * p, Vec_Int_t * vAdds, Vec_Int_t * vOrder, Vec_Int_t * vIns, Vec_Int_t * vOuts ) +{ + Vec_Bit_t * vUnique = Vec_BitStart( Gia_ManObjNum(p) ); + Vec_Bit_t * vUsed = Vec_BitStart( Gia_ManObjNum(p) ); + Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_Int_t * vRoots = Vec_IntAlloc( 100 ); + Vec_Bit_t * vPhase, * vConstPhase; + int i, k, Entry, nTrees; + + // map carries into adder indexes and mark driven nodes + Vec_IntForEachEntry( vOrder, i, k ) + { + int Carry = Vec_IntEntry(vAdds, 6*i+4); + if ( Vec_BitEntry(vUnique, Carry) ) + printf( "Carry %d participates more than once.\n", Carry ); + Vec_BitWriteEntry( vUnique, Carry, 1 ); + Vec_IntWriteEntry( vMap, Carry, i ); + // mark driven + Vec_BitWriteEntry( vUsed, Vec_IntEntry(vAdds, 6*i+0), 1 ); + Vec_BitWriteEntry( vUsed, Vec_IntEntry(vAdds, 6*i+1), 1 ); + Vec_BitWriteEntry( vUsed, Vec_IntEntry(vAdds, 6*i+2), 1 ); + } + // collect carries that do not drive other adders + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + if ( Vec_BitEntry(vUnique, i) && !Vec_BitEntry(vUsed, i) ) + Vec_IntPush( vRoots, i ); + nTrees = Vec_IntSize( vRoots ); + + Vec_IntPrint( vRoots ); + + // compute phases + if ( Vec_IntSize(vRoots) > 0 ) + { + int nCompls = 0; + + vPhase = Pas_ManPhase( p, vAdds, vMap, vRoots, &vConstPhase ); + Pas_ManVerifyPhase( p, vAdds, vOrder, vPhase ); + + printf( "Outputs: " ); + Vec_IntForEachEntry( vOuts, Entry, i ) + printf( "%d(%d) ", Entry, Vec_BitEntry(vPhase, Entry) ); + printf( "\n" ); + + printf( "Inputs: " ); + Vec_IntForEachEntry( vIns, Entry, i ) + { + printf( "%d(%d) ", Entry, Vec_BitEntry(vPhase, Entry) ); + nCompls += Vec_BitEntry(vPhase, Entry); + } + printf( " Compl = %d\n", nCompls ); + + Vec_BitFreeP( &vPhase ); + Vec_BitFreeP( &vConstPhase ); + } + + Vec_IntFree( vRoots ); + Vec_IntFree( vMap ); + Vec_BitFree( vUnique ); + Vec_BitFree( vUsed ); + return nTrees; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pas_ManComputeCutsTest( Gia_Man_t * p ) +{ + extern Vec_Int_t * Ree_ManComputeCuts( Gia_Man_t * p, int fVerbose ); + extern Vec_Int_t * Gia_PolynCoreOrder( Gia_Man_t * pGia, Vec_Int_t * vAdds, Vec_Int_t * vAddCos, Vec_Int_t ** pvIns, Vec_Int_t ** pvOuts ); + + extern int Ree_ManCountFadds( Vec_Int_t * vAdds ); + extern void Ree_ManPrintAdders( Vec_Int_t * vAdds, int fVerbose ); + abctime clk = Abc_Clock(); + Vec_Int_t * vAdds = Ree_ManComputeCuts( p, 1 ); + Vec_Int_t * vIns, * vOuts; + Vec_Int_t * vOrder = Gia_PolynCoreOrder( p, vAdds, NULL, &vIns, &vOuts ); + int nTrees, nFadds = Ree_ManCountFadds( vAdds ); + //Ree_ManPrintAdders( vAdds, 1 ); + printf( "Detected %d FAs and %d HAs. Collected %d adders. ", nFadds, Vec_IntSize(vAdds)/6-nFadds, Vec_IntSize(vOrder) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + // detect trees + clk = Abc_Clock(); + nTrees = Pas_ManComputeCuts( p, vAdds, vOrder, vIns, vOuts ); + Vec_IntFree( vAdds ); + Vec_IntFree( vOrder ); + Vec_IntFree( vIns ); + Vec_IntFree( vOuts ); + + printf( "Detected %d adder trees. ", nTrees ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/acec/acecPool.c b/src/proof/acec/acecPool.c new file mode 100644 index 00000000..294066fa --- /dev/null +++ b/src/proof/acec/acecPool.c @@ -0,0 +1,132 @@ +/**CFile**************************************************************** + + FileName [acecPool.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [CEC for arithmetic circuits.] + + Synopsis [Core procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: acecPool.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "acecInt.h" +#include "misc/vec/vecWec.h" +#include "misc/extra/extra.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Bit_t * Acec_ManPoolGetPointed( Gia_Man_t * p, Vec_Int_t * vAdds ) +{ + Vec_Bit_t * vMarks = Vec_BitStart( Gia_ManObjNum(p) ); + int i, k; + for ( i = 0; 6*i < Vec_IntSize(vAdds); i++ ) + for ( k = 0; k < 3; k++ ) + Vec_BitWriteEntry( vMarks, Vec_IntEntry(vAdds, 6*i+k), 1 ); + return vMarks; +} + +Vec_Int_t * Acec_ManPoolTopMost( Gia_Man_t * p, Vec_Int_t * vAdds ) +{ + int i, k, iTop, fVerbose = 0; + Vec_Int_t * vTops = Vec_IntAlloc( 1000 ); + Vec_Bit_t * vMarks = Acec_ManPoolGetPointed( p, vAdds ); + + for ( i = 0; 6*i < Vec_IntSize(vAdds); i++ ) + if ( !Vec_BitEntry(vMarks, Vec_IntEntry(vAdds, 6*i+3)) && + !Vec_BitEntry(vMarks, Vec_IntEntry(vAdds, 6*i+4)) ) + Vec_IntPush( vTops, i ); + + if ( fVerbose ) + Vec_IntForEachEntry( vTops, iTop, i ) + { + printf( "%4d : ", iTop ); + for ( k = 0; k < 3; k++ ) + printf( "%4d ", Vec_IntEntry(vAdds, 6*iTop+k) ); + printf( " -> " ); + for ( k = 3; k < 5; k++ ) + printf( "%4d ", Vec_IntEntry(vAdds, 6*iTop+k) ); + printf( "\n" ); + } + + Vec_BitFree( vMarks ); + return vTops; +} +void Acec_ManPool( Gia_Man_t * p ) +{ + extern Vec_Int_t * Ree_ManComputeCuts( Gia_Man_t * p, int fVerbose ); + extern Vec_Wec_t * Gia_PolynCoreOrderArray( Gia_Man_t * pGia, Vec_Int_t * vAdds, Vec_Int_t * vRootBoxes ); + + extern int Ree_ManCountFadds( Vec_Int_t * vAdds ); + extern void Ree_ManPrintAdders( Vec_Int_t * vAdds, int fVerbose ); + extern void Ree_ManRemoveTrivial( Gia_Man_t * p, Vec_Int_t * vAdds ); + extern void Ree_ManRemoveContained( Gia_Man_t * p, Vec_Int_t * vAdds ); + Vec_Int_t * vTops, * vTree; + Vec_Wec_t * vTrees; + + abctime clk = Abc_Clock(); + Vec_Int_t * vAdds = Ree_ManComputeCuts( p, 1 ); + int i, nFadds = Ree_ManCountFadds( vAdds ); + printf( "Detected %d FAs and %d HAs. ", nFadds, Vec_IntSize(vAdds)/6-nFadds ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + + clk = Abc_Clock(); + Ree_ManRemoveTrivial( p, vAdds ); + Ree_ManRemoveContained( p, vAdds ); + nFadds = Ree_ManCountFadds( vAdds ); + printf( "Detected %d FAs and %d HAs. ", nFadds, Vec_IntSize(vAdds)/6-nFadds ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + + //Ree_ManPrintAdders( vAdds, 1 ); + + // detect topmost nodes + vTops = Acec_ManPoolTopMost( p, vAdds ); + printf( "Detected %d topmost adder%s.\n", Vec_IntSize(vTops), Vec_IntSize(vTops) > 1 ? "s":"" ); + + // collect adder trees + vTrees = Gia_PolynCoreOrderArray( p, vAdds, vTops ); + Vec_WecForEachLevel( vTrees, vTree, i ) + printf( "Adder %5d : Tree with %5d nodes.\n", Vec_IntEntry(vTops, i), Vec_IntSize(vTree) ); + + Vec_WecFree( vTrees ); + Vec_IntFree( vAdds ); + Vec_IntFree( vTops ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/acec/acecRe.c b/src/proof/acec/acecRe.c index 1f10d249..e2340dba 100644 --- a/src/proof/acec/acecRe.c +++ b/src/proof/acec/acecRe.c @@ -69,6 +69,18 @@ void Ree_TruthPrecompute() } printf( "\n" ); } +void Ree_TruthPrecompute2() +{ + int i, b; + for ( i = 0; i < 8; i++ ) + { + word Truth = 0xE8; + for ( b = 0; b < 3; b++ ) + if ( (i >> b) & 1 ) + Truth = Abc_Tt6Flip( Truth, b ); + printf( "%d = %X\n", i, 0xFF & (int)Truth ); + } +} /**Function************************************************************* @@ -239,7 +251,7 @@ void Ree_ManCutPrint( int * pCut, int Count, word Truth ) void Ree_ManCutMerge( Gia_Man_t * p, int iObj, int * pList0, int * pList1, Vec_Int_t * vCuts, Hash_IntMan_t * pHash, Vec_Int_t * vData ) { int fVerbose = 0; - int i, k, c, Value, Truth, TruthC, * pCut0, * pCut1, pCut[5], Count = 0; + int i, k, c, Value, Truth, TruthC, * pCut0, * pCut1, pCut[6], Count = 0; if ( fVerbose ) printf( "Object %d\n", iObj ); Vec_IntFill( vCuts, 2, 1 ); @@ -290,7 +302,7 @@ void Ree_ManCutMerge( Gia_Man_t * p, int iObj, int * pList0, int * pList1, Vec_I ***********************************************************************/ Vec_Int_t * Ree_ManDeriveAdds( Hash_IntMan_t * p, Vec_Int_t * vData ) { - int i, j, k, iObj, iObj2, Value, Truth, CountX, CountM, Index = 0; + int i, j, k, iObj, iObj2, Value, Truth, Truth2, CountX, CountM, Index = 0; int nEntries = Hash_IntManEntryNum(p); Vec_Int_t * vAdds = Vec_IntAlloc( 1000 ); Vec_Int_t * vXors = Vec_IntStart( nEntries + 1 ); @@ -325,9 +337,9 @@ Vec_Int_t * Ree_ManDeriveAdds( Hash_IntMan_t * p, Vec_Int_t * vData ) if ( Index == -1 ) continue; if ( Truth == 0x66 || Truth == 0x99 || Truth == 0x69 || Truth == 0x96 ) - Vec_WecPush( vXorMap, Index, iObj ); + Vec_IntPushTwo( Vec_WecEntry(vXorMap, Index), iObj, Truth ); else - Vec_WecPush( vMajMap, Index, iObj ); + Vec_IntPushTwo( Vec_WecEntry(vMajMap, Index), iObj, Truth ); } Vec_IntFree( vIndex ); // create pairs @@ -336,11 +348,22 @@ Vec_Int_t * Ree_ManDeriveAdds( Hash_IntMan_t * p, Vec_Int_t * vData ) Vec_Int_t * vXorOne = Vec_WecEntry( vXorMap, i ); Vec_Int_t * vMajOne = Vec_WecEntry( vMajMap, i ); Hash_IntObj_t * pObj = Hash_IntObj( p, Value ); - Vec_IntForEachEntry( vXorOne, iObj, j ) - Vec_IntForEachEntry( vMajOne, iObj2, k ) + Vec_IntForEachEntryDouble( vXorOne, iObj, Truth, j ) + Vec_IntForEachEntryDouble( vMajOne, iObj2, Truth2, k ) { + int SignAnd[8] = {0x88, 0x44, 0x22, 0x11, 0xEE, 0xDD, 0xBB, 0x77}; + int SignMaj[8] = {0xE8, 0xD4, 0xB2, 0x71, 0x8E, 0x4D, 0x2B, 0x17}; + int n, SignXor = (Truth == 0x99 || Truth == 0x69) << 3; + for ( n = 0; n < 8; n++ ) + if ( Truth2 == SignMaj[n] ) + break; + if ( n == 8 ) + for ( n = 0; n < 8; n++ ) + if ( Truth2 == SignAnd[n] ) + break; + assert( n < 8 ); Vec_IntPushThree( vAdds, pObj->iData0, pObj->iData1, pObj->iData2 ); - Vec_IntPushTwo( vAdds, iObj, iObj2 ); + Vec_IntPushThree( vAdds, iObj, iObj2, SignXor | n ); } } Vec_IntFree( vIndexRev ); @@ -384,12 +407,58 @@ Vec_Int_t * Ree_ManComputeCuts( Gia_Man_t * p, int fVerbose ) vAdds = Ree_ManDeriveAdds( pHash, vData ); if ( fVerbose ) printf( "Adds = %d. Total = %d. Hashed = %d. Hashed/Adds = %.2f.\n", - Vec_IntSize(vAdds)/5, Vec_IntSize(vData)/3, Hash_IntManEntryNum(pHash), 5.0*Hash_IntManEntryNum(pHash)/Vec_IntSize(vAdds) ); + Vec_IntSize(vAdds)/6, Vec_IntSize(vData)/3, Hash_IntManEntryNum(pHash), 6.0*Hash_IntManEntryNum(pHash)/Vec_IntSize(vAdds) ); Vec_IntFree( vData ); Hash_IntManStop( pHash ); return vAdds; } +/**Function************************************************************* + + Synopsis [Highlight nodes inside FAs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ree_CollectInsiders_rec( Gia_Man_t * pGia, int iObj, Vec_Bit_t * vVisited, Vec_Bit_t * vInsiders ) +{ + if ( Vec_BitEntry(vVisited, iObj) ) + return; + Vec_BitSetEntry( vVisited, iObj, 1 ); + Ree_CollectInsiders_rec( pGia, Gia_ObjFaninId0p(pGia, Gia_ManObj(pGia, iObj)), vVisited, vInsiders ); + Ree_CollectInsiders_rec( pGia, Gia_ObjFaninId1p(pGia, Gia_ManObj(pGia, iObj)), vVisited, vInsiders ); + Vec_BitSetEntry( vInsiders, iObj, 1 ); +} +Vec_Bit_t * Ree_CollectInsiders( Gia_Man_t * pGia, Vec_Int_t * vAdds ) +{ + Vec_Bit_t * vVisited = Vec_BitStart( Gia_ManObjNum(pGia) ); + Vec_Bit_t * vInsiders = Vec_BitStart( Gia_ManObjNum(pGia) ); + int i, Entry1, Entry2, Entry3; + for ( i = 0; 6*i < Vec_IntSize(vAdds); i++ ) + { + if ( Vec_IntEntry(vAdds, 6*i+2) == 0 ) // HADD + continue; + // mark inputs + Entry1 = Vec_IntEntry( vAdds, 6*i + 0 ); + Entry2 = Vec_IntEntry( vAdds, 6*i + 1 ); + Entry3 = Vec_IntEntry( vAdds, 6*i + 2 ); + Vec_BitWriteEntry( vVisited, Entry1, 1 ); + Vec_BitWriteEntry( vVisited, Entry2, 1 ); + Vec_BitWriteEntry( vVisited, Entry3, 1 ); + // traverse from outputs + Entry1 = Vec_IntEntry( vAdds, 6*i + 3 ); + Entry2 = Vec_IntEntry( vAdds, 6*i + 4 ); + Ree_CollectInsiders_rec( pGia, Entry1, vVisited, vInsiders ); + Ree_CollectInsiders_rec( pGia, Entry2, vVisited, vInsiders ); + } + Vec_BitFree( vVisited ); + return vInsiders; +} + /**Function************************************************************* Synopsis [] @@ -401,28 +470,80 @@ Vec_Int_t * Ree_ManComputeCuts( Gia_Man_t * p, int fVerbose ) SeeAlso [] ***********************************************************************/ -void Ree_ManComputeCutsTest( Gia_Man_t * p ) +// removes HAs whose AND2 is part of XOR2 without additional fanout +void Ree_ManRemoveTrivial( Gia_Man_t * p, Vec_Int_t * vAdds ) +{ + Gia_Obj_t * pObjX, * pObjM; + int i, k = 0; + ABC_FREE( p->pRefs ); + Gia_ManCreateRefs( p ); + for ( i = 0; 6*i < Vec_IntSize(vAdds); i++ ) + { + if ( Vec_IntEntry(vAdds, 6*i+2) == 0 ) // HADD + { + pObjX = Gia_ManObj( p, Vec_IntEntry(vAdds, 6*i+3) ); + pObjM = Gia_ManObj( p, Vec_IntEntry(vAdds, 6*i+4) ); + if ( (pObjM == Gia_ObjFanin0(pObjX) || pObjM == Gia_ObjFanin1(pObjX)) && Gia_ObjRefNum(p, pObjM) == 1 ) + continue; + } + memmove( Vec_IntArray(vAdds) + 6*k++, Vec_IntArray(vAdds) + 6*i, 6*sizeof(int) ); + } + assert( k <= i ); + Vec_IntShrink( vAdds, 6*k ); +} +// removes HAs fully contained inside FAs +void Ree_ManRemoveContained( Gia_Man_t * p, Vec_Int_t * vAdds ) +{ + Vec_Bit_t * vInsiders = Ree_CollectInsiders( p, vAdds ); + int i, k = 0; + for ( i = 0; 6*i < Vec_IntSize(vAdds); i++ ) + { + if ( Vec_IntEntry(vAdds, 6*i+2) == 0 ) // HADD + if ( Vec_BitEntry(vInsiders, Vec_IntEntry(vAdds, 6*i+3)) && Vec_BitEntry(vInsiders, Vec_IntEntry(vAdds, 6*i+4)) ) + continue; + memmove( Vec_IntArray(vAdds) + 6*k++, Vec_IntArray(vAdds) + 6*i, 6*sizeof(int) ); + } + assert( k <= i ); + Vec_IntShrink( vAdds, 6*k ); + Vec_BitFree( vInsiders ); +} + +int Ree_ManCountFadds( Vec_Int_t * vAdds ) { - abctime clk = Abc_Clock(); - Vec_Int_t * vAdds = Ree_ManComputeCuts( p, 1 ); int i, Count = 0; - for ( i = 0; 5*i < Vec_IntSize(vAdds); i++ ) + for ( i = 0; 6*i < Vec_IntSize(vAdds); i++ ) + if ( Vec_IntEntry(vAdds, 6*i+2) != 0 ) + Count++; + return Count; +} +void Ree_ManPrintAdders( Vec_Int_t * vAdds, int fVerbose ) +{ + int i; + for ( i = 0; 6*i < Vec_IntSize(vAdds); i++ ) { - if ( Vec_IntEntry(vAdds, 5*i+2) == 0 ) + //if ( Vec_IntEntry(vAdds, 6*i+2) == 0 ) + // continue; + if ( !fVerbose ) continue; - Count++; - continue; printf( "%6d : ", i ); - printf( "%6d ", Vec_IntEntry(vAdds, 5*i+0) ); - printf( "%6d ", Vec_IntEntry(vAdds, 5*i+1) ); - printf( "%6d ", Vec_IntEntry(vAdds, 5*i+2) ); + printf( "%6d ", Vec_IntEntry(vAdds, 6*i+0) ); + printf( "%6d ", Vec_IntEntry(vAdds, 6*i+1) ); + printf( "%6d ", Vec_IntEntry(vAdds, 6*i+2) ); printf( " -> " ); - printf( "%6d ", Vec_IntEntry(vAdds, 5*i+3) ); - printf( "%6d ", Vec_IntEntry(vAdds, 5*i+4) ); + printf( "%6d ", Vec_IntEntry(vAdds, 6*i+3) ); + printf( "%6d ", Vec_IntEntry(vAdds, 6*i+4) ); + printf( " (%d)", Vec_IntEntry(vAdds, 6*i+5) ); printf( "\n" ); } +} +void Ree_ManComputeCutsTest( Gia_Man_t * p ) +{ + abctime clk = Abc_Clock(); + Vec_Int_t * vAdds = Ree_ManComputeCuts( p, 1 ); + int nFadds = Ree_ManCountFadds( vAdds ); + Ree_ManPrintAdders( vAdds, 1 ); + printf( "Detected %d FAs and %d HAs. ", nFadds, Vec_IntSize(vAdds)/6-nFadds ); Vec_IntFree( vAdds ); - printf( "Detected %d FAs and %d HAs. ", Count, Vec_IntSize(vAdds)/5-Count ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } diff --git a/src/proof/acec/module.make b/src/proof/acec/module.make index e66bf6e8..df6db695 100644 --- a/src/proof/acec/module.make +++ b/src/proof/acec/module.make @@ -1,7 +1,10 @@ -SRC += src/proof/acec/acecCore.c \ +SRC += src/proof/acec/acecCl.c \ + src/proof/acec/acecCore.c \ src/proof/acec/acecCo.c \ src/proof/acec/acecRe.c \ + src/proof/acec/acecPa.c \ src/proof/acec/acecPo.c \ + src/proof/acec/acecPool.c \ src/proof/acec/acecCover.c \ src/proof/acec/acecFadds.c \ src/proof/acec/acecOrder.c \ -- cgit v1.2.3 From c88a2421b46288e4a4c74a72b906f81ea9ed00b1 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 3 Dec 2016 19:58:12 -0800 Subject: New SAT-based optimization package. --- src/opt/sbd/sbdCore.c | 534 ++++++++++++++++++++++++++++++++++++++------------ src/opt/sbd/sbdWin.c | 26 ++- 2 files changed, 437 insertions(+), 123 deletions(-) (limited to 'src') diff --git a/src/opt/sbd/sbdCore.c b/src/opt/sbd/sbdCore.c index b391eefa..a35c5594 100644 --- a/src/opt/sbd/sbdCore.c +++ b/src/opt/sbd/sbdCore.c @@ -44,6 +44,13 @@ struct Sbd_Man_t_ 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 @@ -176,6 +183,7 @@ 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 ); @@ -207,7 +215,7 @@ Sbd_Man_t * Sbd_ManStart( Gia_Man_t * pGia, Sbd_Par_t * pPars ) Gia_ManRandom( 1 ); Gia_ManForEachCiId( pGia, Id, i ) for ( w = 0; w < p->pPars->nWords; w++ ) - Sbd_ObjSim0(p, Id)[w] = Gia_ManRandomW( 0 ); + Sbd_ObjSim0(p, Id)[w] = Gia_ManRandomW( 0 ); return p; } void Sbd_ManStop( Sbd_Man_t * p ) @@ -272,15 +280,16 @@ void Sbd_ManPropagateControlOne( Sbd_Man_t * p, int Node ) 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); + 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); - pDtrl1[w] |= pDtrl[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 @@ -294,11 +303,13 @@ void Sbd_ManPropagateControl( Sbd_Man_t * p, int 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 ); @@ -316,10 +327,13 @@ void Sbd_ManUpdateOrder( Sbd_Man_t * p, int Pivot ) Vec_IntWriteEntry( p->vObj2Var, Node, Vec_IntSize(p->vWinObjs) ); Vec_IntPush( p->vWinObjs, Node ); } - // detect useful divisors + // remember divisor cutoff if ( i == LevelMax - 2 ) - Vec_IntFill( p->vDivValues, Vec_IntSize(p->vWinObjs), 0 ); + 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 ) { @@ -378,14 +392,16 @@ void Sbd_ManWindowSim_rec( Sbd_Man_t * p, int 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 ); - // simulate TFI cone + // 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 ); @@ -419,11 +435,10 @@ int Sbd_ManWindow( Sbd_Man_t * p, int Pivot ) 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 ); - // return 1 if window is too large - if ( p->pPars->fVerbose && Vec_IntSize(p->vDivValues) >= 64 ) - printf( "Window is too large.\n" ); + assert( Vec_IntSize(p->vDivValues) < 64 ); return (int)(Vec_IntSize(p->vDivValues) >= 64); } @@ -441,15 +456,17 @@ int Sbd_ManWindow( Sbd_Man_t * p, int Pivot ) int Sbd_ManCheckConst( Sbd_Man_t * p, int Pivot ) { extern void Sbd_ManPrintObj( Sbd_Man_t * p, int Pivot ); - int nMintCount = 16; + 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; //return -1; //Sbd_ManPrintObj( p, Pivot ); @@ -508,6 +525,7 @@ int Sbd_ManCheckConst( Sbd_Man_t * p, int Pivot ) { if ( p->pPars->fVerbose ) printf( "Found stuck-at-%d node %d.\n", RetValue, Pivot ); + Vec_IntWriteEntry( p->vLutLevs, Pivot, 0 ); p->nConsts++; return RetValue; } @@ -726,24 +744,156 @@ void Sbd_ManPrintObj( Sbd_Man_t * p, int Pivot ) } } +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_ManFindCands( 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; +} 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, Cube0, Cube1, Target; - int c0 = 0, c1 = 0, c2 = 0, c3 = 0, i, k, n, Index, nCubes[2] = {0}, nRows = 0; + 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 < Vec_IntSize(p->vDivValues); i++ ) + 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) ); @@ -762,34 +912,26 @@ int Sbd_ManExplore( Sbd_Man_t * p, int Pivot, word * pTruth ) // collect cubes for ( i = 0; i < 64; i++ ) { - assert( Abc_TtGetBit(&MatrC[0][i], Vec_IntSize(p->vDivValues)) == Abc_TtGetBit(&MatrC[1][i], Vec_IntSize(p->vDivValues)) ); - if ( !Abc_TtGetBit(&MatrC[0][i], Vec_IntSize(p->vDivValues)) ) + 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], Vec_IntSize(p->vDivValues)); // Index==0 offset; Index==1 onset + 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] ); - Cube0 = ~MatrS[i] & MatrC[n][i]; - Cube1 = MatrS[i] & MatrC[n][i]; - assert( Cube0 || Cube1 ); - for ( k = 0; k < nCubes[Index]; k++ ) - if ( Cubes[Index][0][k] == Cube0 && Cubes[Index][1][k] == Cube1 ) - break; - if ( k == nCubes[Index] && k < 64 ) - { - Cubes[Index][0][nCubes[Index]] = Cube0; - Cubes[Index][1][nCubes[Index]] = Cube1; - nCubes[Index]++; - } + 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 ( fVerbose ) + if ( p->pPars->fVerbose ) for ( n = 0; n < 2; n++ ) { printf( "%s:\n", n ? "Onset" : "Offset" ); @@ -804,96 +946,99 @@ int Sbd_ManExplore( Sbd_Man_t * p, int Pivot, word * pTruth ) printf( "\n" ); } - // collect cover - for ( i = 0; i < nCubes[0]; i++ ) - for ( k = 0; k < nCubes[1]; k++ ) + // 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 ); - for ( n = 0; n < nRows; n++ ) - if ( Cover[63-n] == Cube ) - break; - if ( n == nRows && n < 64 ) - Cover[63-nRows++] = 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 ); - // swap - for ( i = 0; i < 32; i++ ) - { - Cube = Cover[i]; - Cover[i] = Cover[63-i]; - Cover[63-i] = Cube; - } - - if ( fVerbose ) - { - for ( i = 0; i <= nRows; i++, printf( "\n") ) - for ( k = 0; k < 64; k++ ) - printf( "%d", (int)((Cover[i] >> k) & 1) ); - } + Sbd_ManCoverReverseOrder( Cover ); - Target = Cover[Vec_IntSize(p->vDivValues)]; - for ( c0 = 0; c0 < Vec_IntSize(p->vDivValues); c0++ ) - for ( c1 = c0+1; c1 < Vec_IntSize(p->vDivValues); c1++ ) - for ( c2 = c1+1; c2 < Vec_IntSize(p->vDivValues); c2++ ) - for ( c3 = c2+1; c3 < Vec_IntSize(p->vDivValues); c3++ ) - { - if ( (Cover[c0] | Cover[c1] | Cover[c2] | Cover[c3]) == Target ) - goto finish; - } -finish: - if ( c0 == Vec_IntSize(p->vDivValues) ) + nRowsOld = nRows; + for ( nIters = 0; nIters < nItersMax && nRows < 64; nIters++ ) { if ( p->pPars->fVerbose ) - printf( "Cannot find a feasible cover.\n" ); - return RetValue; - } + Sbd_ManMatrPrint( Cover, nDivs, nRows ); - Vec_IntClear( p->vDivVars ); - Vec_IntPush( p->vDivVars, c0 ); - Vec_IntPush( p->vDivVars, c1 ); - Vec_IntPush( p->vDivVars, c2 ); - Vec_IntPush( p->vDivVars, c3 ); + 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( "Feasible cover: " ); - if ( p->pPars->fVerbose ) - Vec_IntPrint( p->vDivVars ); - - *pTruth = Sbd_ManSolve( p->pSat, PivotVar, FreeVar, p->vDivVars, p->vDivValues, p->vLits ); - if ( *pTruth == SBD_SAT_UNDEC ) - printf( "Node %d: Undecided.\n", Pivot ); - else if ( *pTruth == SBD_SAT_SAT ) - { 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 ) { - int i; - printf( "Node %d: SAT.\n", Pivot ); - for ( i = 0; i < Vec_IntSize(p->vDivValues); i++ ) - printf( "%d", Vec_IntEntry(p->vDivValues, i) & 1 ); - printf( "\n" ); - for ( i = 0; i < Vec_IntSize(p->vDivValues); i++ ) - printf( "%d", Vec_IntEntry(p->vDivValues, i) >> 1 ); - printf( "\n" ); + 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; } - else - { - if ( p->pPars->fVerbose ) - printf( "Node %d: UNSAT.\n", Pivot ); - if ( p->pPars->fVerbose ) - Extra_PrintBinary( stdout, (unsigned *)pTruth, 1 << Vec_IntSize(p->vDivVars) ), printf( "\n" ); - RetValue = 1; - } - + //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; } @@ -930,9 +1075,11 @@ int Sbd_CutMergeSimple( Sbd_Man_t * p, int * pCut1, int * pCut2, int * pCut ) *pBeg++ = *pBeg2++; return (pCut[0] = pBeg - pCut - 1); } -int Sbd_ManComputeCut( Sbd_Man_t * p, int Node ) +/* +int Sbd_ManMergeCuts( Sbd_Man_t * p, int Node ) { - int pCut[2*SBD_MAX_LUTSIZE]; + 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 ); @@ -940,30 +1087,147 @@ int Sbd_ManComputeCut( Sbd_Man_t * p, int Node ) int LevMax = (Level0 || Level1) ? Abc_MaxInt(Level0, Level1) : 1; int * pCut0 = Sbd_ObjCut( p, iFan0 ); int * pCut1 = Sbd_ObjCut( p, iFan1 ); - int Cut0[2] = {1, iFan0}, * pCut0Temp = Level0 < LevMax ? Cut0 : pCut0; - int Cut1[2] = {1, iFan1}, * pCut1Temp = Level1 < LevMax ? Cut1 : pCut1; - int nSize = Sbd_CutMergeSimple( p, pCut0Temp, pCut1Temp, pCut ); - int Result = 1; // no need to resynthesize - assert( iFan0 != iFan1 ); + int nSize = Sbd_CutMergeSimple( p, pCut0, pCut1, 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++; + 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 == 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 ) { - int i, k, w, iLit, Node; + int i, k, w, iLit, Entry, Node; int iObjLast = Gia_ManObjNum(p->pGia); int iCurLev = Vec_IntEntry(p->vLutLevs, Pivot); + int iNewLev; + Gia_Obj_t * pObj; // collect leaf literals Vec_IntClear( p->vLits ); Vec_IntForEachEntry( p->vDivVars, Node, i ) @@ -986,7 +1250,13 @@ int Sbd_ManImplement( Sbd_Man_t * p, int Pivot, word Truth ) Vec_IntWriteEntry( p->vMirrors, Pivot, iLit ); if ( p->pPars->fVerbose ) printf( "Replacing node %d by literal %d.\n", Pivot, iLit ); - // extend data-structure for new nodes + // 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++ ) { @@ -994,13 +1264,20 @@ int Sbd_ManImplement( Sbd_Man_t * p, int Pivot, word Truth ) Vec_IntPush( p->vObj2Var, 0 ); Vec_IntPush( p->vMirrors, -1 ); Vec_IntFillExtra( p->vLutCuts, Vec_IntSize(p->vLutCuts) + p->pPars->nLutSize + 1, 0 ); - Sbd_ManComputeCut( p, i ); + 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 - assert( Vec_IntEntry(p->vLutLevs, Abc_Lit2Var(iLit)) < iCurLev ); + 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; } @@ -1074,16 +1351,18 @@ Gia_Man_t * Sbd_NtkPerform( Gia_Man_t * pGia, Sbd_Par_t * pPars ) { Gia_Man_t * pNew; Sbd_Man_t * p = Sbd_ManStart( pGia, pPars ); - int nNodesOld = Gia_ManObjNum(pGia); + int nNodesOld = Gia_ManObjNum(pGia);//, Count = 0; int RetValue, Pivot; word Truth = 0; assert( pPars->nLutSize <= 6 ); + //Sbd_ManMergeTest( p ); + //return NULL; Gia_ManForEachAndId( pGia, Pivot ) { if ( Pivot >= nNodesOld ) break; - if ( Sbd_ManComputeCut( p, Pivot ) ) + if ( Sbd_ManMergeCuts( p, Pivot ) ) continue; - //if ( Pivot != 313 ) + //if ( Pivot != 344 ) // continue; if ( p->pPars->fVerbose ) printf( "\nLooking at node %d\n", Pivot ); @@ -1093,10 +1372,25 @@ Gia_Man_t * Sbd_NtkPerform( Gia_Man_t * pGia, Sbd_Par_t * pPars ) if ( RetValue >= 0 ) Vec_IntWriteEntry( p->vMirrors, Pivot, RetValue ); else if ( Sbd_ManExplore( p, Pivot, &Truth ) ) + { Sbd_ManImplement( p, Pivot, Truth ); + //if ( Count++ == 1 ) + // break; + } } - printf( "Found %d constants and %d replacements.\n", p->nConsts, p->nChanges ); + 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; + 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; } diff --git a/src/opt/sbd/sbdWin.c b/src/opt/sbd/sbdWin.c index 50837e1f..7100462b 100644 --- a/src/opt/sbd/sbdWin.c +++ b/src/opt/sbd/sbdWin.c @@ -155,9 +155,9 @@ word Sbd_ManSolve( sat_solver * pSat, int PivotVar, int FreeVar, Vec_Int_t * vDi 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 - assert( Vec_IntSize(vValues) <= sat_solver_nvars(pSat) ); while ( 1 ) { // find onset minterm @@ -169,7 +169,7 @@ word Sbd_ManSolve( sat_solver * pSat, int PivotVar, int FreeVar, Vec_Int_t * vDi assert( status == l_True ); // remember variable values for ( i = 0; i < Vec_IntSize(vValues); i++ ) - Vec_IntWriteEntry( vValues, i, sat_solver_var_value(pSat, 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 @@ -203,7 +203,27 @@ word Sbd_ManSolve( sat_solver * pSat, int PivotVar, int FreeVar, Vec_Int_t * vDi assert( status == l_True ); // store the counter-example for ( i = 0; i < Vec_IntSize(vValues); i++ ) - Vec_IntAddToEntry( vValues, i, 2*sat_solver_var_value(pSat, 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; } -- cgit v1.2.3 From 91aab10757add03dc29e5b7d0d966f5784625949 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 4 Dec 2016 13:05:51 -0800 Subject: Analysis of arithmetic logic cones. --- src/base/abci/abc.c | 13 +- src/opt/sbd/sbdCore.c | 10 +- src/proof/acec/acecCo.c | 4 +- src/proof/acec/acecPa.c | 4 +- src/proof/acec/acecPool.c | 317 +++++++++++++++++++++++++++++++++++++++++++++- src/proof/acec/acecRe.c | 44 +++++-- 6 files changed, 366 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 25bcc306..ba4d37b3 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -28220,9 +28220,10 @@ int Abc_CommandAbc9MuxProfile( Abc_Frame_t * pAbc, int argc, char ** argv ) extern void Gia_ManMuxProfiling( Gia_Man_t * p ); extern void Gia_ManProfileStructures( Gia_Man_t * p, int nLimit, int fVerbose ); extern void Acec_StatsCollect( Gia_Man_t * p, int fVerbose ); - int c, fNpn = 0, fMuxes = 0, nLimit = 0, fVerbose = 0; + extern void Acec_ManProfile( Gia_Man_t * p, int fVerbose ); + int c, fNpn = 0, fMuxes = 0, fAdders = 0, nLimit = 0, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Nnmvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Nnmavh" ) ) != EOF ) { switch ( c ) { @@ -28243,6 +28244,9 @@ int Abc_CommandAbc9MuxProfile( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'm': fMuxes ^= 1; break; + case 'a': + fAdders ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -28268,16 +28272,19 @@ int Abc_CommandAbc9MuxProfile( Abc_Frame_t * pAbc, int argc, char ** argv ) } else if ( fMuxes ) Gia_ManMuxProfiling( pAbc->pGia ); + else if ( fAdders ) + Acec_ManProfile( pAbc->pGia, fVerbose ); else Gia_ManProfileStructures( pAbc->pGia, nLimit, fVerbose ); return 0; usage: - Abc_Print( -2, "usage: &profile [-N num] [-nmvh]\n" ); + Abc_Print( -2, "usage: &profile [-N num] [-nmavh]\n" ); Abc_Print( -2, "\t profile gate structures appearing in the AIG\n" ); Abc_Print( -2, "\t-N num : limit on class size to show [default = %d]\n", nLimit ); Abc_Print( -2, "\t-n : toggle profiling NPN-classes (for 3-LUT mapped AIGs) [default = %s]\n", fNpn? "yes": "no" ); Abc_Print( -2, "\t-m : toggle profiling MUX structures [default = %s]\n", fMuxes? "yes": "no" ); + Abc_Print( -2, "\t-a : toggle profiling adder structures [default = %s]\n", fAdders? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; diff --git a/src/opt/sbd/sbdCore.c b/src/opt/sbd/sbdCore.c index a35c5594..f5c944c9 100644 --- a/src/opt/sbd/sbdCore.c +++ b/src/opt/sbd/sbdCore.c @@ -260,9 +260,9 @@ void Sbd_ManPropagateControlOne( Sbd_Man_t * p, int Node ) 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 * 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); @@ -277,8 +277,8 @@ void Sbd_ManPropagateControlOne( Sbd_Man_t * p, int Node ) 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]; +// 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)); diff --git a/src/proof/acec/acecCo.c b/src/proof/acec/acecCo.c index 39f092b2..1e8ed7bb 100644 --- a/src/proof/acec/acecCo.c +++ b/src/proof/acec/acecCo.c @@ -387,10 +387,10 @@ Gia_Man_t * Gia_PolynCoreDupTree( Gia_Man_t * p, Vec_Int_t * vAddCos, Vec_Int_t ***********************************************************************/ Gia_Man_t * Gia_PolynCoreDetectTest_int( Gia_Man_t * pGia, Vec_Int_t * vAddCos, int fAddCones, int fVerbose ) { - extern Vec_Int_t * Ree_ManComputeCuts( Gia_Man_t * p, int fVerbose ); + extern Vec_Int_t * Ree_ManComputeCuts( Gia_Man_t * p, Vec_Int_t ** pvXors, int fVerbose ); abctime clk = Abc_Clock(); Gia_Man_t * pNew; - Vec_Int_t * vAdds = Ree_ManComputeCuts( pGia, 1 ); + Vec_Int_t * vAdds = Ree_ManComputeCuts( pGia, NULL, 1 ); Vec_Int_t * vLeaves, * vRoots, * vOrder = Gia_PolynCoreOrder( pGia, vAdds, vAddCos, &vLeaves, &vRoots ); Vec_Int_t * vNodes = Gia_PolynCoreCollect( pGia, vAdds, vOrder ); diff --git a/src/proof/acec/acecPa.c b/src/proof/acec/acecPa.c index 11d68d37..ecaf2047 100644 --- a/src/proof/acec/acecPa.c +++ b/src/proof/acec/acecPa.c @@ -248,13 +248,13 @@ int Pas_ManComputeCuts( Gia_Man_t * p, Vec_Int_t * vAdds, Vec_Int_t * vOrder, Ve ***********************************************************************/ void Pas_ManComputeCutsTest( Gia_Man_t * p ) { - extern Vec_Int_t * Ree_ManComputeCuts( Gia_Man_t * p, int fVerbose ); + extern Vec_Int_t * Ree_ManComputeCuts( Gia_Man_t * p, Vec_Int_t ** pvXors, int fVerbose ); extern Vec_Int_t * Gia_PolynCoreOrder( Gia_Man_t * pGia, Vec_Int_t * vAdds, Vec_Int_t * vAddCos, Vec_Int_t ** pvIns, Vec_Int_t ** pvOuts ); extern int Ree_ManCountFadds( Vec_Int_t * vAdds ); extern void Ree_ManPrintAdders( Vec_Int_t * vAdds, int fVerbose ); abctime clk = Abc_Clock(); - Vec_Int_t * vAdds = Ree_ManComputeCuts( p, 1 ); + Vec_Int_t * vAdds = Ree_ManComputeCuts( p, NULL, 1 ); Vec_Int_t * vIns, * vOuts; Vec_Int_t * vOrder = Gia_PolynCoreOrder( p, vAdds, NULL, &vIns, &vOuts ); int nTrees, nFadds = Ree_ManCountFadds( vAdds ); diff --git a/src/proof/acec/acecPool.c b/src/proof/acec/acecPool.c index 294066fa..08ee37f2 100644 --- a/src/proof/acec/acecPool.c +++ b/src/proof/acec/acecPool.c @@ -34,6 +34,319 @@ ABC_NAMESPACE_IMPL_START /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Acec_ManCreateCarryMap( Gia_Man_t * p, Vec_Int_t * vAdds ) +{ + // map carries into their boxes + Vec_Int_t * vCarryMap = Vec_IntStartFull( Gia_ManObjNum(p) ); int i; + for ( i = 0; 6*i < Vec_IntSize(vAdds); i++ ) + Vec_IntWriteEntry( vCarryMap, Vec_IntEntry(vAdds, 6*i+4), i ); + return vCarryMap; +} +int Acec_ManCheckCarryMap( Gia_Man_t * p, int Carry, Vec_Int_t * vAdds, Vec_Int_t * vCarryMap ) +{ + int iBox = Vec_IntEntry( vCarryMap, Carry ); + assert( iBox >= 0 ); + return Vec_IntEntry( vCarryMap, Vec_IntEntry(vAdds, 6*iBox+0) ) >= 0 || + Vec_IntEntry( vCarryMap, Vec_IntEntry(vAdds, 6*iBox+1) ) >= 0 || + Vec_IntEntry( vCarryMap, Vec_IntEntry(vAdds, 6*iBox+2) ) >= 0; +} +Vec_Int_t * Acec_ManCollectCarryRoots( Gia_Man_t * p, Vec_Int_t * vAdds ) +{ + Vec_Int_t * vCarryRoots = Vec_IntAlloc( 100 ); + Vec_Bit_t * vIns = Vec_BitStart( Gia_ManObjNum(p) ); int i; + // marks box inputs + for ( i = 0; 6*i < Vec_IntSize(vAdds); i++ ) + { + Vec_BitWriteEntry( vIns, Vec_IntEntry(vAdds, 6*i+0), 1 ); + Vec_BitWriteEntry( vIns, Vec_IntEntry(vAdds, 6*i+1), 1 ); + Vec_BitWriteEntry( vIns, Vec_IntEntry(vAdds, 6*i+2), 1 ); + } + // collect roots + for ( i = 0; 6*i < Vec_IntSize(vAdds); i++ ) + if ( !Vec_BitEntry(vIns, Vec_IntEntry(vAdds, 6*i+4)) ) + Vec_IntPush( vCarryRoots, Vec_IntEntry(vAdds, 6*i+4) ); + Vec_BitFree( vIns ); + return vCarryRoots; +} +Vec_Int_t * Acec_ManCollectXorRoots( Gia_Man_t * p, Vec_Int_t * vXors ) +{ + Vec_Int_t * vXorRoots = Vec_IntAlloc( 100 ); + Vec_Bit_t * vIns = Vec_BitStart( Gia_ManObjNum(p) ); int i; + // marks box inputs + for ( i = 0; 4*i < Vec_IntSize(vXors); i++ ) + { + Vec_BitWriteEntry( vIns, Vec_IntEntry(vXors, 4*i+1), 1 ); + Vec_BitWriteEntry( vIns, Vec_IntEntry(vXors, 4*i+2), 1 ); + Vec_BitWriteEntry( vIns, Vec_IntEntry(vXors, 4*i+3), 1 ); + } + // collect roots + for ( i = 0; 4*i < Vec_IntSize(vXors); i++ ) + if ( !Vec_BitEntry(vIns, Vec_IntEntry(vXors, 4*i)) ) + Vec_IntPush( vXorRoots, Vec_IntEntry(vXors, 4*i) ); + Vec_BitFree( vIns ); + return vXorRoots; +} +void Acec_ManCountXorTreeInputs_rec( Gia_Man_t * p, int Node, Vec_Int_t * vXors, Vec_Int_t * vXorMap, Vec_Bit_t * vIsCarryRoot, Vec_Int_t * vCarryRootSet, Vec_Int_t * vXorSet ) +{ + int k, iXorBox; + if ( Node == 0 || Gia_ObjIsTravIdCurrentId(p, Node) ) + return; + Gia_ObjSetTravIdCurrentId(p, Node); + iXorBox = Vec_IntEntry( vXorMap, Node ); + if ( iXorBox == -1 ) + { + if ( Vec_BitEntry(vIsCarryRoot, Node) ) + Vec_IntPush( vCarryRootSet, Node ); + return; + } + for ( k = 1; k < 4; k++ ) + Acec_ManCountXorTreeInputs_rec( p, Vec_IntEntry(vXors, 4*iXorBox+k), vXors, vXorMap, vIsCarryRoot, vCarryRootSet, vXorSet ); + Vec_IntPush( vXorSet, Vec_IntEntry(vXors, 4*iXorBox) ); +} +Vec_Wec_t * Acec_ManCollectCarryRootSets( Gia_Man_t * p, Vec_Int_t * vAdds, Vec_Int_t * vCarryMap, Vec_Int_t * vXors, Vec_Int_t * vXorRoots, Vec_Int_t * vCarryRoots ) +{ + Vec_Wec_t * vCarryRootSets = Vec_WecAlloc( 100 ); // XorBoxes, CarryRoots, AdderBoxes, Ins/Ranks, Outs/Ranks + Vec_Int_t * vCarryRootSet = Vec_IntAlloc( 100 ); + Vec_Bit_t * vIsCarryRoot = Vec_BitStart( Gia_ManObjNum(p) ); + Vec_Int_t * vXorSet = Vec_IntAlloc( 100 ), * vLevel; + int i, k, XorRoot, CarryRoot; + // map XORs into their cuts + Vec_Int_t * vXorMap = Vec_IntStartFull( Gia_ManObjNum(p) ); + for ( i = 0; 4*i < Vec_IntSize(vXors); i++ ) + Vec_IntWriteEntry( vXorMap, Vec_IntEntry(vXors, 4*i), i ); + // create carry root marks + Vec_IntForEachEntry( vCarryRoots, CarryRoot, i ) + Vec_BitWriteEntry( vIsCarryRoot, CarryRoot, 1 ); + // collect carry roots attached to each XOR root + Vec_IntForEachEntry( vXorRoots, XorRoot, i ) + { + Vec_IntClear( vXorSet ); + Vec_IntClear( vCarryRootSet ); + Gia_ManIncrementTravId( p ); + Acec_ManCountXorTreeInputs_rec( p, XorRoot, vXors, vXorMap, vIsCarryRoot, vCarryRootSet, vXorSet ); + // skip trivial + Vec_IntForEachEntry( vCarryRootSet, CarryRoot, k ) + if ( Acec_ManCheckCarryMap(p, CarryRoot, vAdds, vCarryMap) ) + break; + if ( k == Vec_IntSize(vCarryRootSet) ) + continue; + Vec_IntSort( vCarryRootSet, 0 ); + vLevel = Vec_WecPushLevel( vCarryRootSets ); + Vec_IntAppend( vLevel, vXorSet ); + vLevel = Vec_WecPushLevel( vCarryRootSets ); + Vec_IntAppend( vLevel, vCarryRootSet ); + vLevel = Vec_WecPushLevel( vCarryRootSets ); + vLevel = Vec_WecPushLevel( vCarryRootSets ); + vLevel = Vec_WecPushLevel( vCarryRootSets ); + // unmark carry root set + Vec_IntForEachEntry( vCarryRootSet, CarryRoot, k ) + { + assert( Vec_BitEntry(vIsCarryRoot, CarryRoot) ); + Vec_BitWriteEntry( vIsCarryRoot, CarryRoot, 0 ); + } + } + Vec_IntFree( vCarryRootSet ); + Vec_IntFree( vXorSet ); + Vec_IntFree( vXorMap ); + // collect unmarked carry roots + Vec_IntForEachEntry( vCarryRoots, CarryRoot, k ) + { + if ( !Vec_BitEntry(vIsCarryRoot, CarryRoot) ) + continue; + if ( !Acec_ManCheckCarryMap(p, CarryRoot, vAdds, vCarryMap) ) + continue; + vLevel = Vec_WecPushLevel( vCarryRootSets ); + vLevel = Vec_WecPushLevel( vCarryRootSets ); + Vec_IntFill( vLevel, 1, CarryRoot ); + vLevel = Vec_WecPushLevel( vCarryRootSets ); + vLevel = Vec_WecPushLevel( vCarryRootSets ); + vLevel = Vec_WecPushLevel( vCarryRootSets ); + } + Vec_BitFree( vIsCarryRoot ); + return vCarryRootSets; +} +int Acec_ManCompareTwo( int * pPair0, int * pPair1 ) +{ + if ( pPair0[1] < pPair1[1] ) return -1; + if ( pPair0[1] > pPair1[1] ) return 1; + return 0; +} +void Acec_ManCollectInsOuts( Gia_Man_t * p, Vec_Int_t * vAdds, Vec_Int_t * vBoxes, Vec_Int_t * vBoxRanks, Vec_Bit_t * vBoxIns, Vec_Bit_t * vBoxOuts, Vec_Int_t * vResIns, Vec_Int_t * vResOuts ) +{ + int i, k, iBox, iObj, Rank, RankMax = 0; + // mark box inputs/outputs + Vec_IntForEachEntry( vBoxes, iBox, i ) + { + Vec_BitWriteEntry( vBoxIns, Vec_IntEntry(vAdds, 6*iBox+0), 1 ); + Vec_BitWriteEntry( vBoxIns, Vec_IntEntry(vAdds, 6*iBox+1), 1 ); + Vec_BitWriteEntry( vBoxIns, Vec_IntEntry(vAdds, 6*iBox+2), 1 ); + Vec_BitWriteEntry( vBoxOuts, Vec_IntEntry(vAdds, 6*iBox+3), 1 ); + Vec_BitWriteEntry( vBoxOuts, Vec_IntEntry(vAdds, 6*iBox+4), 1 ); + } + // collect unmarked inputs/output and their ranks + Vec_IntForEachEntry( vBoxes, iBox, i ) + { + for ( k = 0; k < 3; k++ ) + if ( !Vec_BitEntry(vBoxOuts, Vec_IntEntry(vAdds, 6*iBox+k)) ) + Vec_IntPushTwo( vResIns, Vec_IntEntry(vAdds, 6*iBox+k), Vec_IntEntry(vBoxRanks, iBox) ); + for ( k = 3; k < 5; k++ ) + if ( Vec_IntEntry(vAdds, 6*iBox+k) && !Vec_BitEntry(vBoxIns, Vec_IntEntry(vAdds, 6*iBox+k)) ) + Vec_IntPushTwo( vResOuts, Vec_IntEntry(vAdds, 6*iBox+k), Vec_IntEntry(vBoxRanks, iBox)-(int)(k==4) ); + } + // unmark box inputs/outputs + Vec_IntForEachEntry( vBoxes, iBox, i ) + { + Vec_BitWriteEntry( vBoxIns, Vec_IntEntry(vAdds, 6*iBox+0), 0 ); + Vec_BitWriteEntry( vBoxIns, Vec_IntEntry(vAdds, 6*iBox+1), 0 ); + Vec_BitWriteEntry( vBoxIns, Vec_IntEntry(vAdds, 6*iBox+2), 0 ); + Vec_BitWriteEntry( vBoxOuts, Vec_IntEntry(vAdds, 6*iBox+3), 0 ); + Vec_BitWriteEntry( vBoxOuts, Vec_IntEntry(vAdds, 6*iBox+4), 0 ); + } + // normalize ranks + Vec_IntForEachEntryDouble( vResIns, iObj, Rank, k ) + RankMax = Abc_MaxInt( RankMax, Rank ); + Vec_IntForEachEntryDouble( vResOuts, iObj, Rank, k ) + RankMax = Abc_MaxInt( RankMax, Rank ); + Vec_IntForEachEntryDouble( vResIns, iObj, Rank, k ) + Vec_IntWriteEntry( vResIns, k+1, 1 + RankMax - Rank ); + Vec_IntForEachEntryDouble( vResOuts, iObj, Rank, k ) + Vec_IntWriteEntry( vResOuts, k+1, 1 + RankMax - Rank ); + // sort by rank + qsort( Vec_IntArray(vResIns), Vec_IntSize(vResIns)/2, 8, (int (*)(const void *, const void *))Acec_ManCompareTwo ); + qsort( Vec_IntArray(vResOuts), Vec_IntSize(vResOuts)/2, 8, (int (*)(const void *, const void *))Acec_ManCompareTwo ); +} +void Acec_ManCollectBoxSets_rec( Gia_Man_t * p, int Carry, int iRank, Vec_Int_t * vAdds, Vec_Int_t * vCarryMap, Vec_Int_t * vBoxes, Vec_Int_t * vBoxRanks ) +{ + int iBox = Vec_IntEntry( vCarryMap, Carry ); + if ( iBox == -1 ) + return; + Acec_ManCollectBoxSets_rec( p, Vec_IntEntry(vAdds, 6*iBox+0), iRank+1, vAdds, vCarryMap, vBoxes, vBoxRanks ); + Acec_ManCollectBoxSets_rec( p, Vec_IntEntry(vAdds, 6*iBox+1), iRank+1, vAdds, vCarryMap, vBoxes, vBoxRanks ); + if ( Vec_IntEntry(vAdds, 6*iBox+2) ) + Acec_ManCollectBoxSets_rec( p, Vec_IntEntry(vAdds, 6*iBox+2), iRank+1, vAdds, vCarryMap, vBoxes, vBoxRanks ); + Vec_IntPush( vBoxes, iBox ); + Vec_IntWriteEntry( vBoxRanks, iBox, iRank ); +} +Vec_Wec_t * Acec_ManCollectBoxSets( Gia_Man_t * p, Vec_Int_t * vAdds, Vec_Int_t * vXors ) +{ + Vec_Int_t * vCarryMap = Acec_ManCreateCarryMap( p, vAdds ); + Vec_Int_t * vCarryRoots = Acec_ManCollectCarryRoots( p, vAdds ); + Vec_Int_t * vXorRoots = Acec_ManCollectXorRoots( p, vXors ); + Vec_Wec_t * vBoxSets = Acec_ManCollectCarryRootSets( p, vAdds, vCarryMap, vXors, vXorRoots, vCarryRoots ); + Vec_Int_t * vBoxRanks = Vec_IntStart( Vec_IntSize(vAdds)/6 ); + Vec_Bit_t * vBoxIns = Vec_BitStart( Gia_ManObjNum(p) ); + Vec_Bit_t * vBoxOuts = Vec_BitStart( Gia_ManObjNum(p) ); int i, k, Root; + Vec_IntFree( vCarryRoots ); + Vec_IntFree( vXorRoots ); + // collect boxes for each carry set + assert( Vec_WecSize(vBoxSets) % 5 == 0 ); + for ( i = 0; 5*i < Vec_WecSize(vBoxSets); i++ ) + { + Vec_Int_t * vRoots = Vec_WecEntry( vBoxSets, 5*i+1 ); + Vec_Int_t * vBoxes = Vec_WecEntry( vBoxSets, 5*i+2 ); + Vec_Int_t * vIns = Vec_WecEntry( vBoxSets, 5*i+3 ); + Vec_Int_t * vOuts = Vec_WecEntry( vBoxSets, 5*i+4 ); + Vec_IntForEachEntry( vRoots, Root, k ) + Acec_ManCollectBoxSets_rec( p, Root, 1, vAdds, vCarryMap, vBoxes, vBoxRanks ); + Acec_ManCollectInsOuts( p, vAdds, vBoxes, vBoxRanks, vBoxIns, vBoxOuts, vIns, vOuts ); + } + Vec_IntFree( vBoxRanks ); + Vec_BitFree( vBoxIns ); + Vec_BitFree( vBoxOuts ); + Vec_IntFree( vCarryMap ); + return vBoxSets; +} +void Acec_ManPrintRanks2( Vec_Int_t * vPairs ) +{ + int k, iObj, Rank; + Vec_IntForEachEntryDouble( vPairs, iObj, Rank, k ) + printf( "%d ", Rank ); + printf( "\n" ); +} +void Acec_ManPrintRanks( Vec_Int_t * vPairs ) +{ + int k, iObj, Count, Rank, RankMax = 0; + Vec_Int_t * vCounts = Vec_IntStart( 100 ); + Vec_IntForEachEntryDouble( vPairs, iObj, Rank, k ) + { + Vec_IntFillExtra( vCounts, Rank+1, 0 ); + Vec_IntAddToEntry( vCounts, Rank, 1 ); + RankMax = Abc_MaxInt( RankMax, Rank ); + } + Vec_IntForEachEntryStartStop( vCounts, Count, Rank, 1, RankMax+1 ) + printf( "%2d=%2d ", Rank, Count ); + printf( "\n" ); + Vec_IntFree( vCounts ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Acec_ManProfile( Gia_Man_t * p, int fVerbose ) +{ + extern Vec_Int_t * Ree_ManComputeCuts( Gia_Man_t * p, Vec_Int_t ** pvXors, int fVerbose ); + extern void Ree_ManRemoveTrivial( Gia_Man_t * p, Vec_Int_t * vAdds ); + extern void Ree_ManRemoveContained( Gia_Man_t * p, Vec_Int_t * vAdds ); + extern int Ree_ManCountFadds( Vec_Int_t * vAdds ); + extern void Ree_ManPrintAdders( Vec_Int_t * vAdds, int fVerbose ); + + abctime clk = Abc_Clock(); + Vec_Wec_t * vBoxes; int i; + Vec_Int_t * vXors, * vAdds = Ree_ManComputeCuts( p, &vXors, fVerbose ); + Ree_ManRemoveTrivial( p, vAdds ); + Ree_ManRemoveContained( p, vAdds ); + + //Ree_ManPrintAdders( vAdds, 1 ); + printf( "Detected %d full-adders and %d half-adders. Found %d XOR-cuts. ", Ree_ManCountFadds(vAdds), Vec_IntSize(vAdds)/6-Ree_ManCountFadds(vAdds), Vec_IntSize(vXors)/4 ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + + clk = Abc_Clock(); + vBoxes = Acec_ManCollectBoxSets( p, vAdds, vXors ); + printf( "Detected %d adder-tree%s. ", Vec_WecSize(vBoxes)/5, Vec_WecSize(vBoxes)/5 > 1 ? "s":"" ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + + if ( fVerbose ) + for ( i = 0; 5*i < Vec_WecSize(vBoxes); i++ ) + { + printf( "Tree %3d : ", i ); + printf( "Xor = %4d ", Vec_IntSize(Vec_WecEntry(vBoxes,5*i+0)) ); + printf( "Root = %4d ", Vec_IntSize(Vec_WecEntry(vBoxes,5*i+1)) ); + //printf( "(Top = %5d) ", Vec_IntEntryLast(Vec_WecEntry(vBoxes,5*i+1)) ); + printf( "Adder = %4d ", Vec_IntSize(Vec_WecEntry(vBoxes,5*i+2)) ); + printf( "In = %4d ", Vec_IntSize(Vec_WecEntry(vBoxes,5*i+3))/2 ); + printf( "Out = %4d ", Vec_IntSize(Vec_WecEntry(vBoxes,5*i+4))/2 ); + printf( "\n" ); + printf( " Ins: " ); + Acec_ManPrintRanks( Vec_WecEntry(vBoxes,5*i+3) ); + printf( " Outs: " ); + Acec_ManPrintRanks( Vec_WecEntry(vBoxes,5*i+4) ); + } + + Vec_IntFree( vXors ); + Vec_IntFree( vAdds ); + Vec_WecFree( vBoxes ); +} + + /**Function************************************************************* Synopsis [] @@ -83,7 +396,7 @@ Vec_Int_t * Acec_ManPoolTopMost( Gia_Man_t * p, Vec_Int_t * vAdds ) } void Acec_ManPool( Gia_Man_t * p ) { - extern Vec_Int_t * Ree_ManComputeCuts( Gia_Man_t * p, int fVerbose ); + extern Vec_Int_t * Ree_ManComputeCuts( Gia_Man_t * p, Vec_Int_t ** pvXors, int fVerbose ); extern Vec_Wec_t * Gia_PolynCoreOrderArray( Gia_Man_t * pGia, Vec_Int_t * vAdds, Vec_Int_t * vRootBoxes ); extern int Ree_ManCountFadds( Vec_Int_t * vAdds ); @@ -94,7 +407,7 @@ void Acec_ManPool( Gia_Man_t * p ) Vec_Wec_t * vTrees; abctime clk = Abc_Clock(); - Vec_Int_t * vAdds = Ree_ManComputeCuts( p, 1 ); + Vec_Int_t * vAdds = Ree_ManComputeCuts( p, NULL, 1 ); int i, nFadds = Ree_ManCountFadds( vAdds ); printf( "Detected %d FAs and %d HAs. ", nFadds, Vec_IntSize(vAdds)/6-nFadds ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); diff --git a/src/proof/acec/acecRe.c b/src/proof/acec/acecRe.c index e2340dba..26faad00 100644 --- a/src/proof/acec/acecRe.c +++ b/src/proof/acec/acecRe.c @@ -248,10 +248,11 @@ void Ree_ManCutPrint( int * pCut, int Count, word Truth ) Abc_TtPrintHexRev( stdout, &Truth, 3 ); printf( "\n" ); } -void Ree_ManCutMerge( Gia_Man_t * p, int iObj, int * pList0, int * pList1, Vec_Int_t * vCuts, Hash_IntMan_t * pHash, Vec_Int_t * vData ) +void Ree_ManCutMerge( Gia_Man_t * p, int iObj, int * pList0, int * pList1, Vec_Int_t * vCuts, Hash_IntMan_t * pHash, Vec_Int_t * vData, Vec_Int_t * vXors ) { int fVerbose = 0; int i, k, c, Value, Truth, TruthC, * pCut0, * pCut1, pCut[6], Count = 0; + int iXor2 = -1, iXor3 = -1; if ( fVerbose ) printf( "Object %d\n", iObj ); Vec_IntFill( vCuts, 2, 1 ); @@ -266,12 +267,16 @@ void Ree_ManCutMerge( Gia_Man_t * p, int iObj, int * pList0, int * pList1, Vec_I continue; Truth = TruthC = Ree_ManCutTruth(Gia_ManObj(p, iObj), pCut0, pCut1, pCut); //assert( Truth == Ree_ObjComputeTruth(p, iObj, pCut) ); + if ( Truth & 0x80 ) + Truth = 0xFF & ~Truth; + if ( Truth == 0x66 && iXor2 == -1 ) + iXor2 = Vec_IntSize(vCuts); + else if ( Truth == 0x69 && iXor3 == -1 ) + iXor3 = Vec_IntSize(vCuts); Vec_IntAddToEntry( vCuts, 0, 1 ); for ( c = 0; c <= pCut[0]; c++ ) Vec_IntPush( vCuts, pCut[c] ); - Vec_IntPush( vCuts, Truth ); - if ( Truth & 0x80 ) - Truth = 0xFF & ~Truth; + Vec_IntPush( vCuts, TruthC ); if ( (Truth == 0x66 || Truth == 0x11 || Truth == 0x22 || Truth == 0x44 || Truth == 0x77) && pCut[0] == 2 ) { assert( pCut[0] == 2 ); @@ -287,6 +292,19 @@ void Ree_ManCutMerge( Gia_Man_t * p, int iObj, int * pList0, int * pList1, Vec_I if ( fVerbose ) Ree_ManCutPrint( pCut, ++Count, TruthC ); } + if ( !vXors ) + return; + if ( iXor2 > 0 ) + pCut0 = Vec_IntEntryP( vCuts, iXor2 ); + else if ( iXor3 > 0 ) + pCut0 = Vec_IntEntryP( vCuts, iXor3 ); + else + return; + Vec_IntPush( vXors, iObj ); + for ( c = 1; c <= pCut0[0]; c++ ) + Vec_IntPush( vXors, pCut0[c] ); + if ( pCut0[0] == 2 ) + Vec_IntPush( vXors, 0 ); } /**Function************************************************************* @@ -300,7 +318,7 @@ void Ree_ManCutMerge( Gia_Man_t * p, int iObj, int * pList0, int * pList1, Vec_I SeeAlso [] ***********************************************************************/ -Vec_Int_t * Ree_ManDeriveAdds( Hash_IntMan_t * p, Vec_Int_t * vData ) +Vec_Int_t * Ree_ManDeriveAdds( Hash_IntMan_t * p, Vec_Int_t * vData, int fVerbose ) { int i, j, k, iObj, iObj2, Value, Truth, Truth2, CountX, CountM, Index = 0; int nEntries = Hash_IntManEntryNum(p); @@ -327,7 +345,8 @@ Vec_Int_t * Ree_ManDeriveAdds( Hash_IntMan_t * p, Vec_Int_t * vData ) } Vec_IntFree( vXors ); Vec_IntFree( vMajs ); - printf( "Detected %d shared cuts among %d hashed cuts.\n", Index, nEntries ); + //if ( fVerbose ) + // printf( "Detected %d shared cuts among %d hashed cuts.\n", Index, nEntries ); // collect nodes vXorMap = Vec_WecStart( Index ); vMajMap = Vec_WecStart( Index ); @@ -371,7 +390,7 @@ Vec_Int_t * Ree_ManDeriveAdds( Hash_IntMan_t * p, Vec_Int_t * vData ) Vec_WecFree( vMajMap ); return vAdds; } -Vec_Int_t * Ree_ManComputeCuts( Gia_Man_t * p, int fVerbose ) +Vec_Int_t * Ree_ManComputeCuts( Gia_Man_t * p, Vec_Int_t ** pvXors, int fVerbose ) { Gia_Obj_t * pObj; int * pList0, * pList1, i, nCuts = 0; @@ -390,23 +409,24 @@ Vec_Int_t * Ree_ManComputeCuts( Gia_Man_t * p, int fVerbose ) Vec_IntPush( vCuts, Gia_ObjId(p, pObj) ); Vec_IntPush( vCuts, 0xAA ); } + if ( pvXors ) *pvXors = Vec_IntAlloc( 1000 ); Gia_ManForEachAnd( p, pObj, i ) { pList0 = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, Gia_ObjFaninId0(pObj, i)) ); pList1 = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, Gia_ObjFaninId1(pObj, i)) ); - Ree_ManCutMerge( p, i, pList0, pList1, vTemp, pHash, vData ); + Ree_ManCutMerge( p, i, pList0, pList1, vTemp, pHash, vData, pvXors ? *pvXors : NULL ); Vec_IntWriteEntry( vCuts, i, Vec_IntSize(vCuts) ); Vec_IntAppend( vCuts, vTemp ); nCuts += Vec_IntEntry( vTemp, 0 ); } if ( fVerbose ) - printf( "Nodes = %d. Cuts = %d. Cuts/Node = %.2f. Ints/Node = %.2f.\n", + printf( "AIG nodes = %d. Cuts = %d. Cuts/Node = %.2f. Ints/Node = %.2f.\n", Gia_ManAndNum(p), nCuts, 1.0*nCuts/Gia_ManAndNum(p), 1.0*Vec_IntSize(vCuts)/Gia_ManAndNum(p) ); Vec_IntFree( vTemp ); Vec_IntFree( vCuts ); - vAdds = Ree_ManDeriveAdds( pHash, vData ); + vAdds = Ree_ManDeriveAdds( pHash, vData, fVerbose ); if ( fVerbose ) - printf( "Adds = %d. Total = %d. Hashed = %d. Hashed/Adds = %.2f.\n", + printf( "Adders = %d. Total cuts = %d. Hashed cuts = %d. Hashed/Adders = %.2f.\n", Vec_IntSize(vAdds)/6, Vec_IntSize(vData)/3, Hash_IntManEntryNum(pHash), 6.0*Hash_IntManEntryNum(pHash)/Vec_IntSize(vAdds) ); Vec_IntFree( vData ); Hash_IntManStop( pHash ); @@ -539,7 +559,7 @@ void Ree_ManPrintAdders( Vec_Int_t * vAdds, int fVerbose ) void Ree_ManComputeCutsTest( Gia_Man_t * p ) { abctime clk = Abc_Clock(); - Vec_Int_t * vAdds = Ree_ManComputeCuts( p, 1 ); + Vec_Int_t * vAdds = Ree_ManComputeCuts( p, NULL, 1 ); int nFadds = Ree_ManCountFadds( vAdds ); Ree_ManPrintAdders( vAdds, 1 ); printf( "Detected %d FAs and %d HAs. ", nFadds, Vec_IntSize(vAdds)/6-nFadds ); -- cgit v1.2.3 From 8ba6071a76b2f25995c4048567eb0b3780130ece Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 4 Dec 2016 21:59:10 -0800 Subject: New SAT-based optimization package. --- src/aig/gia/giaMuxes.c | 2 +- src/base/abci/abc.c | 11 ++- src/opt/dau/dauGia.c | 8 ++- src/opt/sbd/sbd.h | 1 + src/opt/sbd/sbdCore.c | 180 ++++++++++++++++++++++++++++++++++++++++--------- src/opt/sbd/sbdWin.c | 5 +- 6 files changed, 168 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/aig/gia/giaMuxes.c b/src/aig/gia/giaMuxes.c index c38cbf43..4ce109f6 100644 --- a/src/aig/gia/giaMuxes.c +++ b/src/aig/gia/giaMuxes.c @@ -100,7 +100,7 @@ Gia_Man_t * Gia_ManDupMuxes( Gia_Man_t * p, int Limit ) Gia_Obj_t * pObj, * pFan0, * pFan1, * pFanC, * pSiblNew, * pObjNew; int i; assert( p->pMuxes == NULL ); - assert( Limit >= 1 ); // allows to create AIG with XORs without MUXes + assert( Limit >= 0 ); // allows to create AIG with XORs without MUXes ABC_FREE( p->pRefs ); Gia_ManCreateRefs( p ); // start the new manager diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index ba4d37b3..1fdffd77 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -27643,6 +27643,7 @@ static inline int Gia_ManCompareWithBest( Gia_Man_t * pBest, Gia_Man_t * p, int *pnBestLuts = nCurLuts; *pnBestEdges = nCurEdges; *pnBestLevels = nCurLevels; + //printf( "\nUpdating best (%d %d %d).\n\n", nCurLuts, nCurEdges, nCurLevels ); return 1; } return 0; @@ -31023,7 +31024,7 @@ usage: Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-S num : the max number of SAT variables [default = %d]\n", pPars->nSatVarMax ); Abc_Print( -2, "\t-K num : the target LUT size for downstream mapping [default = %d]\n", nLutSize ); - Abc_Print( -2, "\t-R num : the delay relaxation ratio (num >= 0) [default = %d]\n", nRelaxRatio ); + Abc_Print( -2, "\t-R num : the delay relaxation ratio (num >= 0) [default = %d]\n", nRelaxRatio ); Abc_Print( -2, "\t-f : toggle using lighter logic synthesis [default = %s]\n", pPars->fLightSynth? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -40852,7 +40853,7 @@ int Abc_CommandAbc9Mfsd( Abc_Frame_t * pAbc, int argc, char ** argv ) Sbd_Par_t Pars, * pPars = &Pars; Sbd_ParSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KWFMCavwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KWFMCacvwh" ) ) != EOF ) { switch ( c ) { @@ -40914,6 +40915,9 @@ int Abc_CommandAbc9Mfsd( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'a': pPars->fArea ^= 1; break; + case 'c': + pPars->fCover ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -40946,7 +40950,7 @@ int Abc_CommandAbc9Mfsd( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &mfsd [-KWFMC ] [-avwh]\n" ); + Abc_Print( -2, "usage: &mfsd [-KWFMC ] [-acvwh]\n" ); Abc_Print( -2, "\t performs SAT-based delay-oriented AIG optimization\n" ); Abc_Print( -2, "\t-K : the LUT size for delay minimization (2 <= num <= 6) [default = %d]\n", pPars->nLutSize ); Abc_Print( -2, "\t-W : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nTfoLevels ); @@ -40954,6 +40958,7 @@ usage: Abc_Print( -2, "\t-M : the max node count of windows to consider (0 = no limit) [default = %d]\n", pPars->nWinSizeMax ); Abc_Print( -2, "\t-C : the max number of conflicts in one SAT run (0 = no limit) [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-a : toggle minimizing area or area+edges [default = %s]\n", pPars->fArea? "area": "area+edges" ); + Abc_Print( -2, "\t-c : toggle using complete slow covering procedure [default = %s]\n", pPars->fCover? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); diff --git a/src/opt/dau/dauGia.c b/src/opt/dau/dauGia.c index c7f5c11f..6489cd86 100644 --- a/src/opt/dau/dauGia.c +++ b/src/opt/dau/dauGia.c @@ -243,7 +243,11 @@ int Dau_DsdBalance( Gia_Man_t * pGia, int * pFans, int nFans, int fAnd ) if ( fAnd ) iFan = Gia_ManAppendAnd( pGia, iFan0, iFan1 ); else if ( pGia->pMuxes ) - iFan = Gia_ManAppendXorReal( pGia, iFan0, iFan1 ); + { + 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 ); } @@ -369,7 +373,7 @@ int Dau_DsdToGia_rec( Gia_Man_t * pGia, char * pStr, char ** p, int * pMatches, 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 { diff --git a/src/opt/sbd/sbd.h b/src/opt/sbd/sbd.h index e1e39a3b..89d29958 100644 --- a/src/opt/sbd/sbd.h +++ b/src/opt/sbd/sbd.h @@ -45,6 +45,7 @@ struct Sbd_Par_t_ 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 }; diff --git a/src/opt/sbd/sbdCore.c b/src/opt/sbd/sbdCore.c index f5c944c9..b6ec70f9 100644 --- a/src/opt/sbd/sbdCore.c +++ b/src/opt/sbd/sbdCore.c @@ -20,6 +20,7 @@ #include "sbdInt.h" #include "opt/dau/dau.h" +#include "misc/tim/tim.h" ABC_NAMESPACE_IMPL_START @@ -97,6 +98,7 @@ void Sbd_ParSetDefault( Sbd_Par_t * pPars ) 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 } @@ -467,6 +469,14 @@ int Sbd_ManCheckConst( Sbd_Man_t * p, int Pivot ) 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 ); @@ -822,7 +832,7 @@ static inline int Sbd_ManAddCube2( word Cover[2][64], int nRows, word Cube[2] ) return nRows; } -static inline int Sbd_ManFindCands( Sbd_Man_t * p, word Cover[64], int nDivs ) +static inline int Sbd_ManFindCandsSimple( Sbd_Man_t * p, word Cover[64], int nDivs ) { int c0, c1, c2, c3; word Target = Cover[nDivs]; @@ -871,6 +881,72 @@ static inline int Sbd_ManFindCands( Sbd_Man_t * p, word Cover[64], int nDivs ) 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; @@ -1158,7 +1234,7 @@ int Sbd_ManMergeCuts( Sbd_Man_t * p, int Node ) 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 == Abc_MaxInt(Level0, Level1); + return LevCur == 1; // LevCur == Abc_MaxInt(Level0, Level1); } int Sbd_ManDelay( Sbd_Man_t * p ) { @@ -1223,11 +1299,11 @@ void Sbd_ManFindCut( Sbd_Man_t * p, int Node, Vec_Int_t * vCutLits ) 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; - Gia_Obj_t * pObj; // collect leaf literals Vec_IntClear( p->vLits ); Vec_IntForEachEntry( p->vDivVars, Node, i ) @@ -1239,12 +1315,13 @@ int Sbd_ManImplement( Sbd_Man_t * p, int Pivot, word Truth ) Vec_IntPush( p->vLits, Abc_Var2Lit(Node, 0) ); } // pretend to have MUXes - assert( p->pGia->pMuxes == NULL ); - if ( p->pGia->nXors ) +// 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 ); - p->pGia->pMuxes = NULL; + 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 ); @@ -1323,6 +1400,8 @@ Gia_Man_t * Sbd_ManDerive( Gia_Man_t * p, Vec_Int_t * vMirrors ) 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 ) @@ -1333,6 +1412,7 @@ Gia_Man_t * Sbd_ManDerive( Gia_Man_t * p, Vec_Int_t * vMirrors ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Gia_ManTransferTiming( pNew, p ); return pNew; } @@ -1347,36 +1427,69 @@ Gia_Man_t * Sbd_ManDerive( Gia_Man_t * p, Vec_Int_t * vMirrors ) 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 RetValue, Pivot; word Truth = 0; + int k, Pivot; assert( pPars->nLutSize <= 6 ); //Sbd_ManMergeTest( p ); //return NULL; - Gia_ManForEachAndId( pGia, Pivot ) + if ( pGia->pManTime != NULL && Tim_ManBoxNum((Tim_Man_t*)pGia->pManTime) ) { - if ( Pivot >= nNodesOld ) - break; - if ( Sbd_ManMergeCuts( p, Pivot ) ) - continue; - //if ( Pivot != 344 ) - // continue; - if ( p->pPars->fVerbose ) - printf( "\nLooking at node %d\n", Pivot ); - if ( Sbd_ManWindow( p, Pivot ) ) - continue; - RetValue = Sbd_ManCheckConst( p, Pivot ); - if ( RetValue >= 0 ) - Vec_IntWriteEntry( p->vMirrors, Pivot, RetValue ); - else if ( Sbd_ManExplore( p, Pivot, &Truth ) ) + 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 ) { - Sbd_ManImplement( p, Pivot, Truth ); - //if ( Count++ == 1 ) - // break; + 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; @@ -1384,13 +1497,16 @@ Gia_Man_t * Sbd_NtkPerform( Gia_Man_t * pGia, Sbd_Par_t * pPars ) pNew = Sbd_ManDerive( pGia, p->vMirrors ); // print runtime statistics p->timeOther = p->timeTotal - p->timeWin - p->timeCnf - p->timeSat - p->timeCov - p->timeEnu; - 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 ); + 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; } diff --git a/src/opt/sbd/sbdWin.c b/src/opt/sbd/sbdWin.c index 7100462b..d722f456 100644 --- a/src/opt/sbd/sbdWin.c +++ b/src/opt/sbd/sbdWin.c @@ -123,7 +123,10 @@ sat_solver * Sbd_ManSatSolver( sat_solver * pSat, Gia_Man_t * p, Vec_Int_t * vMi RetValue = sat_solver_addclause( pSat, Vec_IntArray(vFaninVars), Vec_IntLimit(vFaninVars) ); Vec_IntFree( vFaninVars ); if ( RetValue == 0 ) - return 0; + { + sat_solver_delete( pSat ); + return NULL; + } assert( sat_solver_nvars(pSat) == nVars + 32 ); } // finalize -- cgit v1.2.3 From 6a351c4dc0d4da86d2a82efdecd09021a2e6280f Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 5 Dec 2016 17:45:15 -0800 Subject: Adding support for minimalistic representation of LUT mapping. --- src/aig/gia/gia.h | 2 + src/aig/gia/giaMini.c | 182 +++++++++++++++++++++++++++++ src/aig/miniaig/miniaig.h | 1 + src/aig/miniaig/minilut.h | 288 ++++++++++++++++++++++++++++++++++++++++++++++ src/base/abci/abc.c | 32 ++++-- src/opt/dau/dauGia.c | 2 +- 6 files changed, 496 insertions(+), 11 deletions(-) create mode 100644 src/aig/miniaig/minilut.h (limited to 'src') diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index 3d2d84ae..bf7bf349 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -1382,6 +1382,8 @@ extern Gia_Man_t * Mf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pP /*=== giaMini.c ===========================================================*/ extern Gia_Man_t * Gia_ManReadMiniAig( char * pFileName ); extern void Gia_ManWriteMiniAig( Gia_Man_t * pGia, char * pFileName ); +extern Gia_Man_t * Gia_ManReadMiniLut( char * pFileName ); +extern void Gia_ManWriteMiniLut( Gia_Man_t * pGia, char * pFileName ); /*=== giaMuxes.c ===========================================================*/ extern void Gia_ManCountMuxXor( Gia_Man_t * p, int * pnMuxes, int * pnXors ); extern void Gia_ManPrintMuxStats( Gia_Man_t * p ); diff --git a/src/aig/gia/giaMini.c b/src/aig/gia/giaMini.c index 442be57c..77bb1b64 100644 --- a/src/aig/gia/giaMini.c +++ b/src/aig/gia/giaMini.c @@ -19,8 +19,10 @@ ***********************************************************************/ #include "gia.h" +#include "opt/dau/dau.h" #include "base/main/main.h" #include "aig/miniaig/miniaig.h" +#include "aig/miniaig/minilut.h" ABC_NAMESPACE_IMPL_START @@ -180,6 +182,186 @@ void Gia_ManWriteMiniAig( Gia_Man_t * pGia, char * pFileName ) Mini_AigStop( p ); } + + + +/**Function************************************************************* + + Synopsis [Converts MiniLUT into GIA.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFromMiniLut( Mini_Lut_t * p ) +{ + Gia_Man_t * pGia, * pTemp; + Vec_Int_t * vCopies; + Vec_Int_t * vCover = Vec_IntAlloc( 1000 ); + Vec_Int_t * vLits = Vec_IntAlloc( 100 ); + int i, k, Fan, iGiaLit, nNodes; + int LutSize = Abc_MaxInt( 2, Mini_LutSize(p) ); + assert( LutSize <= 6 ); + // get the number of nodes + nNodes = Mini_LutNodeNum(p); + // create ABC network + pGia = Gia_ManStart( 3 * nNodes ); + pGia->pName = Abc_UtilStrsav( "MiniLut" ); + // create mapping from MiniLUT objects into ABC objects + vCopies = Vec_IntAlloc( nNodes ); + Vec_IntPush( vCopies, 0 ); + Vec_IntPush( vCopies, 1 ); + // iterate through the objects + Gia_ManHashAlloc( pGia ); + for ( i = 2; i < nNodes; i++ ) + { + if ( Mini_LutNodeIsPi( p, i ) ) + iGiaLit = Gia_ManAppendCi(pGia); + else if ( Mini_LutNodeIsPo( p, i ) ) + iGiaLit = Gia_ManAppendCo(pGia, Vec_IntEntry(vCopies, Mini_LutNodeFanin(p, i, 0))); + else if ( Mini_LutNodeIsNode( p, i ) ) + { + unsigned * puTruth = Mini_LutNodeTruth( p, i ); + word Truth = LutSize == 6 ? *(word *)puTruth : ((word)*puTruth << 32) | (word)*puTruth; + Vec_IntClear( vLits ); + Mini_LutForEachFanin( p, i, Fan, k ) + Vec_IntPush( vLits, Vec_IntEntry(vCopies, Fan) ); + iGiaLit = Dsm_ManTruthToGia( pGia, &Truth, vLits, vCover ); + } + else assert( 0 ); + Vec_IntPush( vCopies, iGiaLit ); + } + Vec_IntFree( vCover ); + Vec_IntFree( vLits ); + Gia_ManHashStop( pGia ); + assert( Vec_IntSize(vCopies) == nNodes ); + Vec_IntFree( vCopies ); + Gia_ManSetRegNum( pGia, Mini_LutRegNum(p) ); + pGia = Gia_ManCleanup( pTemp = pGia ); + Gia_ManStop( pTemp ); + return pGia; +} + +/**Function************************************************************* + + Synopsis [Converts GIA into MiniLUT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mini_Lut_t * Gia_ManToMiniLut( Gia_Man_t * pGia ) +{ + Mini_Lut_t * p; + Vec_Wrd_t * vTruths; + Gia_Obj_t * pObj, * pFanin; + int i, k, LutSize, pVars[16]; + word Truth; + assert( Gia_ManHasMapping(pGia) ); + LutSize = Gia_ManLutSizeMax( pGia ); + assert( LutSize >= 2 ); + // create the manager + p = Mini_LutStart( LutSize ); + // create primary inputs + Gia_ManFillValue( pGia ); + Gia_ManForEachCi( pGia, pObj, i ) + pObj->Value = Mini_LutCreatePi(p); + // create internal nodes + vTruths = Vec_WrdStart( Gia_ManObjNum(pGia) ); + Gia_ManForEachLut( pGia, i ) + { + pObj = Gia_ManObj( pGia, i ); + Gia_LutForEachFaninObj( pGia, i, pFanin, k ) + pVars[k] = pFanin->Value; + Truth = Gia_LutComputeTruth6( pGia, i, vTruths ); + pObj->Value = Mini_LutCreateNode( p, Gia_ObjLutSize(pGia, i), pVars, (unsigned *)&Truth ); + } + Vec_WrdFree( vTruths ); + // create primary outputs + Gia_ManForEachCo( pGia, pObj, i ) + { + if ( Gia_ObjFanin0(pObj) == Gia_ManConst0(pGia) ) + pObj->Value = Mini_LutCreatePo( p, Gia_ObjFaninC0(pObj) ); + else if ( !Gia_ObjFaninC0(pObj) ) + pObj->Value = Mini_LutCreatePo( p, Gia_ObjFanin0(pObj)->Value ); + else // add inverter LUT + { + word TruthInv = ABC_CONST(0x5555555555555555); + int Fanin = Gia_ObjFanin0(pObj)->Value; + int LutInv = Mini_LutCreateNode( p, 1, &Fanin, (unsigned *)&TruthInv ); + pObj->Value = Mini_LutCreatePo( p, LutInv ); + } + } + // set registers + Mini_LutSetRegNum( p, Gia_ManRegNum(pGia) ); + Mini_LutPrintStats( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [Procedures to input/output MiniAIG into/from internal GIA.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameGiaInputMiniLut( Abc_Frame_t * pAbc, void * p ) +{ + Gia_Man_t * pGia; + if ( pAbc == NULL ) + printf( "ABC framework is not initialized by calling Abc_Start()\n" ); + pGia = Gia_ManFromMiniLut( (Mini_Lut_t *)p ); + Abc_FrameUpdateGia( pAbc, pGia ); +// Gia_ManDelete( pGia ); +} +void * Abc_FrameGiaOutputMiniLut( Abc_Frame_t * pAbc ) +{ + Gia_Man_t * pGia; + if ( pAbc == NULL ) + printf( "ABC framework is not initialized by calling Abc_Start()\n" ); + pGia = Abc_FrameReadGia( pAbc ); + if ( pGia == NULL ) + printf( "Current network in ABC framework is not defined.\n" ); + return Gia_ManToMiniLut( pGia ); +} + +/**Function************************************************************* + + Synopsis [Procedures to read/write GIA to/from MiniAIG file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManReadMiniLut( char * pFileName ) +{ + Mini_Lut_t * p = Mini_LutLoad( pFileName ); + Gia_Man_t * pGia = Gia_ManFromMiniLut( p ); + ABC_FREE( pGia->pName ); + pGia->pName = Extra_FileNameGeneric( pFileName ); + Mini_LutStop( p ); + return pGia; +} +void Gia_ManWriteMiniLut( Gia_Man_t * pGia, char * pFileName ) +{ + Mini_Lut_t * p = Gia_ManToMiniLut( pGia ); + Mini_LutDump( p, pFileName ); + Mini_LutStop( p ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/miniaig/miniaig.h b/src/aig/miniaig/miniaig.h index dadb578b..6843648e 100644 --- a/src/aig/miniaig/miniaig.h +++ b/src/aig/miniaig/miniaig.h @@ -78,6 +78,7 @@ static void Mini_AigPush( Mini_Aig_t * p, int Lit0, int Lit1 ) { if ( p->nSize + 2 > p->nCap ) { + assert( p->nSize < MINI_AIG_NULL/4 ); if ( p->nCap < MINI_AIG_START_SIZE ) Mini_AigGrow( p, MINI_AIG_START_SIZE ); else diff --git a/src/aig/miniaig/minilut.h b/src/aig/miniaig/minilut.h new file mode 100644 index 00000000..953f0bd3 --- /dev/null +++ b/src/aig/miniaig/minilut.h @@ -0,0 +1,288 @@ +/**CFile**************************************************************** + + FileName [minilut.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic representation of LUT mapped network.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 29, 2012.] + + Revision [$Id: minilut.h,v 1.00 2012/09/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef MINI_LUT__mini_lut_h +#define MINI_LUT__mini_lut_h + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +#define MINI_LUT_NULL (0x7FFFFFFF) +#define MINI_LUT_NULL2 (0x7FFFFFFE) +#define MINI_LUT_START_SIZE (0x000000FF) + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Mini_Lut_t_ Mini_Lut_t; +struct Mini_Lut_t_ +{ + int nCap; + int nSize; + int nRegs; + int LutSize; + int * pArray; + unsigned * pTruths; +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// memory management +#define MINI_LUT_ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) +#define MINI_LUT_CALLOC(type, num) ((type *) calloc((num), sizeof(type))) +#define MINI_LUT_FALLOC(type, num) ((type *) memset(malloc(sizeof(type) * (num)), 0xff, sizeof(type) * (num))) +#define MINI_LUT_FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) +#define MINI_LUT_REALLOC(type, obj, num) \ + ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(type) * (num)))) + +// compute truth table size measured in unsigned's +static int Mini_LutWordNum( int LutSize ) +{ + return LutSize > 5 ? 1 << (LutSize-5) : 1; +} + +// internal procedures +static void Mini_LutGrow( Mini_Lut_t * p, int nCapMin ) +{ + if ( p->nCap >= nCapMin ) + return; + p->pArray = MINI_LUT_REALLOC( int, p->pArray, nCapMin * p->LutSize ); + p->pTruths = MINI_LUT_REALLOC( unsigned, p->pTruths, nCapMin * Mini_LutWordNum(p->LutSize) ); + p->nCap = nCapMin; + assert( p->pArray ); + assert( p->pTruths ); +} +static void Mini_LutPush( Mini_Lut_t * p, int nVars, int * pVars, unsigned * pTruth ) +{ + int i, nWords = Mini_LutWordNum(p->LutSize); + if ( p->nSize == p->nCap ) + { + assert( p->LutSize*p->nSize < MINI_LUT_NULL/2 ); + if ( p->nCap < MINI_LUT_START_SIZE ) + Mini_LutGrow( p, MINI_LUT_START_SIZE ); + else + Mini_LutGrow( p, 2 * p->nCap ); + } + for ( i = 0; i < nVars; i++ ) + p->pArray[p->LutSize * p->nSize + i] = pVars[i]; + for ( ; i < p->LutSize; i++ ) + p->pArray[p->LutSize * p->nSize + i] = MINI_LUT_NULL; + for ( i = 0; i < nWords; i++ ) + p->pTruths[nWords * p->nSize + i] = pTruth? pTruth[i] : 0; + p->nSize++; +} + +// accessing fanins +static int Mini_LutNodeFanin( Mini_Lut_t * p, int Id, int k ) +{ + assert( Id >= 0 && Id < p->nSize ); + return p->pArray[p->LutSize*Id+k]; +} +static unsigned * Mini_LutNodeTruth( Mini_Lut_t * p, int Id ) +{ + assert( Id >= 0 && Id < p->nSize ); + return p->pTruths + Id * Mini_LutWordNum(p->LutSize); +} + +// working with LUTs +static int Mini_LutNodeConst0() { return 0; } +static int Mini_LutNodeConst1() { return 1; } + +static int Mini_LutNodeNum( Mini_Lut_t * p ) { return p->nSize; } +static int Mini_LutNodeIsConst( Mini_Lut_t * p, int Id ) { assert( Id >= 0 ); return Id == 0 || Id == 1; } +static int Mini_LutNodeIsPi( Mini_Lut_t * p, int Id ) { assert( Id >= 0 ); return Id > 0 && Mini_LutNodeFanin( p, Id, 0 ) == MINI_LUT_NULL; } +static int Mini_LutNodeIsPo( Mini_Lut_t * p, int Id ) { assert( Id >= 0 ); return Id > 0 && Mini_LutNodeFanin( p, Id, 0 ) != MINI_LUT_NULL && Mini_LutNodeFanin( p, Id, 1 ) == MINI_LUT_NULL2; } +static int Mini_LutNodeIsNode( Mini_Lut_t * p, int Id ) { assert( Id >= 0 ); return Id > 0 && Mini_LutNodeFanin( p, Id, 0 ) != MINI_LUT_NULL && Mini_LutNodeFanin( p, Id, 1 ) != MINI_LUT_NULL2; } + +static int Mini_LutSize( Mini_Lut_t * p ) { return p->LutSize; } + +// working with sequential AIGs +static int Mini_LutRegNum( Mini_Lut_t * p ) { return p->nRegs; } +static void Mini_LutSetRegNum( Mini_Lut_t * p, int n ) { p->nRegs = n; } + +// iterators through objects +#define Mini_LutForEachPi( p, i ) for (i = 2; i < Mini_LutNodeNum(p); i++) if ( !Mini_LutNodeIsPi(p, i) ) {} else +#define Mini_LutForEachPo( p, i ) for (i = 2; i < Mini_LutNodeNum(p); i++) if ( !Mini_LutNodeIsPo(p, i) ) {} else +#define Mini_LutForEachNode( p, i ) for (i = 2; i < Mini_LutNodeNum(p); i++) if ( !Mini_LutNodeIsNode(p, i) ) {} else + +// iterator through fanins +#define Mini_LutForEachFanin( p, i, Fan, k ) for (k = 0; (k < p->LutSize) && (Fan = Mini_LutNodeFanin(p, i, k)) < MINI_LUT_NULL2; k++) + +// constructor/destructor +static Mini_Lut_t * Mini_LutStart( int LutSize ) +{ + Mini_Lut_t * p; int i; + assert( LutSize >= 2 && LutSize <= 16 ); + p = MINI_LUT_CALLOC( Mini_Lut_t, 1 ); + p->LutSize = LutSize; + p->nCap = MINI_LUT_START_SIZE; + p->pArray = MINI_LUT_ALLOC( int, p->nCap * p->LutSize ); + p->pTruths = MINI_LUT_ALLOC( unsigned, p->nCap * Mini_LutWordNum(p->LutSize) ); + Mini_LutPush( p, 0, NULL, NULL ); // const0 + Mini_LutPush( p, 0, NULL, NULL ); // const1 + for ( i = 0; i < Mini_LutWordNum(p->LutSize); i++ ) + p->pTruths[i] = 0; + for ( i = 0; i < Mini_LutWordNum(p->LutSize); i++ ) + p->pTruths[Mini_LutWordNum(p->LutSize) + i] = ~0; + return p; +} +static void Mini_LutStop( Mini_Lut_t * p ) +{ + MINI_LUT_FREE( p->pArray ); + MINI_LUT_FREE( p->pTruths ); + MINI_LUT_FREE( p ); +} +static void Mini_LutPrintStats( Mini_Lut_t * p ) +{ + int i, nPis, nPos, nNodes; + nPis = 0; + Mini_LutForEachPi( p, i ) + nPis++; + nPos = 0; + Mini_LutForEachPo( p, i ) + nPos++; + nNodes = 0; + Mini_LutForEachNode( p, i ) + nNodes++; + printf( "PI = %d. PO = %d. LUT = %d.\n", nPis, nPos, nNodes ); +} + +// serialization +static void Mini_LutDump( Mini_Lut_t * p, char * pFileName ) +{ + FILE * pFile; + int RetValue; + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file for writing \"%s\".\n", pFileName ); + return; + } + RetValue = fwrite( &p->nSize, sizeof(int), 1, pFile ); + RetValue = fwrite( &p->nRegs, sizeof(int), 1, pFile ); + RetValue = fwrite( &p->LutSize, sizeof(int), 1, pFile ); + RetValue = fwrite( p->pArray, sizeof(int), p->nSize * p->LutSize, pFile ); + RetValue = fwrite( p->pTruths, sizeof(int), p->nSize * Mini_LutWordNum(p->LutSize), pFile ); + fclose( pFile ); +} +static Mini_Lut_t * Mini_LutLoad( char * pFileName ) +{ + Mini_Lut_t * p; + FILE * pFile; + int RetValue, nSize; + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file for reading \"%s\".\n", pFileName ); + return NULL; + } + RetValue = fread( &nSize, sizeof(int), 1, pFile ); + p = MINI_LUT_CALLOC( Mini_Lut_t, 1 ); + p->nSize = p->nCap = nSize; + RetValue = fread( &p->nRegs, sizeof(int), 1, pFile ); + RetValue = fread( &p->LutSize, sizeof(int), 1, pFile ); + p->pArray = MINI_LUT_ALLOC( int, p->nCap * p->LutSize ); + p->pTruths = MINI_LUT_ALLOC( int, p->nCap * Mini_LutWordNum(p->LutSize) ); + RetValue = fread( p->pArray, sizeof(int), p->nCap * p->LutSize, pFile ); + RetValue = fread( p->pTruths, sizeof(int), p->nCap * Mini_LutWordNum(p->LutSize), pFile ); + fclose( pFile ); + return p; +} + + +// creating nodes +// (constant nodes are created when LUT manager is created) +static int Mini_LutCreatePi( Mini_Lut_t * p ) +{ + Mini_LutPush( p, 0, NULL, NULL ); + return p->nSize - 1; +} +static int Mini_LutCreatePo( Mini_Lut_t * p, int Var0 ) +{ + assert( Var0 >= 0 && Var0 < p->nSize ); + Mini_LutPush( p, 1, &Var0, NULL ); + // mark PO by setting its 2nd fanin to the special number + p->pArray[p->LutSize*(p->nSize - 1)+1] = MINI_LUT_NULL2; + return p->nSize - 1; +} + +// create LUT +static int Mini_LutCreateNode( Mini_Lut_t * p, int nVars, int * pVars, unsigned * pTruth ) +{ + assert( nVars >= 0 && nVars <= p->LutSize ); + Mini_LutPush( p, nVars, pVars, pTruth ); + return p->nSize - 1; +} + +// procedure to check the topological order during AIG construction +static int Mini_LutCheck( Mini_Lut_t * p ) +{ + int status = 1; + int i, k, iFaninVar; + Mini_LutForEachNode( p, i ) + { + for ( k = 0; k < p->LutSize; k++ ) + { + iFaninVar = Mini_LutNodeFanin( p, i, k ); + if ( iFaninVar == MINI_LUT_NULL ) + continue; + if ( iFaninVar >= p->LutSize * i ) + printf( "Fanin %d of LUT node %d is not in a topological order.\n", k, i ), status = 0; + } + } + Mini_LutForEachPo( p, i ) + { + iFaninVar = Mini_LutNodeFanin( p, i, 0 ); + if ( iFaninVar >= p->LutSize * i ) + printf( "Fanin %d of PO node %d is not in a topological order.\n", k, i ), status = 0; + } + return status; +} + + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 1fdffd77..9f04926d 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -12074,8 +12074,6 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) { // extern void Cba_PrsReadBlifTest(); // Cba_PrsReadBlifTest(); - extern void Sfm_TimTest( Abc_Ntk_t * pNtk ); - Sfm_TimTest( pNtk ); } return 0; usage: @@ -26998,12 +26996,13 @@ int Abc_CommandAbc9Read( Abc_Frame_t * pAbc, int argc, char ** argv ) char ** pArgvNew; char * FileName, * pTemp; int c, nArgcNew; - int fUseMini = 0; + int fMiniAig = 0; + int fMiniLut = 0; int fVerbose = 0; int fGiaSimple = 0; int fSkipStrash = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "csmvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "csmlvh" ) ) != EOF ) { switch ( c ) { @@ -27014,7 +27013,10 @@ int Abc_CommandAbc9Read( Abc_Frame_t * pAbc, int argc, char ** argv ) fSkipStrash ^= 1; break; case 'm': - fUseMini ^= 1; + fMiniAig ^= 1; + break; + case 'l': + fMiniLut ^= 1; break; case 'v': fVerbose ^= 1; @@ -27047,8 +27049,10 @@ int Abc_CommandAbc9Read( Abc_Frame_t * pAbc, int argc, char ** argv ) } fclose( pFile ); - if ( fUseMini ) + if ( fMiniAig ) pAig = Gia_ManReadMiniAig( FileName ); + else if ( fMiniLut ) + pAig = Gia_ManReadMiniLut( FileName ); // else if ( Extra_FileIsType( FileName, ".v", NULL, NULL ) ) // Abc3_ReadShowHie( FileName, fSkipStrash ); else @@ -27058,11 +27062,12 @@ int Abc_CommandAbc9Read( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &r [-csmvh] \n" ); + Abc_Print( -2, "usage: &r [-csmlvh] \n" ); Abc_Print( -2, "\t reads the current AIG from the AIGER file\n" ); Abc_Print( -2, "\t-c : toggles reading simple AIG [default = %s]\n", fGiaSimple? "yes": "no" ); Abc_Print( -2, "\t-s : toggles structural hashing while reading [default = %s]\n", !fSkipStrash? "yes": "no" ); - Abc_Print( -2, "\t-m : toggles reading MiniAIG rather than AIGER file [default = %s]\n", fUseMini? "yes": "no" ); + Abc_Print( -2, "\t-m : toggles reading MiniAIG rather than AIGER file [default = %s]\n", fMiniAig? "yes": "no" ); + Abc_Print( -2, "\t-l : toggles reading MiniLUT rather than AIGER file [default = %s]\n", fMiniLut? "yes": "no" ); Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the file name\n"); @@ -27843,9 +27848,10 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) int c, nArgcNew; int fUnique = 0; int fMiniAig = 0; + int fMiniLut = 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "umvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "umlvh" ) ) != EOF ) { switch ( c ) { @@ -27855,6 +27861,9 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'm': fMiniAig ^= 1; break; + case 'l': + fMiniLut ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -27885,15 +27894,18 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) } else if ( fMiniAig ) Gia_ManWriteMiniAig( pAbc->pGia, pFileName ); + else if ( fMiniLut ) + Gia_ManWriteMiniLut( pAbc->pGia, pFileName ); else Gia_AigerWrite( pAbc->pGia, pFileName, 0, 0 ); return 0; usage: - Abc_Print( -2, "usage: &w [-umvh] \n" ); + Abc_Print( -2, "usage: &w [-umlvh] \n" ); Abc_Print( -2, "\t writes the current AIG into the AIGER file\n" ); Abc_Print( -2, "\t-u : toggle writing canonical AIG structure [default = %s]\n", fUnique? "yes" : "no" ); Abc_Print( -2, "\t-m : toggle writing MiniAIG rather than AIGER [default = %s]\n", fMiniAig? "yes" : "no" ); + Abc_Print( -2, "\t-l : toggle writing MiniLUT rather than AIGER [default = %s]\n", fMiniLut? "yes" : "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the file name\n"); diff --git a/src/opt/dau/dauGia.c b/src/opt/dau/dauGia.c index 6489cd86..5e74ad21 100644 --- a/src/opt/dau/dauGia.c +++ b/src/opt/dau/dauGia.c @@ -460,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 ); -- cgit v1.2.3 From 3169bd96b784cbc86bb523cb6de094580299fdb6 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 5 Dec 2016 17:48:21 -0800 Subject: Compiler warnings. --- src/aig/miniaig/minilut.h | 4 ++-- src/base/abci/abc.c | 2 +- src/proof/acec/acecPolyn.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/aig/miniaig/minilut.h b/src/aig/miniaig/minilut.h index 953f0bd3..5040f4b7 100644 --- a/src/aig/miniaig/minilut.h +++ b/src/aig/miniaig/minilut.h @@ -214,8 +214,8 @@ static Mini_Lut_t * Mini_LutLoad( char * pFileName ) p->nSize = p->nCap = nSize; RetValue = fread( &p->nRegs, sizeof(int), 1, pFile ); RetValue = fread( &p->LutSize, sizeof(int), 1, pFile ); - p->pArray = MINI_LUT_ALLOC( int, p->nCap * p->LutSize ); - p->pTruths = MINI_LUT_ALLOC( int, p->nCap * Mini_LutWordNum(p->LutSize) ); + p->pArray = MINI_LUT_ALLOC( int, p->nCap * p->LutSize ); + p->pTruths = MINI_LUT_ALLOC( unsigned, p->nCap * Mini_LutWordNum(p->LutSize) ); RetValue = fread( p->pArray, sizeof(int), p->nCap * p->LutSize, pFile ); RetValue = fread( p->pTruths, sizeof(int), p->nCap * Mini_LutWordNum(p->LutSize), pFile ); fclose( pFile ); diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 9f04926d..7da88d3c 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -11867,7 +11867,7 @@ int Abc_CommandTestColor( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + //Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int nCutMax = 1; int nLeafMax = 4; int nDivMax = 2; diff --git a/src/proof/acec/acecPolyn.c b/src/proof/acec/acecPolyn.c index 042e0c59..53ddf710 100644 --- a/src/proof/acec/acecPolyn.c +++ b/src/proof/acec/acecPolyn.c @@ -429,7 +429,7 @@ void Gia_PolynBuild2( Gia_Man_t * pGia, int fSigned, int fVerbose, int fVeryVerb { Hsh_VecMan_t * pHashC = Hsh_VecManStart( 1000 ); // hash table for constants Hsh_VecMan_t * pHashM = Hsh_VecManStart( 1000 ); // hash table for monomials - Vec_Wec_t * vLit2Mono = Vec_WecStart( Gia_ManObjNum(pGia) * 2 ); + //Vec_Wec_t * vLit2Mono = Vec_WecStart( Gia_ManObjNum(pGia) * 2 ); Hsh_VecManStop( pHashC ); Hsh_VecManStop( pHashM ); -- cgit v1.2.3 From d9fdd10960744034bac5da285e221513d4438b75 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 5 Dec 2016 19:54:17 -0800 Subject: Bug fix in Liberty parser. --- src/map/scl/sclLiberty.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/map/scl/sclLiberty.c b/src/map/scl/sclLiberty.c index 2b2e77e9..50e69d08 100644 --- a/src/map/scl/sclLiberty.c +++ b/src/map/scl/sclLiberty.c @@ -1614,10 +1614,14 @@ Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbos Vec_Flt_t * vArray; assert( Vec_PtrSize(vTemples) % 4 == 0 ); Vec_PtrForEachEntry( Vec_Flt_t *, vTemples, vArray, i ) + { + if ( vArray == NULL ) + continue; if ( i % 4 == 0 ) ABC_FREE( vArray ); else if ( i % 4 == 2 || i % 4 == 3 ) Vec_FltFree( vArray ); + } Vec_PtrFree( vTemples ); } if ( fVerbose ) -- cgit v1.2.3 From 77ef610919b09ed0f8cb0df50e48a7f9c4b9c553 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 5 Dec 2016 21:18:51 -0800 Subject: Adding support for minimalistic representation of LUT mapping. --- src/aig/gia/giaMini.c | 2 +- src/aig/miniaig/abcapis.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/aig/gia/giaMini.c b/src/aig/gia/giaMini.c index 77bb1b64..a886311f 100644 --- a/src/aig/gia/giaMini.c +++ b/src/aig/gia/giaMini.c @@ -300,7 +300,7 @@ Mini_Lut_t * Gia_ManToMiniLut( Gia_Man_t * pGia ) } // set registers Mini_LutSetRegNum( p, Gia_ManRegNum(pGia) ); - Mini_LutPrintStats( p ); + //Mini_LutPrintStats( p ); return p; } diff --git a/src/aig/miniaig/abcapis.h b/src/aig/miniaig/abcapis.h index f62612e8..38c0591d 100644 --- a/src/aig/miniaig/abcapis.h +++ b/src/aig/miniaig/abcapis.h @@ -54,6 +54,10 @@ extern void Abc_NtkInputMiniAig( void * pAbc, void * pMiniAig ); extern void * Abc_NtkOutputMiniAig( void * pAbc ); extern void Abc_NtkSetFlopNum( void * pAbc, int nFlops ); +// procedures to input/output 'mini AIG' +extern void Abc_NtkInputMiniLut( void * pAbc, void * pMiniLut ); +extern void * Abc_NtkOutputMiniLut( void * pAbc ); + // procedures to set CI/CO arrival/required times extern void Abc_NtkSetCiArrivalTime( void * pAbc, int iCi, float Rise, float Fall ); extern void Abc_NtkSetCoRequiredTime( void * pAbc, int iCo, float Rise, float Fall ); -- cgit v1.2.3