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