summaryrefslogtreecommitdiffstats
path: root/src/aig
diff options
context:
space:
mode:
authorMiodrag Milanovic <mmicko@gmail.com>2022-11-09 08:42:08 +0100
committerMiodrag Milanovic <mmicko@gmail.com>2022-11-09 08:42:08 +0100
commitbe9a35c0363174a7cef21d55ed80d92a9ef95ab1 (patch)
tree3bf5d3eee39f46d72d3196386eadd8788f742e4b /src/aig
parentab5b16ede2ff3a4ab5209df24db2c76700899684 (diff)
parent70cb339f869e485802159d7f2b886130793556c4 (diff)
downloadabc-be9a35c0363174a7cef21d55ed80d92a9ef95ab1.tar.gz
abc-be9a35c0363174a7cef21d55ed80d92a9ef95ab1.tar.bz2
abc-be9a35c0363174a7cef21d55ed80d92a9ef95ab1.zip
Merge remote-tracking branch 'upstream/master' into yosys-experimental
Diffstat (limited to 'src/aig')
-rw-r--r--src/aig/gia/gia.h12
-rw-r--r--src/aig/gia/giaCut.c215
-rw-r--r--src/aig/gia/giaDup.c21
-rw-r--r--src/aig/gia/giaEquiv.c2
-rw-r--r--src/aig/gia/giaIf.c2
-rw-r--r--src/aig/gia/giaResub2.c2
-rw-r--r--src/aig/gia/giaSatSyn.c60
-rw-r--r--src/aig/gia/giaSimBase.c488
-rw-r--r--src/aig/gia/giaTtopt.cpp1213
-rw-r--r--src/aig/gia/giaUtil.c31
-rw-r--r--src/aig/gia/module.make2
-rw-r--r--src/aig/miniaig/miniaig.h56
-rw-r--r--src/aig/miniaig/ndr.h2
13 files changed, 2098 insertions, 8 deletions
diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h
index 488f12cf..942c9eb7 100644
--- a/src/aig/gia/gia.h
+++ b/src/aig/gia/gia.h
@@ -527,18 +527,22 @@ static inline int Gia_ObjDiff1( Gia_Obj_t * pObj ) {
static inline int Gia_ObjFaninC0( Gia_Obj_t * pObj ) { return pObj->fCompl0; }
static inline int Gia_ObjFaninC1( Gia_Obj_t * pObj ) { return pObj->fCompl1; }
static inline int Gia_ObjFaninC2( Gia_Man_t * p, Gia_Obj_t * pObj ) { return p->pMuxes && Abc_LitIsCompl(p->pMuxes[Gia_ObjId(p, pObj)]); }
+static inline int Gia_ObjFaninC( Gia_Obj_t * pObj, int n ) { return n ? Gia_ObjFaninC1(pObj) : Gia_ObjFaninC0(pObj); }
static inline Gia_Obj_t * Gia_ObjFanin0( Gia_Obj_t * pObj ) { return pObj - pObj->iDiff0; }
static inline Gia_Obj_t * Gia_ObjFanin1( Gia_Obj_t * pObj ) { return pObj - pObj->iDiff1; }
static inline Gia_Obj_t * Gia_ObjFanin2( Gia_Man_t * p, Gia_Obj_t * pObj ) { return p->pMuxes ? Gia_ManObj(p, Abc_Lit2Var(p->pMuxes[Gia_ObjId(p, pObj)])) : NULL; }
+static inline Gia_Obj_t * Gia_ObjFanin( Gia_Obj_t * pObj, int n ) { return n ? Gia_ObjFanin1(pObj) : Gia_ObjFanin0(pObj); }
static inline Gia_Obj_t * Gia_ObjChild0( Gia_Obj_t * pObj ) { return Gia_NotCond( Gia_ObjFanin0(pObj), Gia_ObjFaninC0(pObj) ); }
static inline Gia_Obj_t * Gia_ObjChild1( Gia_Obj_t * pObj ) { return Gia_NotCond( Gia_ObjFanin1(pObj), Gia_ObjFaninC1(pObj) ); }
static inline Gia_Obj_t * Gia_ObjChild2( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_NotCond( Gia_ObjFanin2(p, pObj), Gia_ObjFaninC2(p, pObj) ); }
static inline int Gia_ObjFaninId0( Gia_Obj_t * pObj, int ObjId ) { return ObjId - pObj->iDiff0; }
static inline int Gia_ObjFaninId1( Gia_Obj_t * pObj, int ObjId ) { return ObjId - pObj->iDiff1; }
static inline int Gia_ObjFaninId2( Gia_Man_t * p, int ObjId ) { return (p->pMuxes && p->pMuxes[ObjId]) ? Abc_Lit2Var(p->pMuxes[ObjId]) : -1; }
+static inline int Gia_ObjFaninId( Gia_Obj_t * pObj, int ObjId, int n ){ return n ? Gia_ObjFaninId1(pObj, ObjId) : Gia_ObjFaninId0(pObj, ObjId); }
static inline int Gia_ObjFaninId0p( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjFaninId0( pObj, Gia_ObjId(p, pObj) ); }
static inline int Gia_ObjFaninId1p( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjFaninId1( pObj, Gia_ObjId(p, pObj) ); }
static inline int Gia_ObjFaninId2p( Gia_Man_t * p, Gia_Obj_t * pObj ) { return (p->pMuxes && p->pMuxes[Gia_ObjId(p, pObj)]) ? Abc_Lit2Var(p->pMuxes[Gia_ObjId(p, pObj)]) : -1; }
+static inline int Gia_ObjFaninIdp( Gia_Man_t * p, Gia_Obj_t * pObj, int n){ return n ? Gia_ObjFaninId1p(p, pObj) : Gia_ObjFaninId0p(p, pObj); }
static inline int Gia_ObjFaninLit0( Gia_Obj_t * pObj, int ObjId ) { return Abc_Var2Lit( Gia_ObjFaninId0(pObj, ObjId), Gia_ObjFaninC0(pObj) ); }
static inline int Gia_ObjFaninLit1( Gia_Obj_t * pObj, int ObjId ) { return Abc_Var2Lit( Gia_ObjFaninId1(pObj, ObjId), Gia_ObjFaninC1(pObj) ); }
static inline int Gia_ObjFaninLit2( Gia_Man_t * p, int ObjId ) { return (p->pMuxes && p->pMuxes[ObjId]) ? p->pMuxes[ObjId] : -1; }
@@ -1544,6 +1548,9 @@ extern Gia_Man_t * Gia_ManReadMiniAig( char * pFileName, int fGiaSimple
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 );
+/*=== giaMinLut.c ===========================================================*/
+extern word * Gia_ManCountFraction( Gia_Man_t * p, Vec_Wrd_t * vSimI, Vec_Int_t * vSupp, int Thresh, int fVerbose, int * pCare );
+extern Vec_Int_t * Gia_ManCollectSuppNew( Gia_Man_t * p, int iOut, int nOuts );
/*=== giaMuxes.c ===========================================================*/
extern void Gia_ManCountMuxXor( Gia_Man_t * p, int * pnMuxes, int * pnXors );
extern void Gia_ManPrintMuxStats( Gia_Man_t * p );
@@ -1754,6 +1761,10 @@ extern int Gia_ManCountPosWithNonZeroDrivers( Gia_Man_t * p );
extern void Gia_ManUpdateCopy( Vec_Int_t * vCopy, Gia_Man_t * p );
extern Vec_Int_t * Gia_ManComputeDistance( Gia_Man_t * p, int iObj, Vec_Int_t * vObjs, int fVerbose );
+/*=== giaTtopt.c ===========================================================*/
+extern Gia_Man_t * Gia_ManTtopt( Gia_Man_t * p, int nIns, int nOuts, int nRounds );
+extern Gia_Man_t * Gia_ManTtoptCare( Gia_Man_t * p, int nIns, int nOuts, int nRounds, char * pFileName, int nRarity );
+
/*=== giaCTas.c ===========================================================*/
typedef struct Tas_Man_t_ Tas_Man_t;
extern Tas_Man_t * Tas_ManAlloc( Gia_Man_t * pAig, int nBTLimit );
@@ -1763,7 +1774,6 @@ extern void Tas_ManSatPrintStats( Tas_Man_t * p );
extern int Tas_ManSolve( Tas_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 );
extern int Tas_ManSolveArray( Tas_Man_t * p, Vec_Ptr_t * vObjs );
-
ABC_NAMESPACE_HEADER_END
diff --git a/src/aig/gia/giaCut.c b/src/aig/gia/giaCut.c
index 7ee795b6..19e2d8fc 100644
--- a/src/aig/gia/giaCut.c
+++ b/src/aig/gia/giaCut.c
@@ -20,6 +20,7 @@
#include "gia.h"
#include "misc/util/utilTruth.h"
+#include "misc/vec/vecHsh.h"
ABC_NAMESPACE_IMPL_START
@@ -29,7 +30,7 @@ ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
#define GIA_MAX_CUTSIZE 8
-#define GIA_MAX_CUTNUM 51
+#define GIA_MAX_CUTNUM 65
#define GIA_MAX_TT_WORDS ((GIA_MAX_CUTSIZE > 6) ? 1 << (GIA_MAX_CUTSIZE-6) : 1)
#define GIA_CUT_NO_LEAF 0xF
@@ -778,6 +779,218 @@ void Gia_ManExtractTest( Gia_Man_t * pGia )
Abc_PrintTime( 0, "Creating windows", Abc_Clock() - clk );
}
+/**Function*************************************************************
+
+ Synopsis [Extract a given number of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Gia_StoCutPrint( int * pCut )
+{
+ int v;
+ printf( "{" );
+ for ( v = 1; v <= pCut[0]; v++ )
+ printf( " %d", pCut[v] );
+ printf( " }\n" );
+}
+void Gia_StoPrintCuts( Vec_Int_t * vThis, int iObj, int nCutSize )
+{
+ int i, * pCut;
+ printf( "Cuts of node %d (size = %d):\n", iObj, nCutSize );
+ Sdb_ForEachCut( Vec_IntArray(vThis), pCut, i )
+ if ( !nCutSize || pCut[0] == nCutSize )
+ Gia_StoCutPrint( pCut );
+}
+Vec_Wec_t * Gia_ManFilterCuts( Gia_Man_t * pGia, Vec_Wec_t * vStore, int nCutSize, int nCuts )
+{
+ abctime clkStart = Abc_Clock();
+ Vec_Wec_t * vCutsSel = Vec_WecAlloc( nCuts );
+ Vec_Int_t * vLevel, * vCut = Vec_IntAlloc( 10 );
+ Vec_Wec_t * vCuts = Vec_WecAlloc( 1000 );
+ Hsh_VecMan_t * p = Hsh_VecManStart( 1000 ); int i, s;
+ Vec_WecForEachLevel( vStore, vLevel, i ) if ( Vec_IntSize(vLevel) )
+ {
+ int v, k, * pCut, Value;
+ Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k )
+ {
+ if ( pCut[0] < 2 )
+ continue;
+
+ for ( v = 1; v <= pCut[0]; v++ )
+ if ( pCut[v] < 9 )
+ break;
+ if ( v <= pCut[0] )
+ continue;
+
+ Vec_IntClear( vCut );
+ Vec_IntPushArray( vCut, pCut+1, pCut[0] );
+ Value = Hsh_VecManAdd( p, vCut );
+ if ( Value == Vec_WecSize(vCuts) )
+ {
+ Vec_Int_t * vTemp = Vec_WecPushLevel(vCuts);
+ Vec_IntPush( vTemp, 0 );
+ Vec_IntAppend( vTemp, vCut );
+ }
+ Vec_IntAddToEntry( Vec_WecEntry(vCuts, Value), 0, 1 );
+ }
+ }
+ printf( "Collected cuts = %d.\n", Vec_WecSize(vCuts) );
+ for ( s = 3; s <= nCutSize; s++ )
+ Vec_WecForEachLevel( vCuts, vLevel, i )
+ if ( Vec_IntSize(vLevel) - 1 == s )
+ {
+ int * pCut = Vec_IntEntryP(vLevel, 1);
+ int u, v, Value;
+ for ( u = 0; u < s; u++ )
+ {
+ Vec_IntClear( vCut );
+ for ( v = 0; v < s; v++ ) if ( v != u )
+ Vec_IntPush( vCut, pCut[v] );
+ assert( Vec_IntSize(vCut) == s-1 );
+ Value = Hsh_VecManAdd( p, vCut );
+ if ( Value < Vec_WecSize(vCuts) )
+ Vec_IntAddToEntry( vLevel, 0, Vec_IntEntry(Vec_WecEntry(vCuts, Value), 0) );
+ }
+ }
+ Hsh_VecManStop( p );
+ Vec_IntFree( vCut );
+ // collect
+ Vec_WecSortByFirstInt( vCuts, 1 );
+ Vec_WecForEachLevelStop( vCuts, vLevel, i, Abc_MinInt(Vec_WecSize(vCuts), nCuts) )
+ Vec_IntAppend( Vec_WecPushLevel(vCutsSel), vLevel );
+ Abc_PrintTime( 0, "Cut filtering time", Abc_Clock() - clkStart );
+ return vCutsSel;
+}
+int Gia_ManCountRefs( Gia_Man_t * pGia, Vec_Int_t * vLevel )
+{
+ int i, iObj, nRefs = 0;
+ Vec_IntForEachEntry( vLevel, iObj, i )
+ nRefs += Gia_ObjRefNumId(pGia, iObj);
+ return nRefs;
+}
+Vec_Wrd_t * Gia_ManGenSims( Gia_Man_t * pGia )
+{
+ Vec_Wrd_t * vSims;
+ Vec_WrdFreeP( &pGia->vSimsPi );
+ pGia->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(pGia) );
+ vSims = Gia_ManSimPatSim( pGia );
+ return vSims;
+}
+int Gia_ManFindSatDcs( Gia_Man_t * pGia, Vec_Wrd_t * vSims, Vec_Int_t * vLevel )
+{
+ int nWords = Vec_WrdSize(pGia->vSimsPi) / Gia_ManCiNum(pGia);
+ int i, w, iObj, Res = 0, Pres[256] = {0}, nMints = 1 << Vec_IntSize(vLevel);
+ for ( w = 0; w < 64*nWords; w++ )
+ {
+ int iInMint = 0;
+ Vec_IntForEachEntry( vLevel, iObj, i )
+ if ( Abc_TtGetBit( Vec_WrdEntryP(vSims, iObj*nWords), w ) )
+ iInMint |= 1 << i;
+ Pres[iInMint]++;
+ }
+ for ( i = 0; i < nMints; i++ )
+ Res += Pres[i] == 0;
+ return Res;
+}
+
+
+int Gia_ManCollectCutDivs( Gia_Man_t * p, Vec_Int_t * vIns )
+{
+ Gia_Obj_t * pObj; int i, Res = 0;
+ Vec_Int_t * vRes = Vec_IntAlloc( 100 );
+ Vec_IntSort( vIns, 0 );
+
+ Vec_IntPush( vRes, 0 );
+ Vec_IntAppend( vRes, vIns );
+
+ Gia_ManIncrementTravId( p );
+ Gia_ManIncrementTravId( p );
+ Gia_ManForEachObjVec( vIns, p, pObj, i )
+ Gia_ObjSetTravIdCurrent( p, pObj );
+
+ Gia_ManForEachAnd( p, pObj, i )
+ if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+ continue;
+ else if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) && Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) )
+ {
+ if ( !Gia_ObjIsTravIdPrevious(p, pObj) )
+ Vec_IntPush( vRes, i );
+ Gia_ObjSetTravIdCurrent( p, pObj );
+ }
+// printf( "Divisors: " );
+// Vec_IntPrint( vRes );
+ Res = Vec_IntSize(vRes);
+ Vec_IntFree( vRes );
+ return Res;
+}
+
+void Gia_ManConsiderCuts( Gia_Man_t * pGia, Vec_Wec_t * vCuts )
+{
+ Vec_Wrd_t * vSims = Gia_ManGenSims( pGia );
+ Vec_Int_t * vLevel; int i;
+ Gia_ManCreateRefs( pGia );
+ Vec_WecForEachLevel( vCuts, vLevel, i )
+ {
+ printf( "Cut %3d ", i );
+ printf( "Ref = %3d : ", Vec_IntEntry(vLevel, 0) );
+
+ Vec_IntShift( vLevel, 1 );
+ printf( "Ref = %3d : ", Gia_ManCountRefs(pGia, vLevel) );
+ printf( "SDC = %3d : ", Gia_ManFindSatDcs(pGia, vSims, vLevel) );
+ printf( "Div = %3d : ", Gia_ManCollectCutDivs(pGia, vLevel) );
+ Vec_IntPrint( vLevel );
+ Vec_IntShift( vLevel, -1 );
+ }
+ Vec_WrdFree( vSims );
+}
+
+
+Vec_Wec_t * Gia_ManExploreCuts( Gia_Man_t * pGia, int nCutSize0, int nCuts0, int fVerbose0 )
+{
+ int nCutSize = nCutSize0;
+ int nCutNum = 64;
+ int fCutMin = 0;
+ int fTruthMin = 0;
+ int fVerbose = fVerbose0;
+ Vec_Wec_t * vCutsSel;
+ Gia_Sto_t * p = Gia_StoAlloc( pGia, nCutSize, nCutNum, fCutMin, fTruthMin, fVerbose );
+ Gia_Obj_t * pObj; int i, iObj;
+ assert( nCutSize <= GIA_MAX_CUTSIZE );
+ assert( nCutNum < GIA_MAX_CUTNUM );
+ // prepare references
+ Gia_ManForEachObj( p->pGia, pObj, iObj )
+ Gia_StoRefObj( p, iObj );
+ // compute cuts
+ Gia_StoComputeCutsConst0( p, 0 );
+ Gia_ManForEachCiId( p->pGia, iObj, i )
+ Gia_StoComputeCutsCi( p, iObj );
+ Gia_ManForEachAnd( p->pGia, pObj, iObj )
+ Gia_StoComputeCutsNode( p, iObj );
+ if ( p->fVerbose )
+ {
+ printf( "Running cut computation with CutSize = %d CutNum = %d CutMin = %s TruthMin = %s\n",
+ p->nCutSize, p->nCutNum, p->fCutMin ? "yes":"no", p->fTruthMin ? "yes":"no" );
+ printf( "CutPair = %.0f ", p->CutCount[0] );
+ printf( "Merge = %.0f (%.2f %%) ", p->CutCount[1], 100.0*p->CutCount[1]/p->CutCount[0] );
+ printf( "Eval = %.0f (%.2f %%) ", p->CutCount[2], 100.0*p->CutCount[2]/p->CutCount[0] );
+ printf( "Cut = %.0f (%.2f %%) ", p->CutCount[3], 100.0*p->CutCount[3]/p->CutCount[0] );
+ printf( "Cut/Node = %.2f ", p->CutCount[3] / Gia_ManAndNum(p->pGia) );
+ printf( "\n" );
+ printf( "The number of nodes with cut count over the limit (%d cuts) = %d nodes (out of %d). ",
+ p->nCutNum, p->nCutsOver, Gia_ManAndNum(pGia) );
+ Abc_PrintTime( 0, "Time", Abc_Clock() - p->clkStart );
+ }
+ vCutsSel = Gia_ManFilterCuts( pGia, p->vCuts, nCutSize0, nCuts0 );
+ Gia_ManConsiderCuts( pGia, vCutsSel );
+ Gia_StoFree( p );
+ return vCutsSel;
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c
index cc501562..c9af8a32 100644
--- a/src/aig/gia/giaDup.c
+++ b/src/aig/gia/giaDup.c
@@ -860,6 +860,27 @@ Gia_Man_t * Gia_ManDupMap( Gia_Man_t * p, Vec_Int_t * vMap )
Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
return pNew;
}
+Gia_Man_t * Gia_ManDupAddBufs( Gia_Man_t * p )
+{
+ Gia_Man_t * pNew;
+ Gia_Obj_t * pObj;
+ int i;
+ pNew = Gia_ManStart( Gia_ManObjNum(p) + Gia_ManCiNum(p) + Gia_ManCoNum(p) );
+ Gia_ManHashStart( pNew );
+ Gia_ManConst0(p)->Value = 0;
+ Gia_ManForEachCi( p, pObj, i )
+ pObj->Value = Gia_ManAppendCi( pNew );
+ Gia_ManForEachCi( p, pObj, i )
+ pObj->Value = Gia_ManAppendBuf( pNew, pObj->Value );
+ Gia_ManForEachAnd( p, pObj, i )
+ pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+ Gia_ManForEachCo( p, pObj, i )
+ pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) );
+ Gia_ManForEachCo( p, pObj, i )
+ pObj->Value = Gia_ManAppendCo( pNew, pObj->Value );
+ Gia_ManHashStop( pNew );
+ return pNew;
+}
/**Function*************************************************************
diff --git a/src/aig/gia/giaEquiv.c b/src/aig/gia/giaEquiv.c
index 5c82b260..030eaa60 100644
--- a/src/aig/gia/giaEquiv.c
+++ b/src/aig/gia/giaEquiv.c
@@ -1869,7 +1869,7 @@ void Gia_ManEquivToChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pOb
Gia_Obj_t * pRepr, * pReprNew, * pObjNew;
if ( ~pObj->Value )
return;
- if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) )
+ if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) && !Gia_ObjFailed(p,Gia_ObjId(p,pObj)) )
{
if ( Gia_ObjIsConst0(pRepr) )
{
diff --git a/src/aig/gia/giaIf.c b/src/aig/gia/giaIf.c
index ae87277a..8b4e5b12 100644
--- a/src/aig/gia/giaIf.c
+++ b/src/aig/gia/giaIf.c
@@ -1891,7 +1891,7 @@ Gia_Man_t * Gia_ManFromIfLogic( If_Man_t * pIfMan )
if ( !pIfMan->pPars->fUseTtPerm && !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance &&
!pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize &&
!pIfMan->pPars->fEnableCheck75 && !pIfMan->pPars->fEnableCheck75u && !pIfMan->pPars->fEnableCheck07 && !pIfMan->pPars->fUseDsdTune &&
- !pIfMan->pPars->fUseCofVars && !pIfMan->pPars->fUseAndVars )
+ !pIfMan->pPars->fUseCofVars && !pIfMan->pPars->fUseAndVars && !pIfMan->pPars->fUseCheck1 && !pIfMan->pPars->fUseCheck2 )
If_CutRotatePins( pIfMan, pCutBest );
// collect leaves of the best cut
Vec_IntClear( vLeaves );
diff --git a/src/aig/gia/giaResub2.c b/src/aig/gia/giaResub2.c
index 1219526f..10c5a9e0 100644
--- a/src/aig/gia/giaResub2.c
+++ b/src/aig/gia/giaResub2.c
@@ -733,7 +733,7 @@ void Gia_RsbCiWindowTest( Gia_Man_t * p )
SeeAlso []
***********************************************************************/
-static inline int Gia_ObjFaninId( Gia_Obj_t * pObj, int iObj, int n ) { return n ? Gia_ObjFaninId1(pObj, iObj) : Gia_ObjFaninId0(pObj, iObj); }
+//static inline int Gia_ObjFaninId( Gia_Obj_t * pObj, int iObj, int n ) { return n ? Gia_ObjFaninId1(pObj, iObj) : Gia_ObjFaninId0(pObj, iObj); }
static inline int Gia_ObjTravIsTopTwo( Gia_Man_t * p, int iNodeA ) { return (p->pTravIds[iNodeA] >= p->nTravIds - 1); }
static inline int Gia_ObjTravIsSame( Gia_Man_t * p, int iNodeA, int iNodeB ) { return (p->pTravIds[iNodeA] == p->pTravIds[iNodeB]); }
diff --git a/src/aig/gia/giaSatSyn.c b/src/aig/gia/giaSatSyn.c
new file mode 100644
index 00000000..15829f79
--- /dev/null
+++ b/src/aig/gia/giaSatSyn.c
@@ -0,0 +1,60 @@
+/**CFile****************************************************************
+
+ FileName [giaSyn.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Scalable AIG package.]
+
+ Synopsis [High-effort synthesis.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: giaSyn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/util/utilTruth.h"
+#include "sat/glucose/AbcGlucose.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManSyn( Gia_Man_t * p, int nNodes, int nOuts, int nTimeLimit, int fUseXor, int fFancy, int fVerbose )
+{
+ Gia_Man_t * pNew = NULL;
+ return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/aig/gia/giaSimBase.c b/src/aig/gia/giaSimBase.c
index 002f6bc2..75a6d653 100644
--- a/src/aig/gia/giaSimBase.c
+++ b/src/aig/gia/giaSimBase.c
@@ -22,6 +22,7 @@
#include "misc/util/utilTruth.h"
#include "misc/extra/extra.h"
//#include <immintrin.h>
+#include "aig/miniaig/miniaig.h"
ABC_NAMESPACE_IMPL_START
@@ -2717,13 +2718,89 @@ Vec_Ptr_t * Gia_ManPtrWrdReadBin( char * pFileName, int fVerbose )
SeeAlso []
***********************************************************************/
+Vec_Int_t * Gia_ManProcessBuffs( Gia_Man_t * pHie, Vec_Wrd_t * vSimsH, int nWords, Vec_Mem_t * vStore, Vec_Int_t * vLabels )
+{
+ Vec_Int_t * vPoSigs = Vec_IntAlloc( Gia_ManBufNum(pHie) );
+ Vec_Int_t * vMap;
+ Vec_Wec_t * vNodes = Vec_WecStart( Gia_ManBufNum(pHie) );
+ Gia_Obj_t * pObj; int i, Sig, Value;
+ Gia_ManForEachBuf( pHie, pObj, i )
+ {
+ word * pSim = Vec_WrdEntryP(vSimsH, Gia_ObjId(pHie, pObj)*nWords);
+ int fCompl = pSim[0] & 1;
+ if ( fCompl )
+ Abc_TtNot( pSim, nWords );
+ Vec_IntPush( vPoSigs, Vec_MemHashInsert(vStore, pSim) );
+ if ( fCompl )
+ Abc_TtNot( pSim, nWords );
+ }
+ Vec_IntPrint( vPoSigs );
+ vMap = Vec_IntStartFull( Vec_MemEntryNum(vStore) );
+ Vec_IntForEachEntry( vPoSigs, Sig, i )
+ {
+ assert( Vec_IntEntry(vMap, Sig) == -1 );
+ Vec_IntWriteEntry( vMap, Sig, i );
+ }
+ Vec_IntForEachEntry( vLabels, Sig, i )
+ {
+ if ( Sig < 0 )
+ continue;
+ Value = Vec_IntEntry(vMap, Sig);
+ if ( Value == -1 )
+ continue;
+ assert( Value >= 0 && Value < Gia_ManBufNum(pHie) );
+ Vec_WecPush( vNodes, Value, i );
+ }
+ Vec_WecPrint( vNodes, 0 );
+ Vec_WecFree( vNodes );
+ Vec_IntFree( vMap );
+ Vec_IntFree( vPoSigs );
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Gia_ManUpdateCoPhase( Gia_Man_t * pNew, Gia_Man_t * pOld )
+{
+ Gia_Obj_t * pObj; int i;
+ Gia_ManSetPhase( pNew );
+ Gia_ManSetPhase( pOld );
+ Gia_ManForEachCo( pNew, pObj, i )
+ if ( pObj->fPhase ^ Gia_ManCo(pOld, i)->fPhase )
+ {
+ printf( "Updating out %d.\n", i );
+ Gia_ObjFlipFaninC0( pObj );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
void Gia_ManCompareSims( Gia_Man_t * pHie, Gia_Man_t * pFlat, int nWords, int fVerbose )
{
abctime clk = Abc_Clock();
Vec_Wrd_t * vSims = pFlat->vSimsPi = pHie->vSimsPi = Vec_WrdStartRandom( Gia_ManCiNum(pFlat) * nWords );
Vec_Wrd_t * vSims0 = Gia_ManSimPatSim( pFlat );
Vec_Wrd_t * vSims1 = Gia_ManSimPatSim( pHie );
- Gia_Obj_t * pObj; int * pSpot, * pSpot2, i, nC0s = 0, nC1s = 0, nUnique = 0, nFound[3] = {0}, nBoundary = 0, nMatched = 0;
+ Vec_Int_t * vLabels = Vec_IntStartFull( Gia_ManObjNum(pFlat) );
+ Gia_Obj_t * pObj; int fCompl, Value, * pSpot, * pSpot2, i, nC0s = 0, nC1s = 0, nUnique = 0, nFound[3] = {0}, nBoundary = 0, nMatched = 0;
Vec_Mem_t * vStore = Vec_MemAlloc( nWords, 12 ); // 2^12 N-word entries per page
pFlat->vSimsPi = NULL;
pHie->vSimsPi = NULL;
@@ -2739,7 +2816,13 @@ void Gia_ManCompareSims( Gia_Man_t * pHie, Gia_Man_t * pFlat, int nWords, int fV
word * pSim = Vec_WrdEntryP(vSims0, i*nWords);
nC0s += Abc_TtIsConst0(pSim, nWords);
nC1s += Abc_TtIsConst1(pSim, nWords);
- Vec_MemHashInsert( vStore, pSim );
+ fCompl = pSim[0] & 1;
+ if ( fCompl )
+ Abc_TtNot( pSim, nWords );
+ Value = Vec_MemHashInsert( vStore, pSim );
+ if ( fCompl )
+ Abc_TtNot( pSim, nWords );
+ Vec_IntWriteEntry( vLabels, i, Value );
}
nUnique = Vec_MemEntryNum( vStore );
printf( "Simulating %d patterns through the second (flat) AIG leads to %d unique objects (%.2f %% out of %d). Const0 = %d. Const1 = %d.\n",
@@ -2765,10 +2848,12 @@ void Gia_ManCompareSims( Gia_Man_t * pHie, Gia_Man_t * pFlat, int nWords, int fV
//if ( Gia_ObjIsBuf(pObj) )
// printf( "%d(%d) ", i, nBoundary-1 );
}
+ Gia_ManProcessBuffs( pHie, vSims1, nWords, vStore, vLabels );
Vec_MemHashFree( vStore );
Vec_MemFree( vStore );
Vec_WrdFree( vSims0 );
Vec_WrdFree( vSims1 );
+ Vec_IntFree( vLabels );
printf( "The first (hierarchical) AIG has %d (%.2f %%) matches, %d (%.2f %%) mismatches, including %d (%.2f %%) on the boundary. ",
nMatched, 100.0*nMatched /Abc_MaxInt(1, Gia_ManCandNum(pHie)),
@@ -2777,6 +2862,405 @@ void Gia_ManCompareSims( Gia_Man_t * pHie, Gia_Man_t * pFlat, int nWords, int fV
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Wec_t * Gia_ManRelTfos( Gia_Man_t * p, Vec_Int_t * vObjs )
+{
+ Gia_Obj_t * pObj;
+ Vec_Wec_t * vNodes = Vec_WecStart( Vec_IntSize(vObjs)+1 );
+ Vec_Int_t * vSigns = Vec_IntStart( Gia_ManObjNum(p) );
+ int n, k, i, iObj, * pSigns = Vec_IntArray(vSigns);
+ assert( Vec_IntSize(vObjs) < 32 );
+ Vec_IntForEachEntry( vObjs, iObj, i )
+ pSigns[iObj] |= 1 << i;
+ Gia_ManForEachAnd( p, pObj, i )
+ {
+ if ( pSigns[i] == 0 )
+ for ( n = 0; n < 2; n++ )
+ pSigns[i] |= pSigns[Gia_ObjFaninId(pObj, i, n)];
+ if ( pSigns[i] == 0 )
+ continue;
+ Vec_WecPush( vNodes, Vec_IntSize(vObjs), i );
+ for ( k = 0; k < Vec_IntSize(vObjs); k++ )
+ if ( (pSigns[i] >> k) & 1 )
+ Vec_WecPush( vNodes, k, i );
+ }
+ Vec_IntFree( vSigns );
+ return vNodes;
+}
+Vec_Wrd_t * Gia_ManRelDerive( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wrd_t * vSims )
+{
+ int nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); Gia_Obj_t * pObj;
+ int i, m, iVar, iMint = 0, nMints = 1 << Vec_IntSize(vObjs);
+ Vec_Wrd_t * vCopy = Vec_WrdDup(vSims); Vec_Int_t * vLevel;
+ Vec_Wrd_t * vRel = Vec_WrdStart( Gia_ManCoNum(p) * nWords * nMints );
+ Vec_Wec_t * vNodes = Gia_ManRelTfos( p, vObjs );
+ Vec_WecPrint( vNodes, 0 );
+ Gia_ManForEachAnd( p, pObj, i )
+ assert( pObj->fPhase == 0 );
+ Gia_ManForEachObjVec( vObjs, p, pObj, i )
+ pObj->fPhase = 1;
+ vLevel = Vec_WecEntry( vNodes, Vec_IntSize(vObjs) );
+ Gia_ManForEachObjVec( vLevel, p, pObj, i )
+ if ( pObj->fPhase )
+ Abc_TtClear( Vec_WrdEntryP(vCopy, Gia_ObjId(p, pObj)*nWords), nWords );
+ else
+ Gia_ManSimPatSimAnd( p, Gia_ObjId(p, pObj), pObj, nWords, vCopy );
+ for ( m = 0; m < nMints; m++ )
+ {
+ Gia_ManForEachCo( p, pObj, i )
+ {
+ word * pSimO = Vec_WrdEntryP(vCopy, Gia_ObjId(p, pObj)*nWords);
+ word * pSimF = Vec_WrdEntryP(vCopy, Gia_ObjFaninId0p(p, pObj)*nWords);
+ word * pSimR = Vec_WrdEntryP(vRel, (iMint*Gia_ManCoNum(p) + i)*nWords);
+ Abc_TtXor( pSimR, pSimF, pSimO, nWords, Gia_ObjFaninC0(pObj) );
+ }
+ if ( m == nMints-1 )
+ break;
+ iVar = Abc_TtSuppFindFirst( (m+1) ^ ((m+1) >> 1) ^ (m) ^ ((m) >> 1) );
+ vLevel = Vec_WecEntry( vNodes, iVar );
+ assert( Vec_IntEntry(vLevel, 0) == Vec_IntEntry(vObjs, iVar) );
+ Abc_TtNot( Vec_WrdEntryP(vCopy, Vec_IntEntry(vObjs, iVar)*nWords), nWords );
+ Gia_ManForEachObjVec( vLevel, p, pObj, i )
+ if ( !pObj->fPhase )
+ Gia_ManSimPatSimAnd( p, Gia_ObjId(p, pObj), pObj, nWords, vCopy );
+ iMint ^= 1 << iVar;
+ }
+ Gia_ManForEachObjVec( vObjs, p, pObj, i )
+ pObj->fPhase = 0;
+ Vec_WrdFree( vCopy );
+ Vec_WecFree( vNodes );
+ return vRel;
+}
+Vec_Wrd_t * Gia_ManRelDerive2( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wrd_t * vSims )
+{
+ int nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); Gia_Obj_t * pObj;
+ int i, Id, m, Index, nMints = 1 << Vec_IntSize(vObjs);
+ Vec_Wrd_t * vPos, * vRel = Vec_WrdStart( Gia_ManCoNum(p) * nWords * nMints );
+ for ( m = 0; m < nMints; m++ )
+ {
+ Gia_Man_t * pNew = Gia_ManDup( p );
+ Gia_ManForEachAnd( pNew, pObj, i )
+ {
+ if ( (Index = Vec_IntFind(vObjs, Gia_ObjFaninId0(pObj, i))) >= 0 )
+ pObj->iDiff0 = i, pObj->fCompl0 ^= (m >> Index) & 1;
+ if ( (Index = Vec_IntFind(vObjs, Gia_ObjFaninId1(pObj, i))) >= 0 )
+ pObj->iDiff1 = i, pObj->fCompl1 ^= (m >> Index) & 1;
+ }
+ vPos = Gia_ManSimPatSimOut( pNew, p->vSimsPi, 1 );
+ Gia_ManForEachCoId( p, Id, i )
+ Abc_TtXor( Vec_WrdEntryP(vRel, (m*Gia_ManCoNum(p) + i)*nWords), Vec_WrdEntryP(vPos, i*nWords), Vec_WrdEntryP(vSims, Id*nWords), nWords, 0 );
+ Vec_WrdFree( vPos );
+ Gia_ManStop( pNew );
+ }
+ return vRel;
+}
+void Gia_ManRelPrint( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wrd_t * vSims, Vec_Wrd_t * vRel )
+{
+ int w, nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p);
+ int i, Id, m, nMints = 1 << Vec_IntSize(vObjs);
+ printf( "Relation has %d inputs and %d outputs:\n", Gia_ManCiNum(p), Vec_IntSize(vObjs) );
+ for ( w = 0; w < 64*nWords; w++ )
+ {
+ Gia_ManForEachCiId( p, Id, i )
+ printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) );
+ printf( " " );
+ Vec_IntForEachEntry( vObjs, Id, i )
+ printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) );
+ printf( " " );
+ Gia_ManForEachCoId( p, Id, i )
+ printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) );
+ printf( " " );
+ for ( m = 0; m < nMints; m++ )
+ {
+ printf( " " );
+ for ( i = 0; i < Vec_IntSize(vObjs); i++ )
+ printf( "%d", (m >> i) & 1 );
+ printf( "=" );
+ Gia_ManForEachCoId( p, Id, i )
+ printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vRel, (m*Gia_ManCoNum(p)+i)*nWords), w) );
+ }
+ printf( "\n" );
+ }
+}
+void Gia_ManRelPrint2( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wrd_t * vSims, Vec_Wrd_t * vRel )
+{
+ int w, nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p);
+ int i, Id, m, nMints = 1 << Vec_IntSize(vObjs);
+ int nWordsM = Abc_Truth6WordNum(Vec_IntSize(vObjs));
+ Vec_Wrd_t * vRes = Vec_WrdStart( 64*nWords * nWordsM );
+ printf( "Relation has %d inputs and %d outputs:\n", Gia_ManCiNum(p), Vec_IntSize(vObjs) );
+ for ( w = 0; w < 64*nWords; w++ )
+ {
+ int iMint = 0;
+ int nValid = 0;
+ Gia_ManForEachCiId( p, Id, i )
+ printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) );
+ printf( " " );
+ Vec_IntForEachEntry( vObjs, Id, i )
+ {
+ printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) );
+ if ( Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) )
+ iMint |= 1 << i;
+ }
+ printf( " " );
+ Gia_ManForEachCoId( p, Id, i )
+ printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) );
+ printf( " " );
+ for ( m = 0; m < nMints; m++ )
+ {
+ int Count = 0;
+ Gia_ManForEachCoId( p, Id, i )
+ Count += Abc_TtGetBit(Vec_WrdEntryP(vRel, (m*Gia_ManCoNum(p)+i)*nWords), w);
+ printf( "%d", Count == 0 );
+ nValid += Count > 0;
+ if ( Count == 0 )
+ Abc_TtSetBit( Vec_WrdEntryP(vRes, w*nWordsM), m );
+ }
+ printf( " " );
+ for ( m = 0; m < nMints; m++ )
+ printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vRes, w*nWordsM), m) );
+ printf( " " );
+ assert( Abc_TtGetBit(Vec_WrdEntryP(vRes, w*nWordsM), iMint) );
+ for ( i = 0; i < Vec_IntSize(vObjs); i++ )
+ if ( Abc_TtGetBit(Vec_WrdEntryP(vRes, w*nWordsM), iMint ^ (1 << i)) )
+ printf( "-" );
+ else
+ printf( "%d", (iMint >> i) & 1 );
+ printf( " %d", nMints-nValid );
+ printf( "\n" );
+ }
+ Vec_WrdFree( vRes );
+}
+Vec_Int_t * Gia_ManRelInitObjs()
+{
+ Vec_Int_t * vRes = Vec_IntAlloc( 10 );
+ /*
+ Vec_IntPush( vRes, 33 );
+ Vec_IntPush( vRes, 52 );
+ Vec_IntPush( vRes, 53 );
+ Vec_IntPush( vRes, 65 );
+ Vec_IntPush( vRes, 79 );
+ Vec_IntPush( vRes, 81 );
+ */
+ /*
+ Vec_IntPush( vRes, 60 );
+ Vec_IntPush( vRes, 61 );
+ Vec_IntPush( vRes, 71 );
+ Vec_IntPush( vRes, 72 );
+ */
+ /*
+ Vec_IntPush( vRes, 65 );
+ Vec_IntPush( vRes, 79 );
+ Vec_IntPush( vRes, 81 );
+ */
+ Vec_IntPush( vRes, 52 );
+ Vec_IntPush( vRes, 54 );
+ Vec_IntPrint( vRes );
+ return vRes;
+}
+void Gia_ManRelDeriveTest2( Gia_Man_t * p )
+{
+ Vec_Int_t * vObjs = Gia_ManRelInitObjs();
+ Vec_Wrd_t * vSims, * vRel, * vRel2; int nWords;
+ Vec_WrdFreeP( &p->vSimsPi );
+ p->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) );
+ nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p);
+ vSims = Gia_ManSimPatSim( p );
+ vRel = Gia_ManRelDerive( p, vObjs, vSims );
+ vRel2 = Gia_ManRelDerive2( p, vObjs, vSims );
+ //assert( !memcmp(vRel2->pArray, vRel->pArray, sizeof(word)*Vec_WrdSize(vRel)) );
+ Gia_ManRelPrint2( p, vObjs, vSims, vRel );
+ Vec_WrdFree( vRel2 );
+ Vec_WrdFree( vRel );
+ Vec_WrdFree( vSims );
+ Vec_IntFree( vObjs );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManRelInitIns()
+{
+ Vec_Int_t * vRes = Vec_IntAlloc( 10 );
+ Vec_IntPush( vRes, 12 );
+ Vec_IntPush( vRes, 18 );
+ Vec_IntPush( vRes, 21 );
+ Vec_IntPush( vRes, 34 );
+ Vec_IntPush( vRes, 45 );
+ Vec_IntPush( vRes, 59 );
+ return vRes;
+}
+Vec_Int_t * Gia_ManRelInitOuts()
+{
+ Vec_Int_t * vRes = Vec_IntAlloc( 10 );
+ Vec_IntPush( vRes, 65 );
+ Vec_IntPush( vRes, 66 );
+ return vRes;
+}
+Vec_Int_t * Gia_ManRelInitMffc( Gia_Man_t * p, Vec_Int_t * vOuts )
+{
+ Gia_Obj_t * pObj; int i;
+ Vec_Int_t * vRes = Vec_IntAlloc( 100 );
+ Vec_IntSort( vOuts, 0 );
+ Gia_ManIncrementTravId( p );
+ Gia_ManForEachObjVec( vOuts, p, pObj, i )
+ Gia_ObjSetTravIdCurrent( p, pObj );
+ Gia_ManIncrementTravId( p );
+ Gia_ManForEachCo( p, pObj, i )
+ if ( !Gia_ObjIsTravIdPrevious(p, Gia_ObjFanin0(pObj)) )
+ Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin0(pObj) );
+ Gia_ManForEachAndReverse( p, pObj, i )
+ if ( Gia_ObjIsTravIdPrevious(p, pObj) )
+ continue;
+ else if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+ {
+ if ( !Gia_ObjIsTravIdPrevious(p, Gia_ObjFanin0(pObj)) )
+ Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin0(pObj) );
+ if ( !Gia_ObjIsTravIdPrevious(p, Gia_ObjFanin1(pObj)) )
+ Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin1(pObj) );
+ }
+ Gia_ManForEachAnd( p, pObj, i )
+ if ( !Gia_ObjIsTravIdCurrent(p, pObj) )
+ Vec_IntPush( vRes, i );
+ printf( "MFFC: " );
+ Vec_IntPrint( vRes );
+ return vRes;
+}
+Vec_Int_t * Gia_ManRelInitDivs( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vOuts )
+{
+ Gia_Obj_t * pObj; int i;
+ Vec_Int_t * vMffc = Gia_ManRelInitMffc( p, vOuts );
+ Vec_Int_t * vRes = Vec_IntAlloc( 100 );
+ Vec_IntSort( vIns, 0 );
+
+ Gia_ManIncrementTravId( p );
+ Gia_ManForEachObjVec( vMffc, p, pObj, i )
+ Gia_ObjSetTravIdCurrent( p, pObj );
+ Vec_IntFree( vMffc );
+
+ Vec_IntPush( vRes, 0 );
+ Vec_IntAppend( vRes, vIns );
+
+ Gia_ManIncrementTravId( p );
+ Gia_ManForEachObjVec( vIns, p, pObj, i )
+ Gia_ObjSetTravIdCurrent( p, pObj );
+
+ Gia_ManForEachAnd( p, pObj, i )
+ if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+ continue;
+ else if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) && Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) )
+ {
+ if ( !Gia_ObjIsTravIdPrevious(p, pObj) )
+ Vec_IntPush( vRes, i );
+ Gia_ObjSetTravIdCurrent( p, pObj );
+ }
+ printf( "Divisors: " );
+ Vec_IntPrint( vRes );
+ return vRes;
+}
+
+Vec_Int_t * Gia_ManRelDeriveSimple( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Int_t * vIns, Vec_Int_t * vOuts )
+{
+ Vec_Int_t * vRes = Vec_IntStartFull( 1 << Vec_IntSize(vIns) );
+ int w, nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p);
+ for ( w = 0; w < 64*nWords; w++ )
+ {
+ int i, iObj, iMint = 0, iMint2 = 0;
+ Vec_IntForEachEntry( vIns, iObj, i )
+ if ( Abc_TtGetBit(Vec_WrdEntryP(vSims, iObj*nWords), w) )
+ iMint |= 1 << i;
+ if ( Vec_IntEntry(vRes, iMint) >= 0 )
+ continue;
+ Vec_IntForEachEntry( vOuts, iObj, i )
+ if ( Abc_TtGetBit(Vec_WrdEntryP(vSims, iObj*nWords), w) )
+ iMint2 |= 1 << i;
+ Vec_IntWriteEntry( vRes, iMint, iMint2 );
+ }
+ return vRes;
+}
+
+void Gia_ManRelSolve( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Int_t * vIns, Vec_Int_t * vOuts, Vec_Int_t * vRel, Vec_Int_t * vDivs )
+{
+ extern Mini_Aig_t * Exa4_ManGenTest( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, int TimeOut, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans, int fVerbose );
+
+ int i, m, iObj, Entry, iMint = 0, nMints = Vec_IntSize(vRel) - Vec_IntCountEntry(vRel, -1);
+ Vec_Wrd_t * vSimsIn = Vec_WrdStart( nMints );
+ Vec_Wrd_t * vSimsOut = Vec_WrdStart( nMints );
+ int Entry0 = Vec_IntEntry( vRel, 0 );
+
+ word Value, Phase = 0;
+ int nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p);
+ Vec_IntForEachEntry( vDivs, iObj, i )
+ if ( Vec_WrdEntry(vSims, iObj*nWords) & 1 )
+ Phase |= 1 << i;
+
+ assert( Entry0 >= 0 );
+ printf( "Entry0 = %d\n", Entry0 );
+ Entry0 ^= 1;
+// for ( m = 0; m < nMints; m++ )
+ Vec_IntForEachEntry( vRel, Entry, m )
+ {
+ if ( Entry == -1 )
+ continue;
+ Abc_TtSetBit( Vec_WrdEntryP(vSimsOut, iMint), Entry0 ^ Entry );
+
+ Value = 0;
+ Vec_IntForEachEntry( vDivs, iObj, i )
+ if ( Abc_TtGetBit(Vec_WrdEntryP(vSims, iObj*nWords), m) )
+ Abc_TtSetBit( &Value, i );
+ Vec_WrdEntryP(vSimsOut, iMint)[0] = Value ^ Phase;
+
+ iMint++;
+ }
+ assert( iMint == nMints );
+ printf( "Created %d minterms.\n", iMint );
+ Exa4_ManGenTest( vSimsIn, vSimsOut, Vec_IntSize(vIns), Vec_IntSize(vDivs), Vec_IntSize(vOuts), 10, 0, 0, 0, 0, 0, 1 );
+ Vec_WrdFree( vSimsIn );
+ Vec_WrdFree( vSimsOut );
+}
+void Gia_ManRelDeriveTest( Gia_Man_t * p )
+{
+ Vec_Int_t * vIns = Gia_ManRelInitIns();
+ Vec_Int_t * vOuts = Gia_ManRelInitOuts();
+ Vec_Wrd_t * vSims; Vec_Int_t * vRel, * vDivs; int nWords;
+ Vec_WrdFreeP( &p->vSimsPi );
+ p->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) );
+ nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p);
+ vSims = Gia_ManSimPatSim( p );
+ vRel = Gia_ManRelDeriveSimple( p, vSims, vIns, vOuts );
+ vDivs = Gia_ManRelInitDivs( p, vIns, vOuts );
+ //printf( "Neg = %d\n", Vec_IntCountEntry(vRel, -1) );
+
+ Gia_ManRelSolve( p, vSims, vIns, vOuts, vRel, vDivs );
+
+ Vec_IntFree( vDivs );
+ Vec_IntPrint( vRel );
+ Vec_IntFree( vRel );
+ Vec_WrdFree( vSims );
+ Vec_IntFree( vIns );
+ Vec_IntFree( vOuts );
+}
+
+
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/aig/gia/giaTtopt.cpp b/src/aig/gia/giaTtopt.cpp
new file mode 100644
index 00000000..a765633f
--- /dev/null
+++ b/src/aig/gia/giaTtopt.cpp
@@ -0,0 +1,1213 @@
+/**CFile****************************************************************
+
+ FileName [giaTtopt.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Scalable AIG package.]
+
+ Synopsis [Truth-table-based logic synthesis.]
+
+ Author [Yukio Miyasaka]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: giaTtopt.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifdef _WIN32
+#ifndef __MINGW32__
+#pragma warning(disable : 4786) // warning C4786: identifier was truncated to '255' characters in the browser information
+#endif
+#endif
+
+#include <vector>
+#include <algorithm>
+#include <cassert>
+#include <bitset>
+
+#include "gia.h"
+#include "misc/vec/vecHash.h"
+
+ABC_NAMESPACE_IMPL_START
+
+namespace Ttopt {
+
+class TruthTable {
+public:
+ static const int ww; // word width
+ static const int lww; // log word width
+ typedef std::bitset<64> bsw;
+
+ int nInputs;
+ int nSize;
+ int nTotalSize;
+ int nOutputs;
+ std::vector<word> t;
+
+ std::vector<std::vector<int> > vvIndices;
+ std::vector<std::vector<int> > vvRedundantIndices;
+ std::vector<int> vLevels;
+
+ std::vector<std::vector<word> > savedt;
+ std::vector<std::vector<std::vector<int> > > vvIndicesSaved;
+ std::vector<std::vector<std::vector<int> > > vvRedundantIndicesSaved;
+ std::vector<std::vector<int> > vLevelsSaved;
+
+ static const word ones[];
+ static const word swapmask[];
+
+ TruthTable(int nInputs, int nOutputs): nInputs(nInputs), nOutputs(nOutputs) {
+ srand(0xABC);
+ if(nInputs >= lww) {
+ nSize = 1 << (nInputs - lww);
+ nTotalSize = nSize * nOutputs;
+ t.resize(nTotalSize);
+ } else {
+ nSize = 0;
+ nTotalSize = ((1 << nInputs) * nOutputs + ww - 1) / ww;
+ t.resize(nTotalSize);
+ }
+ vLevels.resize(nInputs);
+ for(int i = 0; i < nInputs; i++) {
+ vLevels[i] = i;
+ }
+ }
+
+ virtual void Save(unsigned i) {
+ if(savedt.size() < i + 1) {
+ savedt.resize(i + 1);
+ vLevelsSaved.resize(i + 1);
+ }
+ savedt[i] = t;
+ vLevelsSaved[i] = vLevels;
+ }
+
+ virtual void Load(unsigned i) {
+ assert(i < savedt.size());
+ t = savedt[i];
+ vLevels = vLevelsSaved[i];
+ }
+
+ virtual void SaveIndices(unsigned i) {
+ if(vvIndicesSaved.size() < i + 1) {
+ vvIndicesSaved.resize(i + 1);
+ vvRedundantIndicesSaved.resize(i + 1);
+ }
+ vvIndicesSaved[i] = vvIndices;
+ vvRedundantIndicesSaved[i] = vvRedundantIndices;
+ }
+
+ virtual void LoadIndices(unsigned i) {
+ vvIndices = vvIndicesSaved[i];
+ vvRedundantIndices = vvRedundantIndicesSaved[i];
+ }
+
+ word GetValue(int index_lev, int lev) {
+ assert(index_lev >= 0);
+ assert(nInputs - lev <= lww);
+ int logwidth = nInputs - lev;
+ int index = index_lev >> (lww - logwidth);
+ int pos = (index_lev % (1 << (lww - logwidth))) << logwidth;
+ return (t[index] >> pos) & ones[logwidth];
+ }
+
+ int IsEq(int index1, int index2, int lev, bool fCompl = false) {
+ assert(index1 >= 0);
+ assert(index2 >= 0);
+ int logwidth = nInputs - lev;
+ bool fEq = true;
+ if(logwidth > lww) {
+ int nScopeSize = 1 << (logwidth - lww);
+ for(int i = 0; i < nScopeSize && (fEq || fCompl); i++) {
+ fEq &= (t[nScopeSize * index1 + i] == t[nScopeSize * index2 + i]);
+ fCompl &= (t[nScopeSize * index1 + i] == ~t[nScopeSize * index2 + i]);
+ }
+ } else {
+ word value = GetValue(index1, lev) ^ GetValue(index2, lev);
+ fEq &= !value;
+ fCompl &= !(value ^ ones[logwidth]);
+ }
+ return 2 * fCompl + fEq;
+ }
+
+ bool Imply(int index1, int index2, int lev) {
+ assert(index1 >= 0);
+ assert(index2 >= 0);
+ int logwidth = nInputs - lev;
+ if(logwidth > lww) {
+ int nScopeSize = 1 << (logwidth - lww);
+ for(int i = 0; i < nScopeSize; i++) {
+ if(t[nScopeSize * index1 + i] & ~t[nScopeSize * index2 + i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return !(GetValue(index1, lev) & (GetValue(index2, lev) ^ ones[logwidth]));
+ }
+
+ int BDDNodeCountLevel(int lev) {
+ return vvIndices[lev].size() - vvRedundantIndices[lev].size();
+ }
+
+ int BDDNodeCount() {
+ int count = 1; // const node
+ for(int i = 0; i < nInputs; i++) {
+ count += BDDNodeCountLevel(i);
+ }
+ return count;
+ }
+
+ int BDDFind(int index, int lev) {
+ int logwidth = nInputs - lev;
+ if(logwidth > lww) {
+ int nScopeSize = 1 << (logwidth - lww);
+ bool fZero = true;
+ bool fOne = true;
+ for(int i = 0; i < nScopeSize && (fZero || fOne); i++) {
+ word value = t[nScopeSize * index + i];
+ fZero &= !value;
+ fOne &= !(~value);
+ }
+ if(fZero || fOne) {
+ return -2 ^ (int)fOne;
+ }
+ for(unsigned j = 0; j < vvIndices[lev].size(); j++) {
+ int index2 = vvIndices[lev][j];
+ bool fEq = true;
+ bool fCompl = true;
+ for(int i = 0; i < nScopeSize && (fEq || fCompl); i++) {
+ fEq &= (t[nScopeSize * index + i] == t[nScopeSize * index2 + i]);
+ fCompl &= (t[nScopeSize * index + i] == ~t[nScopeSize * index2 + i]);
+ }
+ if(fEq || fCompl) {
+ return (j << 1) ^ (int)fCompl;
+ }
+ }
+ } else {
+ word value = GetValue(index, lev);
+ if(!value) {
+ return -2;
+ }
+ if(!(value ^ ones[logwidth])) {
+ return -1;
+ }
+ for(unsigned j = 0; j < vvIndices[lev].size(); j++) {
+ int index2 = vvIndices[lev][j];
+ word value2 = value ^ GetValue(index2, lev);
+ if(!(value2)) {
+ return j << 1;
+ }
+ if(!(value2 ^ ones[logwidth])) {
+ return (j << 1) ^ 1;
+ }
+ }
+ }
+ return -3;
+ }
+
+ virtual int BDDBuildOne(int index, int lev) {
+ int r = BDDFind(index, lev);
+ if(r >= -2) {
+ return r;
+ }
+ vvIndices[lev].push_back(index);
+ return (vvIndices[lev].size() - 1) << 1;
+ }
+
+ virtual void BDDBuildStartup() {
+ vvIndices.clear();
+ vvIndices.resize(nInputs);
+ vvRedundantIndices.clear();
+ vvRedundantIndices.resize(nInputs);
+ for(int i = 0; i < nOutputs; i++) {
+ BDDBuildOne(i, 0);
+ }
+ }
+
+ virtual void BDDBuildLevel(int lev) {
+ for(unsigned i = 0; i < vvIndices[lev-1].size(); i++) {
+ int index = vvIndices[lev-1][i];
+ int cof0 = BDDBuildOne(index << 1, lev);
+ int cof1 = BDDBuildOne((index << 1) ^ 1, lev);
+ if(cof0 == cof1) {
+ vvRedundantIndices[lev-1].push_back(index);
+ }
+ }
+ }
+
+ virtual int BDDBuild() {
+ BDDBuildStartup();
+ for(int i = 1; i < nInputs; i++) {
+ BDDBuildLevel(i);
+ }
+ return BDDNodeCount();
+ }
+
+ virtual int BDDRebuild(int lev) {
+ vvIndices[lev].clear();
+ vvIndices[lev+1].clear();
+ for(int i = lev; i < lev + 2; i++) {
+ if(!i) {
+ for(int j = 0; j < nOutputs; j++) {
+ BDDBuildOne(j, 0);
+ }
+ } else {
+ vvRedundantIndices[i-1].clear();
+ BDDBuildLevel(i);
+ }
+ }
+ if(lev < nInputs - 2) {
+ vvRedundantIndices[lev+1].clear();
+ for(unsigned i = 0; i < vvIndices[lev+1].size(); i++) {
+ int index = vvIndices[lev+1][i];
+ if(IsEq(index << 1, (index << 1) ^ 1, lev + 2)) {
+ vvRedundantIndices[lev+1].push_back(index);
+ }
+ }
+ }
+ return BDDNodeCount();
+ }
+
+ virtual void Swap(int lev) {
+ assert(lev < nInputs - 1);
+ std::vector<int>::iterator it0 = std::find(vLevels.begin(), vLevels.end(), lev);
+ std::vector<int>::iterator it1 = std::find(vLevels.begin(), vLevels.end(), lev + 1);
+ std::swap(*it0, *it1);
+ if(nInputs - lev - 1 > lww) {
+ int nScopeSize = 1 << (nInputs - lev - 2 - lww);
+ for(int i = nScopeSize; i < nTotalSize; i += (nScopeSize << 2)) {
+ for(int j = 0; j < nScopeSize; j++) {
+ std::swap(t[i + j], t[i + nScopeSize + j]);
+ }
+ }
+ } else if(nInputs - lev - 1 == lww) {
+ for(int i = 0; i < nTotalSize; i += 2) {
+ t[i+1] ^= t[i] >> (ww / 2);
+ t[i] ^= t[i+1] << (ww / 2);
+ t[i+1] ^= t[i] >> (ww / 2);
+ }
+ } else {
+ for(int i = 0; i < nTotalSize; i++) {
+ int d = nInputs - lev - 2;
+ int shamt = 1 << d;
+ t[i] ^= (t[i] >> shamt) & swapmask[d];
+ t[i] ^= (t[i] & swapmask[d]) << shamt;
+ t[i] ^= (t[i] >> shamt) & swapmask[d];
+ }
+ }
+ }
+
+ void SwapIndex(int &index, int d) {
+ if((index >> d) % 4 == 1) {
+ index += 1 << d;
+ } else if((index >> d) % 4 == 2) {
+ index -= 1 << d;
+ }
+ }
+
+ virtual int BDDSwap(int lev) {
+ Swap(lev);
+ for(int i = lev + 2; i < nInputs; i++) {
+ for(unsigned j = 0; j < vvIndices[i].size(); j++) {
+ SwapIndex(vvIndices[i][j], i - (lev + 2));
+ }
+ }
+ // swapping vvRedundantIndices is unnecessary for node counting
+ return BDDRebuild(lev);
+ }
+
+ int SiftReo() {
+ int best = BDDBuild();
+ Save(0);
+ SaveIndices(0);
+ std::vector<int> vars(nInputs);
+ int i;
+ for(i = 0; i < nInputs; i++) {
+ vars[i] = i;
+ }
+ std::vector<unsigned> vCounts(nInputs);
+ for(i = 0; i < nInputs; i++) {
+ vCounts[i] = BDDNodeCountLevel(vLevels[i]);
+ }
+ for(i = 1; i < nInputs; i++) {
+ int j = i;
+ while(j > 0 && vCounts[vars[j-1]] < vCounts[vars[j]]) {
+ std::swap(vars[j], vars[j-1]);
+ j--;
+ }
+ }
+ bool turn = true;
+ unsigned j;
+ for(j = 0; j < vars.size(); j++) {
+ int var = vars[j];
+ bool updated = false;
+ int lev = vLevels[var];
+ for(int i = lev; i < nInputs - 1; i++) {
+ int count = BDDSwap(i);
+ if(best > count) {
+ best = count;
+ updated = true;
+ Save(turn);
+ SaveIndices(turn);
+ }
+ }
+ if(lev) {
+ Load(!turn);
+ LoadIndices(!turn);
+ for(int i = lev - 1; i >= 0; i--) {
+ int count = BDDSwap(i);
+ if(best > count) {
+ best = count;
+ updated = true;
+ Save(turn);
+ SaveIndices(turn);
+ }
+ }
+ }
+ turn ^= updated;
+ Load(!turn);
+ LoadIndices(!turn);
+ }
+ return best;
+ }
+
+ void Reo(std::vector<int> vLevelsNew) {
+ for(int i = 0; i < nInputs; i++) {
+ int var = std::find(vLevelsNew.begin(), vLevelsNew.end(), i) - vLevelsNew.begin();
+ int lev = vLevels[var];
+ if(lev < i) {
+ for(int j = lev; j < i; j++) {
+ Swap(j);
+ }
+ } else if(lev > i) {
+ for(int j = lev - 1; j >= i; j--) {
+ Swap(j);
+ }
+ }
+ }
+ assert(vLevels == vLevelsNew);
+ }
+
+ int RandomSiftReo(int nRound) {
+ int best = SiftReo();
+ Save(2);
+ for(int i = 0; i < nRound; i++) {
+ std::vector<int> vLevelsNew(nInputs);
+ int j;
+ for(j = 0; j < nInputs; j++) {
+ vLevelsNew[j] = j;
+ }
+ for(j = nInputs - 1; j > 0; j--) {
+ int d = rand() % j;
+ std::swap(vLevelsNew[j], vLevelsNew[d]);
+ }
+ Reo(vLevelsNew);
+ int r = SiftReo();
+ if(best > r) {
+ best = r;
+ Save(2);
+ }
+ }
+ Load(2);
+ return best;
+ }
+
+ int BDDGenerateAigRec(Gia_Man_t *pNew, std::vector<int> const &vInputs, std::vector<std::vector<int> > &vvNodes, int index, int lev) {
+ int r = BDDFind(index, lev);
+ if(r >= 0) {
+ return vvNodes[lev][r >> 1] ^ (r & 1);
+ }
+ if(r >= -2) {
+ return r + 2;
+ }
+ int cof0 = BDDGenerateAigRec(pNew, vInputs, vvNodes, index << 1, lev + 1);
+ int cof1 = BDDGenerateAigRec(pNew, vInputs, vvNodes, (index << 1) ^ 1, lev + 1);
+ if(cof0 == cof1) {
+ return cof0;
+ }
+ int node;
+ if(Imply(index << 1, (index << 1) ^ 1, lev + 1)) {
+ node = Gia_ManHashOr(pNew, Gia_ManHashAnd(pNew, vInputs[lev], cof1), cof0);
+ } else if(Imply((index << 1) ^ 1, index << 1, lev + 1)) {
+ node = Gia_ManHashOr(pNew, Gia_ManHashAnd(pNew, vInputs[lev] ^ 1, cof0), cof1);
+ } else {
+ node = Gia_ManHashMux(pNew, vInputs[lev], cof1, cof0);
+ }
+ vvIndices[lev].push_back(index);
+ vvNodes[lev].push_back(node);
+ return node;
+ }
+
+ virtual void BDDGenerateAig(Gia_Man_t *pNew, Vec_Int_t *vSupp) {
+ vvIndices.clear();
+ vvIndices.resize(nInputs);
+ std::vector<std::vector<int> > vvNodes(nInputs);
+ std::vector<int> vInputs(nInputs);
+ int i;
+ for(i = 0; i < nInputs; i++) {
+ vInputs[vLevels[i]] = Vec_IntEntry(vSupp, nInputs - i - 1) << 1;
+ }
+ for(i = 0; i < nOutputs; i++) {
+ int node = BDDGenerateAigRec(pNew, vInputs, vvNodes, i, 0);
+ Gia_ManAppendCo(pNew, node);
+ }
+ }
+};
+
+const int TruthTable::ww = 64;
+const int TruthTable::lww = 6;
+
+const word TruthTable::ones[7] = {ABC_CONST(0x0000000000000001),
+ ABC_CONST(0x0000000000000003),
+ ABC_CONST(0x000000000000000f),
+ ABC_CONST(0x00000000000000ff),
+ ABC_CONST(0x000000000000ffff),
+ ABC_CONST(0x00000000ffffffff),
+ ABC_CONST(0xffffffffffffffff)};
+
+const word TruthTable::swapmask[5] = {ABC_CONST(0x2222222222222222),
+ ABC_CONST(0x0c0c0c0c0c0c0c0c),
+ ABC_CONST(0x00f000f000f000f0),
+ ABC_CONST(0x0000ff000000ff00),
+ ABC_CONST(0x00000000ffff0000)};
+
+class TruthTableReo : public TruthTable {
+public:
+ bool fBuilt;
+ std::vector<std::vector<int> > vvChildren;
+ std::vector<std::vector<std::vector<int> > > vvChildrenSaved;
+
+ TruthTableReo(int nInputs, int nOutputs): TruthTable(nInputs, nOutputs) {
+ fBuilt = false;
+ }
+
+ void Save(unsigned i) {
+ if(vLevelsSaved.size() < i + 1) {
+ vLevelsSaved.resize(i + 1);
+ }
+ vLevelsSaved[i] = vLevels;
+ }
+
+ void Load(unsigned i) {
+ assert(i < vLevelsSaved.size());
+ vLevels = vLevelsSaved[i];
+ }
+
+ void SaveIndices(unsigned i) {
+ TruthTable::SaveIndices(i);
+ if(vvChildrenSaved.size() < i + 1) {
+ vvChildrenSaved.resize(i + 1);
+ }
+ vvChildrenSaved[i] = vvChildren;
+ }
+
+ void LoadIndices(unsigned i) {
+ TruthTable::LoadIndices(i);
+ vvChildren = vvChildrenSaved[i];
+ }
+
+ void BDDBuildStartup() {
+ vvChildren.clear();
+ vvChildren.resize(nInputs);
+ TruthTable::BDDBuildStartup();
+ }
+
+ void BDDBuildLevel(int lev) {
+ for(unsigned i = 0; i < vvIndices[lev-1].size(); i++) {
+ int index = vvIndices[lev-1][i];
+ int cof0 = BDDBuildOne(index << 1, lev);
+ int cof1 = BDDBuildOne((index << 1) ^ 1, lev);
+ vvChildren[lev-1].push_back(cof0);
+ vvChildren[lev-1].push_back(cof1);
+ if(cof0 == cof1) {
+ vvRedundantIndices[lev-1].push_back(index);
+ }
+ }
+ }
+
+ int BDDBuild() {
+ if(fBuilt) {
+ return BDDNodeCount();
+ }
+ fBuilt = true;
+ BDDBuildStartup();
+ for(int i = 1; i < nInputs + 1; i++) {
+ BDDBuildLevel(i);
+ }
+ return BDDNodeCount();
+ }
+
+ int BDDRebuildOne(int index, int cof0, int cof1, int lev, Hash_IntMan_t *unique, std::vector<int> &vChildrenLow) {
+ if(cof0 < 0 && cof0 == cof1) {
+ return cof0;
+ }
+ bool fCompl = cof0 & 1;
+ if(fCompl) {
+ cof0 ^= 1;
+ cof1 ^= 1;
+ }
+ int *place = Hash_Int2ManLookup(unique, cof0, cof1);
+ if(*place) {
+ return (Hash_IntObjData2(unique, *place) << 1) ^ (int)fCompl;
+ }
+ vvIndices[lev].push_back(index);
+ Hash_Int2ManInsert(unique, cof0, cof1, vvIndices[lev].size() - 1);
+ vChildrenLow.push_back(cof0);
+ vChildrenLow.push_back(cof1);
+ if(cof0 == cof1) {
+ vvRedundantIndices[lev].push_back(index);
+ }
+ return ((vvIndices[lev].size() - 1) << 1) ^ (int)fCompl;
+ }
+
+ int BDDRebuild(int lev) {
+ vvRedundantIndices[lev].clear();
+ vvRedundantIndices[lev+1].clear();
+ std::vector<int> vChildrenHigh;
+ std::vector<int> vChildrenLow;
+ Hash_IntMan_t *unique = Hash_IntManStart(2 * vvIndices[lev+1].size());
+ vvIndices[lev+1].clear();
+ for(unsigned i = 0; i < vvIndices[lev].size(); i++) {
+ int index = vvIndices[lev][i];
+ int cof0index = vvChildren[lev][i+i] >> 1;
+ int cof1index = vvChildren[lev][i+i+1] >> 1;
+ bool cof0c = vvChildren[lev][i+i] & 1;
+ bool cof1c = vvChildren[lev][i+i+1] & 1;
+ int cof00, cof01, cof10, cof11;
+ if(cof0index < 0) {
+ cof00 = -2 ^ (int)cof0c;
+ cof01 = -2 ^ (int)cof0c;
+ } else {
+ cof00 = vvChildren[lev+1][cof0index+cof0index] ^ (int)cof0c;
+ cof01 = vvChildren[lev+1][cof0index+cof0index+1] ^ (int)cof0c;
+ }
+ if(cof1index < 0) {
+ cof10 = -2 ^ (int)cof1c;
+ cof11 = -2 ^ (int)cof1c;
+ } else {
+ cof10 = vvChildren[lev+1][cof1index+cof1index] ^ (int)cof1c;
+ cof11 = vvChildren[lev+1][cof1index+cof1index+1] ^ (int)cof1c;
+ }
+ int newcof0 = BDDRebuildOne(index << 1, cof00, cof10, lev + 1, unique, vChildrenLow);
+ int newcof1 = BDDRebuildOne((index << 1) ^ 1, cof01, cof11, lev + 1, unique, vChildrenLow);
+ vChildrenHigh.push_back(newcof0);
+ vChildrenHigh.push_back(newcof1);
+ if(newcof0 == newcof1) {
+ vvRedundantIndices[lev].push_back(index);
+ }
+ }
+ Hash_IntManStop(unique);
+ vvChildren[lev] = vChildrenHigh;
+ vvChildren[lev+1] = vChildrenLow;
+ return BDDNodeCount();
+ }
+
+ void Swap(int lev) {
+ assert(lev < nInputs - 1);
+ std::vector<int>::iterator it0 = std::find(vLevels.begin(), vLevels.end(), lev);
+ std::vector<int>::iterator it1 = std::find(vLevels.begin(), vLevels.end(), lev + 1);
+ std::swap(*it0, *it1);
+ BDDRebuild(lev);
+ }
+
+ int BDDSwap(int lev) {
+ Swap(lev);
+ return BDDNodeCount();
+ }
+
+ virtual void BDDGenerateAig(Gia_Man_t *pNew, Vec_Int_t *vSupp) {
+ abort();
+ }
+};
+
+class TruthTableRewrite : public TruthTable {
+public:
+ TruthTableRewrite(int nInputs, int nOutputs): TruthTable(nInputs, nOutputs) {}
+
+ void SetValue(int index_lev, int lev, word value) {
+ assert(index_lev >= 0);
+ assert(nInputs - lev <= lww);
+ int logwidth = nInputs - lev;
+ int index = index_lev >> (lww - logwidth);
+ int pos = (index_lev % (1 << (lww - logwidth))) << logwidth;
+ t[index] &= ~(ones[logwidth] << pos);
+ t[index] ^= value << pos;
+ }
+
+ void CopyFunc(int index1, int index2, int lev, bool fCompl) {
+ assert(index1 >= 0);
+ int logwidth = nInputs - lev;
+ if(logwidth > lww) {
+ int nScopeSize = 1 << (logwidth - lww);
+ if(!fCompl) {
+ if(index2 < 0) {
+ for(int i = 0; i < nScopeSize; i++) {
+ t[nScopeSize * index1 + i] = 0;
+ }
+ } else {
+ for(int i = 0; i < nScopeSize; i++) {
+ t[nScopeSize * index1 + i] = t[nScopeSize * index2 + i];
+ }
+ }
+ } else {
+ if(index2 < 0) {
+ for(int i = 0; i < nScopeSize; i++) {
+ t[nScopeSize * index1 + i] = ones[lww];
+ }
+ } else {
+ for(int i = 0; i < nScopeSize; i++) {
+ t[nScopeSize * index1 + i] = ~t[nScopeSize * index2 + i];
+ }
+ }
+ }
+ } else {
+ word value = 0;
+ if(index2 >= 0) {
+ value = GetValue(index2, lev);
+ }
+ if(fCompl) {
+ value ^= ones[logwidth];
+ }
+ SetValue(index1, lev, value);
+ }
+ }
+
+ void ShiftToMajority(int index, int lev) {
+ assert(index >= 0);
+ int logwidth = nInputs - lev;
+ int count = 0;
+ if(logwidth > lww) {
+ int nScopeSize = 1 << (logwidth - lww);
+ for(int i = 0; i < nScopeSize; i++) {
+ count += bsw(t[nScopeSize * index + i]).count();
+ }
+ } else {
+ count = bsw(GetValue(index, lev)).count();
+ }
+ bool majority = count > (1 << (logwidth - 1));
+ CopyFunc(index, -1, lev, majority);
+ }
+};
+
+class TruthTableCare : public TruthTableRewrite {
+public:
+ std::vector<word> originalt;
+ std::vector<word> caret;
+ std::vector<word> care;
+
+ std::vector<std::vector<std::pair<int, int> > > vvMergedIndices;
+
+ std::vector<std::vector<word> > savedcare;
+ std::vector<std::vector<std::vector<std::pair<int, int> > > > vvMergedIndicesSaved;
+
+ TruthTableCare(int nInputs, int nOutputs): TruthTableRewrite(nInputs, nOutputs) {
+ if(nSize) {
+ care.resize(nSize);
+ } else {
+ care.resize(1);
+ }
+ }
+
+ void Save(unsigned i) {
+ TruthTable::Save(i);
+ if(savedcare.size() < i + 1) {
+ savedcare.resize(i + 1);
+ }
+ savedcare[i] = care;
+ }
+
+ void Load(unsigned i) {
+ TruthTable::Load(i);
+ care = savedcare[i];
+ }
+
+ void SaveIndices(unsigned i) {
+ TruthTable::SaveIndices(i);
+ if(vvMergedIndicesSaved.size() < i + 1) {
+ vvMergedIndicesSaved.resize(i + 1);
+ }
+ vvMergedIndicesSaved[i] = vvMergedIndices;
+ }
+
+ void LoadIndices(unsigned i) {
+ TruthTable::LoadIndices(i);
+ vvMergedIndices = vvMergedIndicesSaved[i];
+ }
+
+ void Swap(int lev) {
+ TruthTable::Swap(lev);
+ if(nInputs - lev - 1 > lww) {
+ int nScopeSize = 1 << (nInputs - lev - 2 - lww);
+ for(int i = nScopeSize; i < nSize; i += (nScopeSize << 2)) {
+ for(int j = 0; j < nScopeSize; j++) {
+ std::swap(care[i + j], care[i + nScopeSize + j]);
+ }
+ }
+ } else if(nInputs - lev - 1 == lww) {
+ for(int i = 0; i < nSize; i += 2) {
+ care[i+1] ^= care[i] >> (ww / 2);
+ care[i] ^= care[i+1] << (ww / 2);
+ care[i+1] ^= care[i] >> (ww / 2);
+ }
+ } else {
+ for(int i = 0; i < nSize || (i == 0 && !nSize); i++) {
+ int d = nInputs - lev - 2;
+ int shamt = 1 << d;
+ care[i] ^= (care[i] >> shamt) & swapmask[d];
+ care[i] ^= (care[i] & swapmask[d]) << shamt;
+ care[i] ^= (care[i] >> shamt) & swapmask[d];
+ }
+ }
+ }
+
+ void RestoreCare() {
+ caret.clear();
+ if(nSize) {
+ for(int i = 0; i < nOutputs; i++) {
+ caret.insert(caret.end(), care.begin(), care.end());
+ }
+ } else {
+ caret.resize(nTotalSize);
+ for(int i = 0; i < nOutputs; i++) {
+ int padding = i * (1 << nInputs);
+ caret[padding / ww] |= care[0] << (padding % ww);
+ }
+ }
+ }
+
+ word GetCare(int index_lev, int lev) {
+ assert(index_lev >= 0);
+ assert(nInputs - lev <= lww);
+ int logwidth = nInputs - lev;
+ int index = index_lev >> (lww - logwidth);
+ int pos = (index_lev % (1 << (lww - logwidth))) << logwidth;
+ return (caret[index] >> pos) & ones[logwidth];
+ }
+
+ void CopyFuncMasked(int index1, int index2, int lev, bool fCompl) {
+ assert(index1 >= 0);
+ assert(index2 >= 0);
+ int logwidth = nInputs - lev;
+ if(logwidth > lww) {
+ int nScopeSize = 1 << (logwidth - lww);
+ for(int i = 0; i < nScopeSize; i++) {
+ word value = t[nScopeSize * index2 + i];
+ if(fCompl) {
+ value = ~value;
+ }
+ word cvalue = caret[nScopeSize * index2 + i];
+ t[nScopeSize * index1 + i] &= ~cvalue;
+ t[nScopeSize * index1 + i] |= cvalue & value;
+ }
+ } else {
+ word one = ones[logwidth];
+ word value1 = GetValue(index1, lev);
+ word value2 = GetValue(index2, lev);
+ if(fCompl) {
+ value2 ^= one;
+ }
+ word cvalue = GetCare(index2, lev);
+ value1 &= cvalue ^ one;
+ value1 |= cvalue & value2;
+ SetValue(index1, lev, value1);
+ }
+ }
+
+ bool IsDC(int index, int lev) {
+ if(nInputs - lev > lww) {
+ int nScopeSize = 1 << (nInputs - lev - lww);
+ for(int i = 0; i < nScopeSize; i++) {
+ if(caret[nScopeSize * index + i]) {
+ return false;
+ }
+ }
+ } else if(GetCare(index, lev)) {
+ return false;
+ }
+ return true;
+ }
+
+ int Include(int index1, int index2, int lev, bool fCompl) {
+ assert(index1 >= 0);
+ assert(index2 >= 0);
+ int logwidth = nInputs - lev;
+ bool fEq = true;
+ if(logwidth > lww) {
+ int nScopeSize = 1 << (logwidth - lww);
+ for(int i = 0; i < nScopeSize && (fEq || fCompl); i++) {
+ word cvalue = caret[nScopeSize * index2 + i];
+ if(~caret[nScopeSize * index1 + i] & cvalue) {
+ return 0;
+ }
+ word value = t[nScopeSize * index1 + i] ^ t[nScopeSize * index2 + i];
+ fEq &= !(value & cvalue);
+ fCompl &= !(~value & cvalue);
+ }
+ } else {
+ word cvalue = GetCare(index2, lev);
+ if((GetCare(index1, lev) ^ ones[logwidth]) & cvalue) {
+ return 0;
+ }
+ word value = GetValue(index1, lev) ^ GetValue(index2, lev);
+ fEq &= !(value & cvalue);
+ fCompl &= !((value ^ ones[logwidth]) & cvalue);
+ }
+ return 2 * fCompl + fEq;
+ }
+
+ int Intersect(int index1, int index2, int lev, bool fCompl, bool fEq = true) {
+ assert(index1 >= 0);
+ assert(index2 >= 0);
+ int logwidth = nInputs - lev;
+ if(logwidth > lww) {
+ int nScopeSize = 1 << (logwidth - lww);
+ for(int i = 0; i < nScopeSize && (fEq || fCompl); i++) {
+ word value = t[nScopeSize * index1 + i] ^ t[nScopeSize * index2 + i];
+ word cvalue = caret[nScopeSize * index1 + i] & caret[nScopeSize * index2 + i];
+ fEq &= !(value & cvalue);
+ fCompl &= !(~value & cvalue);
+ }
+ } else {
+ word value = GetValue(index1, lev) ^ GetValue(index2, lev);
+ word cvalue = GetCare(index1, lev) & GetCare(index2, lev);
+ fEq &= !(value & cvalue);
+ fCompl &= !((value ^ ones[logwidth]) & cvalue);
+ }
+ return 2 * fCompl + fEq;
+ }
+
+ void MergeCare(int index1, int index2, int lev) {
+ assert(index1 >= 0);
+ assert(index2 >= 0);
+ int logwidth = nInputs - lev;
+ if(logwidth > lww) {
+ int nScopeSize = 1 << (logwidth - lww);
+ for(int i = 0; i < nScopeSize; i++) {
+ caret[nScopeSize * index1 + i] |= caret[nScopeSize * index2 + i];
+ }
+ } else {
+ word value = GetCare(index2, lev);
+ int index = index1 >> (lww - logwidth);
+ int pos = (index1 % (1 << (lww - logwidth))) << logwidth;
+ caret[index] |= value << pos;
+ }
+ }
+
+ void Merge(int index1, int index2, int lev, bool fCompl) {
+ MergeCare(index1, index2, lev);
+ vvMergedIndices[lev].push_back(std::make_pair((index1 << 1) ^ (int)fCompl, index2));
+ }
+
+ int BDDBuildOne(int index, int lev) {
+ int r = BDDFind(index, lev);
+ if(r >= -2) {
+ if(r >= 0) {
+ Merge(vvIndices[lev][r >> 1], index, lev, r & 1);
+ }
+ return r;
+ }
+ vvIndices[lev].push_back(index);
+ return (vvIndices[lev].size() - 1) << 1;
+ }
+
+ void CompleteMerge() {
+ for(int i = nInputs - 1; i >= 0; i--) {
+ for(std::vector<std::pair<int, int> >::reverse_iterator it = vvMergedIndices[i].rbegin(); it != vvMergedIndices[i].rend(); it++) {
+ CopyFunc((*it).second, (*it).first >> 1, i, (*it).first & 1);
+ }
+ }
+ }
+
+ void BDDBuildStartup() {
+ RestoreCare();
+ vvIndices.clear();
+ vvIndices.resize(nInputs);
+ vvRedundantIndices.clear();
+ vvRedundantIndices.resize(nInputs);
+ vvMergedIndices.clear();
+ vvMergedIndices.resize(nInputs);
+ for(int i = 0; i < nOutputs; i++) {
+ if(!IsDC(i, 0)) {
+ BDDBuildOne(i, 0);
+ }
+ }
+ }
+
+ virtual void BDDRebuildByMerge(int lev) {
+ for(unsigned i = 0; i < vvMergedIndices[lev].size(); i++) {
+ std::pair<int, int> &p = vvMergedIndices[lev][i];
+ MergeCare(p.first >> 1, p.second, lev);
+ }
+ }
+
+ int BDDRebuild(int lev) {
+ RestoreCare();
+ int i;
+ for(i = lev; i < nInputs; i++) {
+ vvIndices[i].clear();
+ vvMergedIndices[i].clear();
+ if(i) {
+ vvRedundantIndices[i-1].clear();
+ }
+ }
+ for(i = 0; i < lev; i++) {
+ BDDRebuildByMerge(i);
+ }
+ for(i = lev; i < nInputs; i++) {
+ if(!i) {
+ for(int j = 0; j < nOutputs; j++) {
+ if(!IsDC(j, 0)) {
+ BDDBuildOne(j, 0);
+ }
+ }
+ } else {
+ BDDBuildLevel(i);
+ }
+ }
+ return BDDNodeCount();
+ }
+
+ int BDDSwap(int lev) {
+ Swap(lev);
+ return BDDRebuild(lev);
+ }
+
+ void OptimizationStartup() {
+ originalt = t;
+ RestoreCare();
+ vvIndices.clear();
+ vvIndices.resize(nInputs);
+ vvMergedIndices.clear();
+ vvMergedIndices.resize(nInputs);
+ for(int i = 0; i < nOutputs; i++) {
+ if(!IsDC(i, 0)) {
+ BDDBuildOne(i, 0);
+ } else {
+ ShiftToMajority(i, 0);
+ }
+ }
+ }
+
+ virtual void Optimize() {
+ OptimizationStartup();
+ for(int i = 1; i < nInputs; i++) {
+ for(unsigned j = 0; j < vvIndices[i-1].size(); j++) {
+ int index = vvIndices[i-1][j];
+ BDDBuildOne(index << 1, i);
+ BDDBuildOne((index << 1) ^ 1, i);
+ }
+ }
+ CompleteMerge();
+ }
+};
+
+class TruthTableLevelTSM : public TruthTableCare {
+public:
+ TruthTableLevelTSM(int nInputs, int nOutputs): TruthTableCare(nInputs, nOutputs) {}
+
+ int BDDFindTSM(int index, int lev) {
+ int logwidth = nInputs - lev;
+ if(logwidth > lww) {
+ int nScopeSize = 1 << (logwidth - lww);
+ bool fZero = true;
+ bool fOne = true;
+ for(int i = 0; i < nScopeSize && (fZero || fOne); i++) {
+ word value = t[nScopeSize * index + i];
+ word cvalue = caret[nScopeSize * index + i];
+ fZero &= !(value & cvalue);
+ fOne &= !(~value & cvalue);
+ }
+ if(fZero || fOne) {
+ return -2 ^ (int)fOne;
+ }
+ for(unsigned j = 0; j < vvIndices[lev].size(); j++) {
+ int index2 = vvIndices[lev][j];
+ bool fEq = true;
+ bool fCompl = true;
+ for(int i = 0; i < nScopeSize && (fEq || fCompl); i++) {
+ word value = t[nScopeSize * index + i] ^ t[nScopeSize * index2 + i];
+ word cvalue = caret[nScopeSize * index + i] & caret[nScopeSize * index2 + i];
+ fEq &= !(value & cvalue);
+ fCompl &= !(~value & cvalue);
+ }
+ if(fEq || fCompl) {
+ return (index2 << 1) ^ (int)!fEq;
+ }
+ }
+ } else {
+ word one = ones[logwidth];
+ word value = GetValue(index, lev);
+ word cvalue = GetCare(index, lev);
+ if(!(value & cvalue)) {
+ return -2;
+ }
+ if(!((value ^ one) & cvalue)) {
+ return -1;
+ }
+ for(unsigned j = 0; j < vvIndices[lev].size(); j++) {
+ int index2 = vvIndices[lev][j];
+ word value2 = value ^ GetValue(index2, lev);
+ word cvalue2 = cvalue & GetCare(index2, lev);
+ if(!(value2 & cvalue2)) {
+ return index2 << 1;
+ }
+ if(!((value2 ^ one) & cvalue2)) {
+ return (index2 << 1) ^ 1;
+ }
+ }
+ }
+ return -3;
+ }
+
+ int BDDBuildOne(int index, int lev) {
+ int r = BDDFindTSM(index, lev);
+ if(r >= -2) {
+ if(r >= 0) {
+ CopyFuncMasked(r >> 1, index, lev, r & 1);
+ Merge(r >> 1, index, lev, r & 1);
+ } else {
+ vvMergedIndices[lev].push_back(std::make_pair(r, index));
+ }
+ return r;
+ }
+ vvIndices[lev].push_back(index);
+ return index << 1;
+ }
+
+ int BDDBuild() {
+ TruthTable::Save(3);
+ int r = TruthTable::BDDBuild();
+ TruthTable::Load(3);
+ return r;
+ }
+
+ void BDDRebuildByMerge(int lev) {
+ for(unsigned i = 0; i < vvMergedIndices[lev].size(); i++) {
+ std::pair<int, int> &p = vvMergedIndices[lev][i];
+ if(p.first >= 0) {
+ CopyFuncMasked(p.first >> 1, p.second, lev, p.first & 1);
+ MergeCare(p.first >> 1, p.second, lev);
+ }
+ }
+ }
+
+ int BDDRebuild(int lev) {
+ TruthTable::Save(3);
+ int r = TruthTableCare::BDDRebuild(lev);
+ TruthTable::Load(3);
+ return r;
+ }
+};
+
+}
+
+Gia_Man_t * Gia_ManTtopt( Gia_Man_t * p, int nIns, int nOuts, int nRounds )
+{
+ Gia_Man_t * pNew;
+ Gia_Obj_t * pObj;
+ Vec_Int_t * vSupp;
+ word v;
+ word * pTruth;
+ int i, g, k, nInputs;
+ Gia_ManLevelNum( p );
+ pNew = Gia_ManStart( Gia_ManObjNum(p) );
+ pNew->pName = Abc_UtilStrsav( p->pName );
+ pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+ Gia_ManForEachCi( p, pObj, k )
+ Gia_ManAppendCi( pNew );
+ Gia_ObjComputeTruthTableStart( p, nIns );
+ Gia_ManHashStart( pNew );
+ for ( g = 0; g < Gia_ManCoNum(p); g += nOuts )
+ {
+ vSupp = Gia_ManCollectSuppNew( p, g, nOuts );
+ nInputs = Vec_IntSize( vSupp );
+ Ttopt::TruthTableReo tt( nInputs, nOuts );
+ for ( k = 0; k < nOuts; k++ )
+ {
+ pObj = Gia_ManCo( p, g+k );
+ pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ObjFanin0(pObj), vSupp );
+ if ( nInputs >= 6 )
+ for ( i = 0; i < tt.nSize; i++ )
+ tt.t[i + tt.nSize * k] = Gia_ObjFaninC0(pObj)? ~pTruth[i]: pTruth[i];
+ else
+ {
+ i = k * (1 << nInputs);
+ v = (Gia_ObjFaninC0(pObj)? ~pTruth[0]: pTruth[0]) & tt.ones[nInputs];
+ tt.t[i / tt.ww] |= v << (i % tt.ww);
+ }
+ }
+ tt.RandomSiftReo( nRounds );
+ Ttopt::TruthTable tt2( nInputs, nOuts );
+ tt2.t = tt.t;
+ tt2.Reo( tt.vLevels );
+ tt2.BDDGenerateAig( pNew, vSupp );
+ Vec_IntFree( vSupp );
+ }
+ Gia_ObjComputeTruthTableStop( p );
+ Gia_ManHashStop( pNew );
+ Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+ return pNew;
+}
+
+Gia_Man_t * Gia_ManTtoptCare( Gia_Man_t * p, int nIns, int nOuts, int nRounds, char * pFileName, int nRarity )
+{
+ int fVerbose = 0;
+ Gia_Man_t * pNew;
+ Gia_Obj_t * pObj;
+ Vec_Int_t * vSupp;
+ word v;
+ word * pTruth, * pCare;
+ int i, g, k, nInputs;
+ Vec_Wrd_t * vSimI = Vec_WrdReadBin( pFileName, fVerbose );
+ Gia_ManLevelNum( p );
+ pNew = Gia_ManStart( Gia_ManObjNum(p) );
+ pNew->pName = Abc_UtilStrsav( p->pName );
+ pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+ Gia_ManForEachCi( p, pObj, k )
+ Gia_ManAppendCi( pNew );
+ Gia_ObjComputeTruthTableStart( p, nIns );
+ Gia_ManHashStart( pNew );
+ for ( g = 0; g < Gia_ManCoNum(p); g += nOuts )
+ {
+ vSupp = Gia_ManCollectSuppNew( p, g, nOuts );
+ nInputs = Vec_IntSize( vSupp );
+ Ttopt::TruthTableLevelTSM tt( nInputs, nOuts );
+ for ( k = 0; k < nOuts; k++ )
+ {
+ pObj = Gia_ManCo( p, g+k );
+ pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ObjFanin0(pObj), vSupp );
+ if ( nInputs >= 6 )
+ for ( i = 0; i < tt.nSize; i++ )
+ tt.t[i + tt.nSize * k] = Gia_ObjFaninC0(pObj)? ~pTruth[i]: pTruth[i];
+ else
+ {
+ i = k * (1 << nInputs);
+ v = (Gia_ObjFaninC0(pObj)? ~pTruth[0]: pTruth[0]) & tt.ones[nInputs];
+ tt.t[i / tt.ww] |= v << (i % tt.ww);
+ }
+ }
+ i = 1 << Vec_IntSize( vSupp );
+ pCare = Gia_ManCountFraction( p, vSimI, vSupp, nRarity, fVerbose, &i );
+ tt.care[0] = pCare[0];
+ for ( i = 1; i < tt.nSize; i++ )
+ tt.care[i] = pCare[i];
+ ABC_FREE( pCare );
+ tt.RandomSiftReo( nRounds );
+ tt.Optimize();
+ tt.BDDGenerateAig( pNew, vSupp );
+ Vec_IntFree( vSupp );
+ }
+ Gia_ObjComputeTruthTableStop( p );
+ Gia_ManHashStop( pNew );
+ Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+ Vec_WrdFreeP( &vSimI );
+ return pNew;
+}
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/aig/gia/giaUtil.c b/src/aig/gia/giaUtil.c
index d8130550..dfddc693 100644
--- a/src/aig/gia/giaUtil.c
+++ b/src/aig/gia/giaUtil.c
@@ -3130,6 +3130,37 @@ void Gia_ManWriteResub( Gia_Man_t * p, char * pFileName )
}
}
+
+/**Function*************************************************************
+
+ Synopsis [Transform flops.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Gia_ManPrintArray( Gia_Man_t * p )
+{
+ Gia_Obj_t * pObj; int i, nSize = Gia_ManObjNum(p);
+ printf( "static int s_ArraySize = %d;\n", nSize );
+ printf( "static int s_ArrayData[%d] = {\n", 2*nSize );
+ printf( " 0, 0," );
+ printf( "\n " );
+ Gia_ManForEachCi( p, pObj, i )
+ printf( "0, 0, " );
+ printf( "\n " );
+ Gia_ManForEachAnd( p, pObj, i )
+ printf( "%d, %d, ", Gia_ObjFaninLit0p(p, pObj), Gia_ObjFaninLit1p(p, pObj) );
+ printf( "\n " );
+ Gia_ManForEachCo( p, pObj, i )
+ printf( "%d, %d, ", Gia_ObjFaninLit0p(p, pObj), Gia_ObjFaninLit0p(p, pObj) );
+ printf( "\n" );
+ printf( "};\n" );
+
+}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/aig/gia/module.make b/src/aig/gia/module.make
index 171d8be3..870da208 100644
--- a/src/aig/gia/module.make
+++ b/src/aig/gia/module.make
@@ -77,6 +77,7 @@ SRC += src/aig/gia/giaAig.c \
src/aig/gia/giaSatLut.c \
src/aig/gia/giaSatMap.c \
src/aig/gia/giaSatoko.c \
+ src/aig/gia/giaSatSyn.c \
src/aig/gia/giaSat3.c \
src/aig/gia/giaScl.c \
src/aig/gia/giaScript.c \
@@ -104,5 +105,6 @@ SRC += src/aig/gia/giaAig.c \
src/aig/gia/giaTis.c \
src/aig/gia/giaTruth.c \
src/aig/gia/giaTsim.c \
+ src/aig/gia/giaTtopt.cpp \
src/aig/gia/giaUnate.c \
src/aig/gia/giaUtil.c
diff --git a/src/aig/miniaig/miniaig.h b/src/aig/miniaig/miniaig.h
index 0365b946..9aa41b11 100644
--- a/src/aig/miniaig/miniaig.h
+++ b/src/aig/miniaig/miniaig.h
@@ -144,6 +144,18 @@ static Mini_Aig_t * Mini_AigStart()
Mini_AigPush( p, MINI_AIG_NULL, MINI_AIG_NULL );
return p;
}
+static Mini_Aig_t * Mini_AigStartSupport( int nIns, int nObjsAlloc )
+{
+ Mini_Aig_t * p; int i;
+ assert( 1+nIns < nObjsAlloc );
+ p = MINI_AIG_CALLOC( Mini_Aig_t, 1 );
+ p->nCap = 2*nObjsAlloc;
+ p->nSize = 2*(1+nIns);
+ p->pArray = MINI_AIG_ALLOC( int, p->nCap );
+ for ( i = 0; i < p->nSize; i++ )
+ p->pArray[i] = MINI_AIG_NULL;
+ return p;
+}
static void Mini_AigStop( Mini_Aig_t * p )
{
MINI_AIG_FREE( p->pArray );
@@ -170,6 +182,31 @@ static int Mini_AigAndNum( Mini_Aig_t * p )
nNodes++;
return nNodes;
}
+static int Mini_AigXorNum( Mini_Aig_t * p )
+{
+ int i, nNodes = 0;
+ Mini_AigForEachAnd( p, i )
+ nNodes += p->pArray[2*i] > p->pArray[2*i+1];
+ return nNodes;
+}
+static int Mini_AigLevelNum( Mini_Aig_t * p )
+{
+ int i, Level = 0;
+ int * pLevels = MINI_AIG_CALLOC( int, Mini_AigNodeNum(p) );
+ Mini_AigForEachAnd( p, i )
+ {
+ int Lel0 = pLevels[Mini_AigLit2Var(Mini_AigNodeFanin0(p, i))];
+ int Lel1 = pLevels[Mini_AigLit2Var(Mini_AigNodeFanin1(p, i))];
+ pLevels[i] = 1 + (Lel0 > Lel1 ? Lel0 : Lel1);
+ }
+ Mini_AigForEachPo( p, i )
+ {
+ int Lel0 = pLevels[Mini_AigLit2Var(Mini_AigNodeFanin0(p, i))];
+ Level = Level > Lel0 ? Level : Lel0;
+ }
+ MINI_AIG_FREE( pLevels );
+ return Level;
+}
static void Mini_AigPrintStats( Mini_Aig_t * p )
{
printf( "MiniAIG stats: PI = %d PO = %d FF = %d AND = %d\n", Mini_AigPiNum(p), Mini_AigPoNum(p), Mini_AigRegNum(p), Mini_AigAndNum(p) );
@@ -648,6 +685,25 @@ int main( int argc, char ** argv )
}
*/
+/*
+#include "aig/miniaig/miniaig.h"
+
+// this procedure creates a MiniAIG for function F = a*b + ~c and writes it into a file "test.aig"
+void Mini_AigTest()
+{
+ Mini_Aig_t * p = Mini_AigStart(); // create empty AIG manager (contains only const0 node)
+ int litApos = Mini_AigCreatePi( p ); // create input A (returns pos lit of A)
+ int litBpos = Mini_AigCreatePi( p ); // create input B (returns pos lit of B)
+ int litCpos = Mini_AigCreatePi( p ); // create input C (returns pos lit of C)
+ int litCneg = Mini_AigLitNot( litCpos ); // neg lit of C
+ int litAnd = Mini_AigAnd( p, litApos, litBpos ); // lit for a*b
+ int litOr = Mini_AigOr( p, litAnd, litCneg ); // lit for a*b + ~c
+ Mini_AigCreatePo( p, litOr ); // create primary output
+ Mini_AigerWrite( "test.aig", p, 1 ); // write the result into a file
+ Mini_AigStop( p ); // deallocate MiniAIG
+}
+*/
+
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/aig/miniaig/ndr.h b/src/aig/miniaig/ndr.h
index 68c2779c..19373063 100644
--- a/src/aig/miniaig/ndr.h
+++ b/src/aig/miniaig/ndr.h
@@ -506,7 +506,7 @@ static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod
else if ( nArray == 3 && Type == ABC_OPER_ARI_ADD )
fprintf( pFile, "%s + %s + %s;\n", pNames[pArray[0]], pNames[pArray[1]], pNames[pArray[2]] );
else if ( Type == ABC_OPER_BIT_MUX )
- fprintf( pFile, "%s ? %s : %s;\n", pNames[pArray[0]], pNames[pArray[1]], pNames[pArray[2]] );
+ fprintf( pFile, "%s ? %s : %s;\n", pNames[pArray[0]], pNames[pArray[2]], pNames[pArray[1]] );
else
fprintf( pFile, "<cannot write operation %s>;\n", Abc_OperName(Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE)) );
}