summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--abcexe.dsp4
-rw-r--r--abclib.dsp12
-rw-r--r--src/aig/aig/aigDfs.c14
-rw-r--r--src/aig/aig/aigUtil.c29
-rw-r--r--src/aig/gia/gia.h6
-rw-r--r--src/aig/gia/giaDup.c19
-rw-r--r--src/aig/gia/giaEdge.c5
-rw-r--r--src/aig/gia/giaEquiv.c142
-rw-r--r--src/aig/gia/giaFx.c4
-rw-r--r--src/aig/gia/giaIf.c12
-rw-r--r--src/aig/gia/giaMan.c2
-rw-r--r--src/aig/gia/giaMf.c9
-rw-r--r--src/aig/gia/giaMfs.c4
-rw-r--r--src/aig/gia/giaSatLE.c251
-rw-r--r--src/aig/gia/giaShow.c16
-rw-r--r--src/aig/gia/giaStr.c17
-rw-r--r--src/aig/gia/giaSweep.c3
-rw-r--r--src/base/abc/abc.h8
-rw-r--r--src/base/abc/abcFunc.c16
-rw-r--r--src/base/abc/abcUtil.c20
-rw-r--r--src/base/abci/abc.c515
-rw-r--r--src/base/abci/abcDetect.c2
-rw-r--r--src/base/abci/abcDress3.c344
-rw-r--r--src/base/abci/abcExact.c1696
-rw-r--r--src/base/abci/abcFx.c199
-rw-r--r--src/base/abci/abcIf.c20
-rw-r--r--src/base/abci/abcMini.c2
-rw-r--r--src/base/abci/abcPrint.c8
-rw-r--r--src/base/abci/module.make2
-rw-r--r--src/base/io/ioReadBench.c2
-rw-r--r--src/base/io/ioReadPlaMo.c79
-rw-r--r--src/base/wlc/wlc.h2
-rw-r--r--src/base/wlc/wlcBlast.c114
-rw-r--r--src/base/wlc/wlcCom.c45
-rw-r--r--src/base/wlc/wlcReadSmt.c22
-rw-r--r--src/base/wlc/wlcReadVer.c4
-rw-r--r--src/base/wlc/wlcSim.c2
-rw-r--r--src/map/if/if.h3
-rw-r--r--src/map/if/ifCut.c2
-rw-r--r--src/map/if/ifMap.c65
-rw-r--r--src/opt/fxch/Fxch.c129
-rw-r--r--src/opt/fxch/Fxch.h73
-rw-r--r--src/opt/fxch/FxchDiv.c18
-rw-r--r--src/opt/fxch/FxchMan.c363
-rw-r--r--src/opt/fxch/FxchSCHashTable.c256
-rw-r--r--src/proof/acec/acec.h2
-rw-r--r--src/proof/acec/acecCover.c263
-rw-r--r--src/proof/acec/acecFadds.c54
-rw-r--r--src/proof/acec/acecOrder.c2
-rw-r--r--src/proof/acec/acecPolyn.c89
-rw-r--r--src/proof/acec/module.make1
-rw-r--r--src/proof/cec/cec.h1
-rw-r--r--src/proof/cec/cecCore.c10
-rw-r--r--src/proof/cec/cecInt.h2
-rw-r--r--src/proof/cec/cecSolve.c12
-rw-r--r--src/proof/ssw/sswConstr.c6
-rw-r--r--src/proof/ssw/sswSweep.c3
-rw-r--r--src/sat/bsat/satSolver.c2
58 files changed, 4385 insertions, 622 deletions
diff --git a/abcexe.dsp b/abcexe.dsp
index 9d5152fc..d2b2db3b 100644
--- a/abcexe.dsp
+++ b/abcexe.dsp
@@ -90,6 +90,10 @@ LINK32=link.exe
SOURCE=.\src\base\main\main.c
# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswSat.c
+# End Source File
# End Group
# Begin Group "Header Files"
diff --git a/abclib.dsp b/abclib.dsp
index 7129d0e8..7d1c1551 100644
--- a/abclib.dsp
+++ b/abclib.dsp
@@ -263,10 +263,18 @@ SOURCE=.\src\base\abci\abcDress2.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\abci\abcDress3.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\abci\abcDsd.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\abci\abcExact.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\abci\abcExtract.c
# End Source File
# Begin Source File
@@ -5347,6 +5355,10 @@ SOURCE=.\src\proof\acec\acecCore.c
# End Source File
# Begin Source File
+SOURCE=.\src\proof\acec\acecCover.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\proof\acec\acecFadds.c
# End Source File
# Begin Source File
diff --git a/src/aig/aig/aigDfs.c b/src/aig/aig/aigDfs.c
index 8afec81e..d560fc29 100644
--- a/src/aig/aig/aigDfs.c
+++ b/src/aig/aig/aigDfs.c
@@ -199,6 +199,20 @@ void Aig_ManDfsAll_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
Aig_ManDfsAll_rec( p, Aig_ObjFanin1(pObj), vNodes );
Vec_PtrPush( vNodes, pObj );
}
+Vec_Ptr_t * Aig_ManDfsArray( Aig_Man_t * p, Aig_Obj_t ** pNodes, int nNodes )
+{
+ Vec_Ptr_t * vNodes;
+ int i;
+ Aig_ManIncrementTravId( p );
+ vNodes = Vec_PtrAlloc( Aig_ManObjNumMax(p) );
+ // add constant
+ Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) );
+ Vec_PtrPush( vNodes, Aig_ManConst1(p) );
+ // collect nodes reachable in the DFS order
+ for ( i = 0; i < nNodes; i++ )
+ Aig_ManDfsAll_rec( p, pNodes[i], vNodes );
+ return vNodes;
+}
/**Function*************************************************************
diff --git a/src/aig/aig/aigUtil.c b/src/aig/aig/aigUtil.c
index 6637e1a4..767015c9 100644
--- a/src/aig/aig/aigUtil.c
+++ b/src/aig/aig/aigUtil.c
@@ -653,23 +653,36 @@ void Aig_ObjPrintVerilog( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, i
void Aig_ObjPrintVerbose( Aig_Obj_t * pObj, int fHaig )
{
assert( !Aig_IsComplement(pObj) );
- printf( "Node %p : ", pObj );
+ printf( "Node %d : ", pObj->Id );
if ( Aig_ObjIsConst1(pObj) )
printf( "constant 1" );
else if ( Aig_ObjIsCi(pObj) )
- printf( "PI" );
+ printf( "CI" );
else if ( Aig_ObjIsCo(pObj) )
{
- printf( "PO" );
- printf( "%p%s",
- Aig_ObjFanin0(pObj), (Aig_ObjFaninC0(pObj)? "\'" : " ") );
+ printf( "CO( " );
+ printf( "%d%s )",
+ Aig_ObjFanin0(pObj)->Id, (Aig_ObjFaninC0(pObj)? "\'" : " ") );
}
else
- printf( "AND( %p%s, %p%s )",
- Aig_ObjFanin0(pObj), (Aig_ObjFaninC0(pObj)? "\'" : " "),
- Aig_ObjFanin1(pObj), (Aig_ObjFaninC1(pObj)? "\'" : " ") );
+ printf( "AND( %d%s, %d%s )",
+ Aig_ObjFanin0(pObj)->Id, (Aig_ObjFaninC0(pObj)? "\'" : " "),
+ Aig_ObjFanin1(pObj)->Id, (Aig_ObjFaninC1(pObj)? "\'" : " ") );
printf( " (refs = %3d)", Aig_ObjRefs(pObj) );
}
+void Aig_ObjPrintVerboseCone( Aig_Man_t * p, Aig_Obj_t * pRoot, int fHaig )
+{
+ extern Vec_Ptr_t * Aig_ManDfsArray( Aig_Man_t * p, Aig_Obj_t ** pNodes, int nNodes );
+ Vec_Ptr_t * vNodes;
+ Aig_Obj_t * pObj;
+ int i;
+ vNodes = Aig_ManDfsArray( p, &pRoot, 1 );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ Aig_ObjPrintVerbose( pObj, fHaig ), printf( "\n" );
+ printf( "\n" );
+ Vec_PtrFree( vNodes );
+
+}
/**Function*************************************************************
diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h
index f2baf7e0..3d2d84ae 100644
--- a/src/aig/gia/gia.h
+++ b/src/aig/gia/gia.h
@@ -175,6 +175,8 @@ struct Gia_Man_t_
Vec_Int_t * vUserFfIds; // numbers assigned to FFs by the user
Vec_Int_t * vCiNumsOrig; // original CI names
Vec_Int_t * vCoNumsOrig; // original CO names
+ Vec_Int_t * vIdsOrig; // original object IDs
+ Vec_Int_t * vIdsEquiv; // original object IDs proved equivalent
Vec_Int_t * vCofVars; // cofactoring variables
Vec_Vec_t * vClockDoms; // clock domains
Vec_Flt_t * vTiming; // arrival/required/slack
@@ -1241,6 +1243,10 @@ extern void Gia_ManDetectSeqSignals( Gia_Man_t * p, int fSetReset
extern Gia_Man_t * Gia_ManUnrollAndCofactor( Gia_Man_t * p, int nFrames, int nFanMax, int fVerbose );
extern Gia_Man_t * Gia_ManRemoveEnables( Gia_Man_t * p );
/*=== giaEquiv.c ==========================================================*/
+extern void Gia_ManOrigIdsInit( Gia_Man_t * p );
+extern void Gia_ManOrigIdsStart( Gia_Man_t * p );
+extern void Gia_ManOrigIdsRemap( Gia_Man_t * p, Gia_Man_t * pNew );
+extern Gia_Man_t * Gia_ManOrigIdsReduce( Gia_Man_t * p, Vec_Int_t * vPairs );
extern void Gia_ManEquivFixOutputPairs( Gia_Man_t * p );
extern int Gia_ManCheckTopoOrder( Gia_Man_t * p );
extern int * Gia_ManDeriveNexts( Gia_Man_t * p );
diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c
index a2277294..7ced54a4 100644
--- a/src/aig/gia/giaDup.c
+++ b/src/aig/gia/giaDup.c
@@ -1383,7 +1383,7 @@ Gia_Man_t * Gia_ManDupDfs( Gia_Man_t * p )
Gia_ManForEachCo( p, pObj, i )
Gia_ManDupDfs_rec( pNew, p, Gia_ObjFanin0(pObj) );
Gia_ManForEachCo( p, pObj, i )
- Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+ pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
pNew->nConstrs = p->nConstrs;
if ( p->pCexSeq )
@@ -3825,7 +3825,7 @@ Vec_Int_t * Gia_ManCollectTopXors( Gia_Man_t * p )
Gia_ManSetMark0Dfs_rec( p, Gia_ObjId(p, pFan[fFlip]) );
Gia_ManSetMark1Dfs_rec( p, Gia_ObjId(p, pFan[!fFlip]) );
}
- printf( "Detected %d single-output XOR miters and %d other miters.\n", Vec_IntSize(vXors) - Count1, Count1 );
+ //printf( "Detected %d single-output XOR miters and %d other miters.\n", Vec_IntSize(vXors) - Count1, Count1 );
Vec_IntFree( vXors );
Gia_ManCleanMark01(p);
// create new order
@@ -3860,9 +3860,18 @@ Gia_Man_t * Gia_ManDemiterToDual( Gia_Man_t * p )
pObj->Value = Gia_ManAppendCi( pNew );
Gia_ManForEachObjVec( vNodes, p, pObj, i )
pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
- Gia_ManSetPhase( p );
- Gia_ManForEachObjVec( vOrder, p, pObj, i )
- Gia_ManAppendCo( pNew, Abc_LitNotCond(pObj->Value, pObj->fPhase) );
+ pObj = Gia_ManCo(p, 0);
+ if ( Gia_ObjFanin0(pObj) == Gia_ManConst0(p) )
+ {
+ Gia_ManAppendCo( pNew, 0 );
+ Gia_ManAppendCo( pNew, Gia_ObjFaninC0(pObj) );
+ }
+ else
+ {
+ Gia_ManSetPhase( p );
+ Gia_ManForEachObjVec( vOrder, p, pObj, i )
+ Gia_ManAppendCo( pNew, Abc_LitNotCond(pObj->Value, pObj->fPhase) );
+ }
Vec_IntFree( vNodes );
Vec_IntFree( vOrder );
return pNew;
diff --git a/src/aig/gia/giaEdge.c b/src/aig/gia/giaEdge.c
index 65d9d6ef..5ba8006f 100644
--- a/src/aig/gia/giaEdge.c
+++ b/src/aig/gia/giaEdge.c
@@ -175,13 +175,14 @@ int Gia_ObjCheckEdge( Gia_Man_t * p, int iObj, int iNext )
}
static inline int Gia_ObjEvalEdgeDelay( Gia_Man_t * p, int iObj, Vec_Int_t * vDelay )
{
+ int nEdgeDelay = 2;
int i, iFan, Delay, DelayMax = 0;
if ( Gia_ManHasMapping(p) && Gia_ObjIsLut(p, iObj) )
{
assert( Gia_ObjLutSize(p, iObj) <= 4 );
Gia_LutForEachFanin( p, iObj, iFan, i )
{
- Delay = Vec_IntEntry(vDelay, iFan) + (Gia_ObjHaveEdge(p, iObj, iFan) ? 2 : 10);
+ Delay = Vec_IntEntry(vDelay, iFan) + (Gia_ObjHaveEdge(p, iObj, iFan) ? nEdgeDelay : 10);
DelayMax = Abc_MaxInt( DelayMax, Delay );
}
}
@@ -190,7 +191,7 @@ static inline int Gia_ObjEvalEdgeDelay( Gia_Man_t * p, int iObj, Vec_Int_t * vDe
assert( Gia_ObjLutSize2(p, iObj) <= 4 );
Gia_LutForEachFanin2( p, iObj, iFan, i )
{
- Delay = Vec_IntEntry(vDelay, iFan) + (Gia_ObjHaveEdge(p, iObj, iFan) ? 2 : 10);
+ Delay = Vec_IntEntry(vDelay, iFan) + (Gia_ObjHaveEdge(p, iObj, iFan) ? nEdgeDelay : 10);
DelayMax = Abc_MaxInt( DelayMax, Delay );
}
}
diff --git a/src/aig/gia/giaEquiv.c b/src/aig/gia/giaEquiv.c
index d383ce41..584be4cd 100644
--- a/src/aig/gia/giaEquiv.c
+++ b/src/aig/gia/giaEquiv.c
@@ -34,6 +34,143 @@ ABC_NAMESPACE_IMPL_START
/**Function*************************************************************
+ Synopsis [Manipulating original IDs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Gia_ManOrigIdsInit( Gia_Man_t * p )
+{
+ Vec_IntFreeP( &p->vIdsOrig );
+ p->vIdsOrig = Vec_IntStartNatural( Gia_ManObjNum(p) );
+}
+void Gia_ManOrigIdsStart( Gia_Man_t * p )
+{
+ Vec_IntFreeP( &p->vIdsOrig );
+ p->vIdsOrig = Vec_IntStartFull( Gia_ManObjNum(p) );
+}
+void Gia_ManOrigIdsRemap( Gia_Man_t * p, Gia_Man_t * pNew )
+{
+ Gia_Obj_t * pObj; int i;
+ if ( p->vIdsOrig == NULL )
+ return;
+ Gia_ManOrigIdsStart( pNew );
+ Vec_IntWriteEntry( pNew->vIdsOrig, 0, 0 );
+ Gia_ManForEachObj1( p, pObj, i )
+ if ( ~pObj->Value && Abc_Lit2Var(pObj->Value) && Vec_IntEntry(p->vIdsOrig, i) != -1 && Vec_IntEntry(pNew->vIdsOrig, Abc_Lit2Var(pObj->Value)) == -1 )
+ Vec_IntWriteEntry( pNew->vIdsOrig, Abc_Lit2Var(pObj->Value), Vec_IntEntry(p->vIdsOrig, i) );
+ Gia_ManForEachObj( pNew, pObj, i )
+ assert( Vec_IntEntry(pNew->vIdsOrig, i) >= 0 );
+}
+// input is a set of equivalent node pairs in any order
+// output is the mapping of each node into the equiv node with the smallest ID
+void Gia_ManOrigIdsRemapPairsInsert( Vec_Int_t * vMap, int One, int Two )
+{
+ int Smo = One < Two ? One : Two;
+ int Big = One < Two ? Two : One;
+ assert( Smo != Big );
+ if ( Vec_IntEntry(vMap, Big) == -1 )
+ Vec_IntWriteEntry( vMap, Big, Smo );
+ else
+ Gia_ManOrigIdsRemapPairsInsert( vMap, Smo, Vec_IntEntry(vMap, Big) );
+}
+int Gia_ManOrigIdsRemapPairsExtract( Vec_Int_t * vMap, int One )
+{
+ if ( Vec_IntEntry(vMap, One) == -1 )
+ return One;
+ return Gia_ManOrigIdsRemapPairsExtract( vMap, Vec_IntEntry(vMap, One) );
+}
+Vec_Int_t * Gia_ManOrigIdsRemapPairs( Vec_Int_t * vEquivPairs, int nObjs )
+{
+ Vec_Int_t * vMapResult;
+ Vec_Int_t * vMap2Smaller;
+ int i, One, Two;
+ // map bigger into smaller one
+ vMap2Smaller = Vec_IntStartFull( nObjs );
+ Vec_IntForEachEntryDouble( vEquivPairs, One, Two, i )
+ Gia_ManOrigIdsRemapPairsInsert( vMap2Smaller, One, Two );
+ // collect results in the topo order
+ vMapResult = Vec_IntStartFull( nObjs );
+ Vec_IntForEachEntry( vMap2Smaller, One, i )
+ if ( One >= 0 )
+ Vec_IntWriteEntry( vMapResult, i, Gia_ManOrigIdsRemapPairsExtract(vMap2Smaller, One) );
+ Vec_IntFree( vMap2Smaller );
+ return vMapResult;
+}
+// remap the AIG using the equivalent pairs proved
+// returns the reduced AIG and the equivalence classes of the original AIG
+Gia_Man_t * Gia_ManOrigIdsReduce( Gia_Man_t * p, Vec_Int_t * vPairs )
+{
+ Gia_Man_t * pNew = NULL;
+ Gia_Obj_t * pObj, * pRepr; int i;
+ Vec_Int_t * vMap = Gia_ManOrigIdsRemapPairs( vPairs, Gia_ManObjNum(p) );
+ Gia_ManSetPhase( p );
+ pNew = Gia_ManStart( Gia_ManObjNum(p) );
+ pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+ pNew->pName = Abc_UtilStrsav( p->pName );
+ Gia_ManFillValue(p);
+ Gia_ManConst0(p)->Value = 0;
+ Gia_ManForEachCi( p, pObj, i )
+ pObj->Value = Gia_ManAppendCi(pNew);
+ Gia_ManHashAlloc( pNew );
+ Gia_ManForEachAnd( p, pObj, i )
+ {
+ if ( Vec_IntEntry(vMap, i) == -1 )
+ pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+ else
+ {
+ pRepr = Gia_ManObj( p, Vec_IntEntry(vMap, i) );
+ pObj->Value = Abc_LitNotCond( pRepr->Value, pRepr->fPhase ^ pObj->fPhase );
+ }
+ }
+ Gia_ManHashStop( pNew );
+ Gia_ManForEachCo( p, pObj, i )
+ Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+ Vec_IntFree( vMap );
+ // compute equivalences
+ assert( !p->pReprs && !p->pNexts );
+ p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) );
+ for ( i = 0; i < Gia_ManObjNum(p); i++ )
+ Gia_ObjSetRepr( p, i, GIA_VOID );
+ Gia_ManFillValue(pNew);
+ Gia_ManForEachAnd( p, pObj, i )
+ {
+ int iRepr = Abc_Lit2Var(pObj->Value);
+ if ( iRepr == 0 )
+ {
+ Gia_ObjSetRepr( p, i, 0 );
+ continue;
+ }
+ pRepr = Gia_ManObj( pNew, iRepr );
+ if ( !~pRepr->Value ) // first time
+ {
+ pRepr->Value = i;
+ continue;
+ }
+ // add equivalence
+ Gia_ObjSetRepr( p, i, pRepr->Value );
+ }
+ p->pNexts = Gia_ManDeriveNexts( p );
+ return pNew;
+}
+Gia_Man_t * Gia_ManOrigIdsReduceTest( Gia_Man_t * p, Vec_Int_t * vPairs )
+{
+ Gia_Man_t * pTemp, * pNew = Gia_ManOrigIdsReduce( p, vPairs );
+ Gia_ManPrintStats( p, NULL );
+ Gia_ManPrintStats( pNew, NULL );
+ //Gia_ManStop( pNew );
+ // cleanup the resulting one
+ pNew = Gia_ManCleanup( pTemp = pNew );
+ Gia_ManStop( pTemp );
+ return pNew;
+}
+
+/**Function*************************************************************
+
Synopsis [Returns 1 if AIG is not in the required topo order.]
Description []
@@ -460,7 +597,7 @@ Gia_Man_t * Gia_ManEquivReduce( Gia_Man_t * p, int fUseAll, int fDualOut, int fS
Gia_ManForEachCo( p, pObj, i )
Gia_ManEquivReduce_rec( pNew, p, Gia_ObjFanin0(pObj), fUseAll, fDualOut );
Gia_ManForEachCo( p, pObj, i )
- Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+ pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
Gia_ManHashStop( pNew );
Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
return pNew;
@@ -641,6 +778,7 @@ Gia_Man_t * Gia_ManEquivReduceAndRemap( Gia_Man_t * p, int fSeq, int fMiterPairs
pNew = Gia_ManEquivReduce( p, 0, 0, 0, 0 );
if ( pNew == NULL )
return NULL;
+ Gia_ManOrigIdsRemap( p, pNew );
if ( fMiterPairs )
Gia_ManEquivFixOutputPairs( pNew );
if ( fSeq )
@@ -649,9 +787,11 @@ Gia_Man_t * Gia_ManEquivReduceAndRemap( Gia_Man_t * p, int fSeq, int fMiterPairs
Gia_ManCombMarkUsed( pNew );
Gia_ManEquivUpdatePointers( p, pNew );
pFinal = Gia_ManDupMarked( pNew );
+ Gia_ManOrigIdsRemap( pNew, pFinal );
Gia_ManEquivDeriveReprs( p, pNew, pFinal );
Gia_ManStop( pNew );
pFinal = Gia_ManEquivRemapDfs( pNew = pFinal );
+ Gia_ManOrigIdsRemap( pNew, pFinal );
Gia_ManStop( pNew );
return pFinal;
}
diff --git a/src/aig/gia/giaFx.c b/src/aig/gia/giaFx.c
index 4fff177c..c6eae6c7 100644
--- a/src/aig/gia/giaFx.c
+++ b/src/aig/gia/giaFx.c
@@ -455,7 +455,7 @@ Gia_Man_t * Gia_ManFxInsert( Gia_Man_t * p, Vec_Wec_t * vCubes, Vec_Str_t * vCom
***********************************************************************/
Gia_Man_t * Gia_ManPerformFx( Gia_Man_t * p, int nNewNodesMax, int LitCountMax, int fReverse, int fVerbose, int fVeryVerbose )
{
- extern int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitCountMax, int fVerbose, int fVeryVerbose );
+ extern int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitCountMax, int fCanonDivs, int fVerbose, int fVeryVerbose );
Gia_Man_t * pNew = NULL;
Vec_Wec_t * vCubes;
Vec_Str_t * vCompl;
@@ -467,7 +467,7 @@ Gia_Man_t * Gia_ManPerformFx( Gia_Man_t * p, int nNewNodesMax, int LitCountMax,
vCubes = Gia_ManFxRetrieve( p, &vCompl, fReverse );
// call the fast extract procedure
// clk = Abc_Clock();
- Fx_FastExtract( vCubes, Vec_StrSize(vCompl), nNewNodesMax, LitCountMax, fVerbose, fVeryVerbose );
+ Fx_FastExtract( vCubes, Vec_StrSize(vCompl), nNewNodesMax, LitCountMax, 0, fVerbose, fVeryVerbose );
// Abc_PrintTime( 1, "Fx runtime", Abc_Clock() - clk );
// insert information
pNew = Gia_ManFxInsert( p, vCubes, vCompl );
diff --git a/src/aig/gia/giaIf.c b/src/aig/gia/giaIf.c
index 9a72f576..26f549d0 100644
--- a/src/aig/gia/giaIf.c
+++ b/src/aig/gia/giaIf.c
@@ -926,7 +926,7 @@ Gia_Man_t * Gia_ManFromIfAig( If_Man_t * pIfMan )
Vec_Int_t * vAig;
int i, k;
assert( pIfMan->pPars->pLutStruct == NULL );
- assert( pIfMan->pPars->fDelayOpt || pIfMan->pPars->fDsdBalance || pIfMan->pPars->fUserRecLib );
+ assert( pIfMan->pPars->fDelayOpt || pIfMan->pPars->fDsdBalance || pIfMan->pPars->fUserRecLib || pIfMan->pPars->fUserSesLib );
// create new manager
pNew = Gia_ManStart( If_ManObjNum(pIfMan) );
Gia_ManHashAlloc( pNew );
@@ -1783,8 +1783,8 @@ Gia_Man_t * Gia_ManFromIfLogic( If_Man_t * pIfMan )
pCutBest = If_ObjCutBest( pIfObj );
// perform sorting of cut leaves by delay, so that the slowest pin drives the fastest input of the LUT
if ( !pIfMan->pPars->fUseTtPerm && !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance &&
- !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->nGateSize && !pIfMan->pPars->fEnableCheck75 &&
- !pIfMan->pPars->fEnableCheck75u && !pIfMan->pPars->fEnableCheck07 && !pIfMan->pPars->fUseDsdTune &&
+ !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 )
If_CutRotatePins( pIfMan, pCutBest );
// collect leaves of the best cut
@@ -2117,7 +2117,7 @@ Gia_Man_t * Gia_ManPerformMappingInt( Gia_Man_t * p, If_Par_t * pPars )
ABC_FREE( p->pCellStr );
Vec_IntFreeP( &p->vConfigs );
// disable cut minimization when GIA strucure is needed
- if ( !pPars->fDelayOpt && !pPars->fDelayOptLut && !pPars->fDsdBalance && !pPars->fUserRecLib && !pPars->fDeriveLuts && !pPars->fUseDsd && !pPars->fUseTtPerm )
+ if ( !pPars->fDelayOpt && !pPars->fDelayOptLut && !pPars->fDsdBalance && !pPars->fUserRecLib && !pPars->fUserSesLib && !pPars->fDeriveLuts && !pPars->fUseDsd && !pPars->fUseTtPerm )
pPars->fCutMin = 0;
// translate into the mapper
pIfMan = Gia_ManToIf( p, pPars );
@@ -2142,7 +2142,7 @@ Gia_Man_t * Gia_ManPerformMappingInt( Gia_Man_t * p, If_Par_t * pPars )
Abc_Print( 0, "Switching activity computation for designs with boxes is disabled.\n" );
}
if ( p->pManTime )
- pIfMan->pManTim = Tim_ManDup( (Tim_Man_t *)p->pManTime, pPars->fDelayOpt || pPars->fDelayOptLut || pPars->fDsdBalance || pPars->fUserRecLib );
+ pIfMan->pManTim = Tim_ManDup( (Tim_Man_t *)p->pManTime, pPars->fDelayOpt || pPars->fDelayOptLut || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib );
// Tim_ManPrint( pIfMan->pManTim );
if ( !If_ManPerformMapping( pIfMan ) )
{
@@ -2150,7 +2150,7 @@ Gia_Man_t * Gia_ManPerformMappingInt( Gia_Man_t * p, If_Par_t * pPars )
return NULL;
}
// transform the result of mapping into the new network
- if ( pIfMan->pPars->fDelayOpt || pIfMan->pPars->fDsdBalance || pIfMan->pPars->fUserRecLib )
+ if ( pIfMan->pPars->fDelayOpt || pIfMan->pPars->fDsdBalance || pIfMan->pPars->fUserRecLib || pIfMan->pPars->fUserSesLib )
pNew = Gia_ManFromIfAig( pIfMan );
else
pNew = Gia_ManFromIfLogic( pIfMan );
diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c
index d9e878a7..9ccab495 100644
--- a/src/aig/gia/giaMan.c
+++ b/src/aig/gia/giaMan.c
@@ -93,6 +93,8 @@ void Gia_ManStop( Gia_Man_t * p )
Vec_FltFreeP( &p->vTiming );
Vec_VecFreeP( &p->vClockDoms );
Vec_IntFreeP( &p->vCofVars );
+ Vec_IntFreeP( &p->vIdsOrig );
+ Vec_IntFreeP( &p->vIdsEquiv );
Vec_IntFreeP( &p->vLutConfigs );
Vec_IntFreeP( &p->vEdgeDelay );
Vec_IntFreeP( &p->vEdgeDelayR );
diff --git a/src/aig/gia/giaMf.c b/src/aig/gia/giaMf.c
index 086da95b..591f5bc5 100644
--- a/src/aig/gia/giaMf.c
+++ b/src/aig/gia/giaMf.c
@@ -247,6 +247,14 @@ void Mf_ManProfileTruths( Mf_Man_t * p )
SeeAlso []
***********************************************************************/
+static inline void Mf_CutPrintOne( int * pCut )
+{
+ int i;
+ printf( "%d {", Mf_CutSize(pCut) );
+ for ( i = 1; i <= Mf_CutSize(pCut); i++ )
+ printf( " %d", pCut[i] );
+ printf( " }\n" );
+}
static inline int Mf_CubeLit( int Cube, int iVar ) { return (Cube >> (iVar << 1)) & 3; }
static inline int Mf_ManCountLits( int * pCnf, int nCubes, int nVars )
{
@@ -287,6 +295,7 @@ Vec_Int_t * Mf_ManDeriveCnfs( Mf_Man_t * p, int * pnVars, int * pnClas, int * pn
if ( !Mf_ObjMapRefNum(p, i) )
continue;
pCut = Mf_ObjCutBest( p, i );
+ //Mf_CutPrintOne( pCut );
iFunc = Abc_Lit2Var( Mf_CutFunc(pCut) );
if ( Vec_IntEntry(vCnfs, iFunc) == -1 )
{
diff --git a/src/aig/gia/giaMfs.c b/src/aig/gia/giaMfs.c
index e5dfb788..c39e102d 100644
--- a/src/aig/gia/giaMfs.c
+++ b/src/aig/gia/giaMfs.c
@@ -67,7 +67,7 @@ Sfm_Ntk_t * Gia_ManExtractMfs( Gia_Man_t * p )
int i, j, k, curCi, curCo, nBoxIns, nBoxOuts;
int Id, iFan, nMfsVars, nBbIns = 0, nBbOuts = 0, Counter = 0;
assert( !p->pAigExtra || Gia_ManPiNum(p->pAigExtra) <= 6 );
- Tim_ManBlackBoxIoNum( pManTime, &nBbIns, &nBbOuts );
+ if ( pManTime ) Tim_ManBlackBoxIoNum( pManTime, &nBbIns, &nBbOuts );
// skip PIs due to box outputs
Counter += nBbOuts;
// prepare storage
@@ -252,7 +252,7 @@ Gia_Man_t * Gia_ManInsertMfs( Gia_Man_t * p, Sfm_Ntk_t * pNtk )
Vec_Int_t * vArray, * vLeaves;
Vec_Int_t * vMapping, * vMapping2;
int nBbIns = 0, nBbOuts = 0;
- Tim_ManBlackBoxIoNum( pManTime, &nBbIns, &nBbOuts );
+ if ( pManTime ) Tim_ManBlackBoxIoNum( pManTime, &nBbIns, &nBbOuts );
nMfsNodes = 1 + Gia_ManCiNum(p) + Gia_ManLutNum(p) + Gia_ManCoNum(p) + nBbIns + nBbOuts;
vMfs2Gia = Vec_IntStartFull( nMfsNodes );
vGroupMap = Vec_IntStartFull( nMfsNodes );
diff --git a/src/aig/gia/giaSatLE.c b/src/aig/gia/giaSatLE.c
index 549ec4fb..d541804a 100644
--- a/src/aig/gia/giaSatLE.c
+++ b/src/aig/gia/giaSatLE.c
@@ -31,8 +31,8 @@ ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
static inline int Sle_CutSize( int * pCut ) { return pCut[0] & 0xF; } // 4 bits
-static inline int Sle_CutSign( int * pCut ) { return pCut[0] >> 4; } // 28 bits
-static inline int Sle_CutSetSizeSign( int s, int S ) { return (S << 28) | s; }
+static inline int Sle_CutSign( int * pCut ) { return ((unsigned)pCut[0]) >> 4; } // 28 bits
+static inline int Sle_CutSetSizeSign( int s, int S ) { return (S << 4) | s; }
static inline int * Sle_CutLeaves( int * pCut ) { return pCut + 1; }
static inline int Sle_CutIsUsed( int * pCut ) { return pCut[1] != 0; }
@@ -197,7 +197,7 @@ int Sle_ManCutMerge( Gia_Man_t * p, int iObj, Vec_Int_t * vCuts, Vec_Int_t * vTe
nCuts++;
}
// add unit cut
- Vec_IntPush( vCuts, Sle_CutSetSizeSign(1, iObj % 28) );
+ Vec_IntPush( vCuts, Sle_CutSetSizeSign(1, 1<<(iObj % 28)) );
Vec_IntPush( vCuts, iObj );
Vec_IntWriteEntry( vCuts, Vec_IntEntry(vCuts, iObj), nCuts );
return nCuts;
@@ -213,7 +213,7 @@ Vec_Int_t * Sle_ManComputeCuts( Gia_Man_t * p, int nLutSize, int fVerbose )
{
Vec_IntWriteEntry( vCuts, iObj, Vec_IntSize(vCuts) );
Vec_IntPush( vCuts, 0 );
- Vec_IntPush( vCuts, Sle_CutSetSizeSign(1, iObj % 28) );
+ Vec_IntPush( vCuts, Sle_CutSetSizeSign(1, 1<<(iObj % 28)) );
Vec_IntPush( vCuts, iObj );
}
Gia_ManForEachAndId( p, iObj )
@@ -226,6 +226,64 @@ Vec_Int_t * Sle_ManComputeCuts( Gia_Man_t * p, int nLutSize, int fVerbose )
Vec_IntFree( vTemp );
return vCuts;
}
+
+/**Function*************************************************************
+
+ Synopsis [Cut delay computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Sle_ManComputeDelayCut( Gia_Man_t * p, int * pCut, Vec_Int_t * vTime )
+{
+ int nSize = Sle_CutSize(pCut);
+ int k, * pC = Sle_CutLeaves(pCut);
+ int DelayMax = 0;
+ for ( k = 0; k < nSize; k++ )
+ DelayMax = Abc_MaxInt( DelayMax, Vec_IntEntry(vTime, pC[k]) );
+ return DelayMax + 1;
+}
+int Sle_ManComputeDelayOne( Gia_Man_t * p, int iObj, Vec_Int_t * vCuts, Vec_Int_t * vTime )
+{
+ int i, * pCut, Delay, DelayMin = ABC_INFINITY;
+ int * pList = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, iObj) );
+ Sle_ForEachCut( pList, pCut, i )
+ {
+ Delay = Sle_ManComputeDelayCut( p, pCut, vTime );
+ DelayMin = Abc_MinInt( DelayMin, Delay );
+ }
+ Vec_IntWriteEntry( vTime, iObj, DelayMin );
+ return DelayMin;
+}
+int Sle_ManComputeDelay( Gia_Man_t * p, Vec_Int_t * vCuts )
+{
+ int iObj, Delay, DelayMax = 0;
+ Vec_Int_t * vTime = Vec_IntStart( Gia_ManObjNum(p) );
+ Gia_ManForEachAndId( p, iObj )
+ {
+ Delay = Sle_ManComputeDelayOne( p, iObj, vCuts, vTime );
+ DelayMax = Abc_MaxInt( DelayMax, Delay );
+ }
+ Vec_IntFree( vTime );
+ //printf( "Delay = %d.\n", DelayMax );
+ return DelayMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cut printing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
void Sle_ManPrintCut( int * pCut )
{
int nSize = Sle_CutSize(pCut);
@@ -347,6 +405,7 @@ struct Sle_Man_t_
Gia_Man_t * pGia; // user's manager (with mapping and edges)
int nLevels; // total number of levels
int fVerbose; // verbose flag
+ int nSatCalls; // the number of SAT calls
// SAT variables
int nNodeVars; // node variables (Gia_ManAndNum(pGia))
int nCutVars; // cut variables (total number of non-trivial cuts)
@@ -405,6 +464,7 @@ Sle_Man_t * Sle_ManAlloc( Gia_Man_t * pGia, int nLevels, int fVerbose )
p->vDelayFirst = Vec_IntStartFull( Gia_ManObjNum(pGia) );
p->vPolars = Vec_IntAlloc( 100 );
p->vLits = Vec_IntAlloc( 100 );
+ p->nLevels = Sle_ManComputeDelay( pGia, p->vCuts );
return p;
}
void Sle_ManStop( Sle_Man_t * p )
@@ -462,8 +522,6 @@ void Sle_ManMarkupVariables( Sle_Man_t * p )
}
p->nDelayVars = Counter - p->nEdgeVars - p->nCutVars - p->nNodeVars;
p->nVarsTotal = Counter;
- printf( "Vars: Total = %d. Node = %d. Cut = %d. Edge = %d. Delay = %d.\n",
- p->nVarsTotal, p->nNodeVars, p->nCutVars, p->nEdgeVars, p->nDelayVars );
}
@@ -478,10 +536,25 @@ void Sle_ManMarkupVariables( Sle_Man_t * p )
SeeAlso []
***********************************************************************/
+// returns 1 if Cut can represent LUT (Cut is equal or is contained in LUT)
+static inline int Sle_ManCheckContained( int * pCutLeaves, int nCutLeaves, int * pLutFanins, int nLutFanins )
+{
+ int i, k;
+ if ( nCutLeaves > nLutFanins )
+ return 0;
+ for ( i = 0; i < nCutLeaves; i++ )
+ {
+ for ( k = 0; k < nLutFanins; k++ )
+ if ( pCutLeaves[i] == pLutFanins[k] )
+ break;
+ if ( k == nLutFanins ) // not found
+ return 0;
+ }
+ return 1;
+}
void Sle_ManDeriveInit( Sle_Man_t * p )
{
Vec_Int_t * vEdges;
- int pFaninsCopy[16];
int i, iObj, iFanin, iEdge;
if ( !Gia_ManHasMapping(p->pGia) )
return;
@@ -495,13 +568,10 @@ void Sle_ManDeriveInit( Sle_Man_t * p )
Vec_IntPush( p->vPolars, iObj ); // node var
nFanins = Gia_ObjLutSize( p->pGia, iObj );
pFanins = Gia_ObjLutFanins( p->pGia, iObj );
- // duplicate and sort fanins
- memcpy( pFaninsCopy, pFanins, sizeof(int)*nFanins );
- Vec_IntSelectSort( pFaninsCopy, nFanins );
// find cut
pList = Sle_ManList( p, iObj );
Sle_ForEachCut( pList, pCut, i )
- if ( nFanins == Sle_CutSize(pCut) && !memcmp(pFaninsCopy, Sle_CutLeaves(pCut), sizeof(int)*Sle_CutSize(pCut)) )
+ if ( Sle_ManCheckContained( Sle_CutLeaves(pCut), Sle_CutSize(pCut), pFanins, nFanins ) )
{
iFound = i;
break;
@@ -510,7 +580,7 @@ void Sle_ManDeriveInit( Sle_Man_t * p )
{
printf( "Cannot find the following cut at node %d: {", iObj );
for ( i = 0; i < nFanins; i++ )
- printf( " %d", pFaninsCopy[i] );
+ printf( " %d", pFanins[i] );
printf( " }\n" );
Sle_ManPrintCuts( p->pGia, p->vCuts, iObj );
fflush( stdout );
@@ -535,6 +605,8 @@ void Sle_ManDeriveInit( Sle_Man_t * p )
assert( Gia_ObjIsAnd(Gia_ManObj(p->pGia, iObj)) );
// find edge
iEdge = Vec_IntFind( Vec_WecEntry(p->vCutFanins, iObj), iFanin );
+ if ( iEdge < 0 )
+ continue;
assert( iEdge >= 0 );
Vec_IntPush( p->vPolars, Vec_IntEntry(p->vEdgeFirst, iObj) + iEdge ); // edge
}
@@ -552,9 +624,8 @@ void Sle_ManDeriveInit( Sle_Man_t * p )
SeeAlso []
***********************************************************************/
-void Sle_ManDeriveCnf( Sle_Man_t * p )
+void Sle_ManDeriveCnf( Sle_Man_t * p, int nBTLimit, int fDynamic )
{
- int nBTLimit = 0;
int nTimeOut = 0;
int i, iObj, value;
Vec_Int_t * vArray;
@@ -592,7 +663,15 @@ void Sle_ManDeriveCnf( Sle_Man_t * p )
Vec_IntPush( p->vLits, Abc_Var2Lit(iCutVar0 + i, 0) );
value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) );
assert( value );
- // cut required fanin nodes
+ // cuts are mutually exclusive
+ for ( i = 0; i < Sle_ListCutNum(pList); i++ )
+ for ( e = i+1; e < Sle_ListCutNum(pList); e++ )
+ {
+ Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(iCutVar0 + i, 1), Abc_Var2Lit(iCutVar0 + e, 1) );
+ value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) );
+ assert( value );
+ }
+ // cut requires fanin nodes
Vec_WecInit( p->vEdgeCuts, Vec_IntSize(vCutFans) );
Sle_ForEachCut( pList, pCut, i )
{
@@ -609,11 +688,17 @@ void Sle_ManDeriveCnf( Sle_Man_t * p )
// find the edge ID between pC[k] and iObj
iEdge = Vec_IntEntry(p->vObjMap, pC[k]);
if ( iEdge == -1 )
+ {
Vec_IntWriteEntry( p->vObjMap, pC[k], (iEdge = nEdges++) );
+ Vec_WecPush( p->vFanoutEdges, pC[k], iEdgeVar0 + iEdge );
+ }
Vec_WecPush( p->vEdgeCuts, iEdge, iCutVar0 + i );
- Vec_WecPush( p->vFanoutEdges, pC[k], iEdgeVar0 + iEdge );
p->nCutClas++;
}
+ // cut requires the node
+ Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(iCutVar0 + i, 1), Abc_Var2Lit(iObj, 0) );
+ value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) );
+ assert( value );
}
assert( nEdges == Vec_IntSize(vCutFans) );
@@ -644,6 +729,8 @@ void Sle_ManDeriveCnf( Sle_Man_t * p )
for ( i = 0; i < Vec_IntSize(vCutFans); i++ )
Vec_IntPush( vArray, iEdgeVar0 + i );
// generate pairs
+ if ( fDynamic )
+ continue;
Vec_IntForEachEntry( vArray, EdgeJ, j )
Vec_IntForEachEntryStart( vArray, EdgeK, k, j+1 )
{
@@ -667,6 +754,7 @@ void Sle_ManDeriveCnf( Sle_Man_t * p )
if ( Sle_ManCutHasPisOnly(pCut, p->vMask) )
{
Vec_IntFill( p->vLits, 1, Abc_Var2Lit(iDelayVar0, 0) ); // pos lit
+// Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(iObj, 1), Abc_Var2Lit(iDelayVar0, 0) );
value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) );
assert( value );
break;
@@ -680,6 +768,7 @@ void Sle_ManDeriveCnf( Sle_Man_t * p )
for ( d = 0; d < p->nLevels; d++ )
{
Vec_IntClear( p->vLits );
+ Vec_IntPush( p->vLits, Abc_Var2Lit(iObj, 1) );
Vec_IntPush( p->vLits, Abc_Var2Lit(iFanin, 1) );
Vec_IntPush( p->vLits, Abc_Var2Lit(iDelayVarIn + d, 1) );
Vec_IntPush( p->vLits, Abc_Var2Lit(iEdgeVar0 + e, 0) );
@@ -689,6 +778,7 @@ void Sle_ManDeriveCnf( Sle_Man_t * p )
assert( value );
Vec_IntClear( p->vLits );
+ Vec_IntPush( p->vLits, Abc_Var2Lit(iObj, 1) );
Vec_IntPush( p->vLits, Abc_Var2Lit(iFanin, 1) );
Vec_IntPush( p->vLits, Abc_Var2Lit(iDelayVarIn + d, 1) );
if ( d < p->nLevels-1 )
@@ -700,8 +790,68 @@ void Sle_ManDeriveCnf( Sle_Man_t * p )
p->nDelayClas += 2*p->nLevels;
}
}
- printf( "Clas: Total = %d. Cut = %d. Edge = %d. EdgeEx = %d. Delay = %d.\n",
- sat_solver_nclauses(p->pSat), p->nCutClas, p->nEdgeClas, p->nEdgeClas2, p->nDelayClas );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Add edge compatibility constraints.]
+
+ Description [Returns 1 if constraints have been added.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Sle_ManAddEdgeConstraints( Sle_Man_t * p, int nEdges )
+{
+ Vec_Int_t * vArray;
+ Vec_Int_t * vTemp = Vec_IntAlloc( 100 );
+ int value, iObj, nAdded = 0;
+ assert( nEdges == 1 || nEdges == 2 );
+ Vec_WecForEachLevel( p->vFanoutEdges, vArray, iObj )
+ {
+ int j, k, EdgeJ, EdgeK;
+ // check if they are incompatible
+ Vec_IntClear( vTemp );
+ Vec_IntForEachEntry( vArray, EdgeJ, j )
+ if ( sat_solver_var_value(p->pSat, EdgeJ) )
+ Vec_IntPush( vTemp, EdgeJ );
+ if ( Vec_IntSize(vTemp) <= nEdges )
+ continue;
+ nAdded++;
+ if ( nEdges == 1 )
+ {
+ // generate pairs
+ Vec_IntForEachEntry( vTemp, EdgeJ, j )
+ Vec_IntForEachEntryStart( vTemp, EdgeK, k, j+1 )
+ {
+ Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(EdgeJ, 1), Abc_Var2Lit(EdgeK, 1) );
+ value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) );
+ assert( value );
+ }
+ p->nEdgeClas2 += Vec_IntSize(vTemp) * (Vec_IntSize(vTemp) - 1) / 2;
+ }
+ else if ( nEdges == 2 )
+ {
+ int m, EdgeM;
+ // generate triples
+ Vec_IntForEachEntry( vTemp, EdgeJ, j )
+ Vec_IntForEachEntryStart( vTemp, EdgeK, k, j+1 )
+ Vec_IntForEachEntryStart( vTemp, EdgeM, m, k+1 )
+ {
+ Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(EdgeJ, 1), Abc_Var2Lit(EdgeK, 1) );
+ Vec_IntPush( p->vLits, Abc_Var2Lit(EdgeM, 1) );
+ value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) );
+ assert( value );
+ }
+ p->nEdgeClas2 += Vec_IntSize(vTemp) * (Vec_IntSize(vTemp) - 1) * (Vec_IntSize(vTemp) - 2) / 6;
+ }
+ else assert( 0 );
+ }
+ Vec_IntFree( vTemp );
+ //printf( "Added clauses to %d nodes.\n", nAdded );
+ return nAdded;
}
/**Function*************************************************************
@@ -742,11 +892,31 @@ void Sle_ManDeriveResult( Sle_Man_t * p, Vec_Int_t * vEdge2, Vec_Int_t * vMappin
{
int i, iFanin, iEdgeVar0 = Vec_IntEntry( p->vEdgeFirst, iObj );
Vec_Int_t * vCutFans = Vec_WecEntry( p->vCutFanins, iObj );
+ //int * pCut, * pList = Sle_ManList( p, iObj );
+ // int iCutVar0 = Vec_IntEntry( p->vCutFirst, iObj );
if ( !sat_solver_var_value(p->pSat, iObj) )
continue;
+ //for ( i = 0; i < Sle_ListCutNum(pList); i++ )
+ // printf( "%d", sat_solver_var_value(p->pSat, iCutVar0 + i) );
+ //printf( "\n" );
Vec_IntForEachEntry( vCutFans, iFanin, i )
- if ( sat_solver_var_value(p->pSat, iEdgeVar0 + i) )
+ if ( sat_solver_var_value(p->pSat, iFanin) && sat_solver_var_value(p->pSat, iEdgeVar0 + i) )
+ {
+ // verify edge
+ int * pFanins = Gia_ObjLutFanins( p->pGia, iObj );
+ int k, nFanins = Gia_ObjLutSize( p->pGia, iObj );
+ for ( k = 0; k < nFanins; k++ )
+ {
+ //printf( "%d ", pFanins[k] );
+ if ( pFanins[k] == iFanin )
+ break;
+ }
+ //printf( "\n" );
+ if ( k == nFanins )
+// printf( "Cannot find LUT with input %d at node %d.\n", iFanin, iObj );
+ continue;
Vec_IntPushTwo( vEdge2, iFanin, iObj );
+ }
}
}
@@ -761,23 +931,31 @@ void Sle_ManDeriveResult( Sle_Man_t * p, Vec_Int_t * vEdge2, Vec_Int_t * vMappin
SeeAlso []
***********************************************************************/
-void Sle_ManExplore( Gia_Man_t * pGia, int DelayInit, int fVerbose )
+void Sle_ManExplore( Gia_Man_t * pGia, int nBTLimit, int DelayInit, int fDynamic, int fTwoEdges, int fVerbose )
{
int fVeryVerbose = 0;
abctime clk = Abc_Clock();
Vec_Int_t * vEdges2 = Vec_IntAlloc(1000);
Vec_Int_t * vMapping = Vec_IntAlloc(1000);
int i, iLut, nConfs, status, Delay, iFirstVar;
- int DelayStart = DelayInit ? DelayInit : Gia_ManLutLevel(pGia, NULL);
+ int DelayStart = (DelayInit || !Gia_ManHasMapping(pGia)) ? DelayInit : Gia_ManLutLevel(pGia, NULL);
Sle_Man_t * p = Sle_ManAlloc( pGia, DelayStart, fVerbose );
+ if ( fVerbose )
+ printf( "Running solver with %d conflicts, %d initial delay, and %d edges. Dynamic constraints = %s.\n", nBTLimit, DelayInit, 1+fTwoEdges, fDynamic?"yes":"no" );
Sle_ManMarkupVariables( p );
+ if ( fVerbose )
+ printf( "Vars: Total = %d. Node = %d. Cut = %d. Edge = %d. Delay = %d.\n",
+ p->nVarsTotal, p->nNodeVars, p->nCutVars, p->nEdgeVars, p->nDelayVars );
Sle_ManDeriveInit( p );
- Sle_ManDeriveCnf( p );
+ Sle_ManDeriveCnf( p, nBTLimit, fDynamic || fTwoEdges );
+ if ( fVerbose )
+ printf( "Clas: Total = %d. Cut = %d. Edge = %d. EdgeEx = %d. Delay = %d.\n",
+ sat_solver_nclauses(p->pSat), p->nCutClas, p->nEdgeClas, p->nEdgeClas2, p->nDelayClas );
//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", NULL, NULL, 0 );
- for ( Delay = DelayStart; Delay >= 0; Delay-- )
+ for ( Delay = p->nLevels; Delay >= 0; Delay-- )
{
// we constrain COs, although it would be fine to constrain only POs
- if ( Delay < DelayStart )
+ if ( Delay < p->nLevels )
{
Gia_ManForEachCoDriverId( p->pGia, iLut, i )
if ( Vec_BitEntry(p->vMask, iLut) ) // internal node
@@ -788,15 +966,26 @@ void Sle_ManExplore( Gia_Man_t * pGia, int DelayInit, int fVerbose )
}
if ( i < Gia_ManCoNum(p->pGia) )
{
- printf( "Proved UNSAT for delay %d. ", Delay );
- Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+ if ( fVerbose )
+ {
+ printf( "Proved UNSAT for delay %d. ", Delay );
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+ }
break;
}
}
// solve with assumptions
//clk = Abc_Clock();
nConfs = sat_solver_nconflicts( p->pSat );
- status = sat_solver_solve_internal( p->pSat );
+ while ( 1 )
+ {
+ p->nSatCalls++;
+ status = sat_solver_solve_internal( p->pSat );
+ if ( status != l_True )
+ break;
+ if ( !Sle_ManAddEdgeConstraints(p, 1+fTwoEdges) )
+ break;
+ }
nConfs = sat_solver_nconflicts( p->pSat ) - nConfs;
if ( status == l_True )
{
@@ -851,14 +1040,17 @@ void Sle_ManExplore( Gia_Man_t * pGia, int DelayInit, int fVerbose )
if ( fVerbose )
{
if ( status == l_False )
- printf( "Proved UNSAT for delay %d. ", Delay );
+ printf( "Proved UNSAT for delay %d. Conf = %8d. ", Delay, nConfs );
else
- printf( "Resource limit reached for delay %d. ", Delay );
+ printf( "Resource limit reached for delay %d. Conf = %8d. ", Delay, nConfs );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
}
break;
}
}
+ if ( fVerbose )
+ printf( "Clas: Total = %d. Cut = %d. Edge = %d. EdgeEx = %d. Delay = %d. Calls = %d.\n",
+ sat_solver_nclauses(p->pSat), p->nCutClas, p->nEdgeClas, p->nEdgeClas2, p->nDelayClas, p->nSatCalls );
if ( Vec_IntSize(vMapping) > 0 )
{
Gia_ManEdgeFromArray( p->pGia, vEdges2 );
@@ -871,6 +1063,7 @@ void Sle_ManExplore( Gia_Man_t * pGia, int DelayInit, int fVerbose )
Vec_IntFree( vEdges2 );
Vec_IntFree( vMapping );
}
+ Vec_IntFreeP( &p->pGia->vPacking );
Sle_ManStop( p );
}
diff --git a/src/aig/gia/giaShow.c b/src/aig/gia/giaShow.c
index 039931b2..872ba6ec 100644
--- a/src/aig/gia/giaShow.c
+++ b/src/aig/gia/giaShow.c
@@ -114,11 +114,12 @@ int Gia_WriteDotAigLevel( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vHadds,
return Level;
}
*/
-int Gia_WriteDotAigLevel( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vHadds, Vec_Int_t * vRecord, Vec_Int_t ** pvLevel, Vec_Int_t ** pvMarks, Vec_Int_t ** pvRemap )
+int Gia_WriteDotAigLevel( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vHadds, Vec_Int_t * vRecord, Vec_Int_t ** pvLevel, Vec_Int_t ** pvMarks, Vec_Int_t ** pvRemap, Vec_Int_t ** pvRemap2 )
{
Vec_Int_t * vLevel = Vec_IntStart( Gia_ManObjNum(p) );
Vec_Int_t * vMarks = Vec_IntStart( Gia_ManObjNum(p) );
Vec_Int_t * vRemap = Vec_IntStartNatural( Gia_ManObjNum(p) );
+ Vec_Int_t * vRemap2 = Vec_IntStartNatural( Gia_ManObjNum(p) );
int i, k, Id, Entry, LevelMax = 0;
Vec_IntWriteEntry( vMarks, 0, -1 );
@@ -141,6 +142,7 @@ int Gia_WriteDotAigLevel( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vHadds,
Vec_IntWriteEntry( vLevel, pFanins[4], Level+1 );
Vec_IntWriteEntry( vMarks, pFanins[4], Entry );
Vec_IntWriteEntry( vRemap, pFanins[3], pFanins[4] );
+ Vec_IntWriteEntry( vRemap2, pFanins[4], pFanins[3] );
//printf( "Making FA output %d.\n", pFanins[4] );
}
else if ( Attr == 1 )
@@ -154,7 +156,8 @@ int Gia_WriteDotAigLevel( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vHadds,
Vec_IntWriteEntry( vLevel, pFanins[1], Level+1 );
Vec_IntWriteEntry( vMarks, pFanins[1], Entry );
Vec_IntWriteEntry( vRemap, pFanins[0], pFanins[1] );
- //printf( "Making HA output %d.\n", pFanins[1] );
+ Vec_IntWriteEntry( vRemap2, pFanins[1], pFanins[0] );
+ //printf( "Making HA output %d %d.\n", pFanins[0], pFanins[1] );
}
else // if ( Attr == 3 || Attr == 0 )
{
@@ -171,6 +174,7 @@ int Gia_WriteDotAigLevel( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vHadds,
*pvLevel = vLevel;
*pvMarks = vMarks;
*pvRemap = vRemap;
+ *pvRemap2 = vRemap2;
return LevelMax;
}
@@ -188,7 +192,7 @@ int Gia_WriteDotAigLevel( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vHadds,
***********************************************************************/
void Gia_WriteDotAig( Gia_Man_t * pMan, char * pFileName, Vec_Int_t * vBold, int fAdders )
{
- Vec_Int_t * vFadds = NULL, * vHadds = NULL, * vRecord = NULL, * vMarks = NULL, * vRemap = NULL;
+ Vec_Int_t * vFadds = NULL, * vHadds = NULL, * vRecord = NULL, * vMarks = NULL, * vRemap = NULL, * vRemap2 = NULL;
FILE * pFile;
Gia_Obj_t * pNode;//, * pTemp, * pPrev;
int LevelMax, Prev, Level, i;
@@ -218,10 +222,10 @@ void Gia_WriteDotAig( Gia_Man_t * pMan, char * pFileName, Vec_Int_t * vBold, int
if ( fAdders )
{
Vec_IntFreeP( &pMan->vLevels );
- vFadds = Gia_ManDetectFullAdders( pMan, 0 );
+ vFadds = Gia_ManDetectFullAdders( pMan, 0, NULL );
vHadds = Gia_ManDetectHalfAdders( pMan, 0 );
vRecord = Gia_PolynFindOrder( pMan, vFadds, vHadds, 0, 0 );
- LevelMax = 1 + Gia_WriteDotAigLevel( pMan, vFadds, vHadds, vRecord, &pMan->vLevels, &vMarks, &vRemap );
+ LevelMax = 1 + Gia_WriteDotAigLevel( pMan, vFadds, vHadds, vRecord, &pMan->vLevels, &vMarks, &vRemap, &vRemap2 );
}
else
LevelMax = 1 + Gia_ManLevelNum( pMan );
@@ -364,7 +368,7 @@ void Gia_WriteDotAig( Gia_Man_t * pMan, char * pFileName, Vec_Int_t * vBold, int
*/
if ( vMarks && Vec_IntEntry(vMarks, i) > 0 )
{
- fprintf( pFile, " Node%d [label = \"%d_%d\"", i, Vec_IntFind(vRemap, i), i );
+ fprintf( pFile, " Node%d [label = \"%d_%d\"", i, Vec_IntEntry(vRemap2, i), i );
if ( Abc_Lit2Att2(Vec_IntEntry(vMarks, i)) == 2 )
fprintf( pFile, ", shape = doubleoctagon" );
else
diff --git a/src/aig/gia/giaStr.c b/src/aig/gia/giaStr.c
index bf89b547..68d478b8 100644
--- a/src/aig/gia/giaStr.c
+++ b/src/aig/gia/giaStr.c
@@ -30,6 +30,7 @@ ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
#define STR_SUPER 100
+#define MAX_TREE 10000
enum {
STR_NONE = 0,
@@ -1301,7 +1302,7 @@ Gia_Man_t * Str_NtkBalance( Gia_Man_t * pGia, Str_Ntk_t * p, int nLutSize, int f
pNew->vSuper = Vec_IntAlloc( 1000 );
if ( pNew->vStore == NULL )
pNew->vStore = Vec_IntAlloc( 1000 );
- vDelay = Vec_IntStart( pNew->nObjsAlloc );
+ vDelay = Vec_IntStart( 2*pNew->nObjsAlloc );
Gia_ManHashStart( pNew );
if ( pGia->pManTime != NULL ) // Tim_Man with unit delay 16
{
@@ -1646,7 +1647,7 @@ Str_Mux_t * Str_MuxFindBranching( Str_Mux_t * pRoot, int i )
}
int Str_MuxTryOnce( Gia_Man_t * pNew, Str_Ntk_t * pNtk, Str_Mux_t * pTree, Str_Mux_t * pRoot, int Edge, Vec_Int_t * vDelay, int fVerbose )
{
- int pPath[500];
+ int pPath[MAX_TREE];
Str_Mux_t pBackup[3];
int Delay, DelayBest = Str_MuxDelayEdge_rec( pRoot, Edge ), DelayInit = DelayBest;
int i, k, nLength = 0, ForkBest = -1, nChecks = 0;
@@ -1696,8 +1697,8 @@ int Str_MuxRestruct_rec( Gia_Man_t * pNew, Str_Ntk_t * pNtk, Str_Mux_t * pTree,
}
int Str_MuxRestructure2( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fVerbose )
{
- int Limit = 500;
- Str_Mux_t pTree[500];
+ int Limit = MAX_TREE;
+ Str_Mux_t pTree[MAX_TREE];
int Delay, Delay2, fChanges = 0;
if ( nMuxes >= Limit )
return -1;
@@ -1719,8 +1720,8 @@ int Str_MuxRestructure2( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxe
}
int Str_MuxRestructure1( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fVerbose )
{
- int Limit = 500;
- Str_Mux_t pTree[500];
+ int Limit = MAX_TREE;
+ Str_Mux_t pTree[MAX_TREE];
int Delay, Delay2, fChanges = 0;
if ( nMuxes >= Limit )
return -1;
@@ -1843,8 +1844,8 @@ int Str_MuxRestructArea_rec( Gia_Man_t * pNew, Str_Mux_t * pTree, Str_Mux_t * pR
}
int Str_MuxRestructureArea( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fVerbose )
{
- int Limit = 500;
- Str_Mux_t pTree[500];
+ int Limit = MAX_TREE;
+ Str_Mux_t pTree[MAX_TREE];
int Result;
if ( nMuxes >= Limit )
return -1;
diff --git a/src/aig/gia/giaSweep.c b/src/aig/gia/giaSweep.c
index 3bb6487b..2d8e705b 100644
--- a/src/aig/gia/giaSweep.c
+++ b/src/aig/gia/giaSweep.c
@@ -665,6 +665,8 @@ Gia_Man_t * Gia_ManSweepWithBoxesAndDomains( Gia_Man_t * p, void * pParsS, int f
continue;
// find global equivalences
pClp = Gia_ManDupCollapse( pNew, pNew->pAigExtra, NULL, 1 );
+ //Gia_DumpAiger( pClp, p->pSpec, iDom, 2 );
+ //Gia_ManPrintStats( pClp, NULL );
// compute equivalences
Gia_ManSweepComputeOneDomainEquivs( pClp, pNew->vRegClasses, iDom, pParsS, fConst, fEquiv, fVerbose );
// transfer equivalences
@@ -728,6 +730,7 @@ Gia_Man_t * Gia_ManSweepWithBoxes( Gia_Man_t * p, void * pParsC, void * pParsS,
nFlops = Vec_IntCountEntry(pNew->vRegClasses, 1);
// find global equivalences
pClp = Gia_ManDupCollapse( pNew, pNew->pAigExtra, NULL, pParsC ? 0 : 1 );
+ //Gia_DumpAiger( pClp, p->pSpec, 1, 1 );
// compute equivalences
if ( pParsC )
Gia_ManFraigSweepPerform( pClp, pParsC );
diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h
index 971f29bb..35b20dbe 100644
--- a/src/base/abc/abc.h
+++ b/src/base/abc/abc.h
@@ -642,6 +642,11 @@ extern ABC_DLL int Abc_NtkLevelReverse( Abc_Ntk_t * pNtk );
extern ABC_DLL int Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk );
extern ABC_DLL int Abc_NtkIsAcyclicWithBoxes( Abc_Ntk_t * pNtk );
extern ABC_DLL Vec_Ptr_t * Abc_AigGetLevelizedOrder( Abc_Ntk_t * pNtk, int fCollectCis );
+/*=== abcExact.c ==========================================================*/
+extern ABC_DLL int Abc_ExactInputNum();
+extern ABC_DLL int Abc_ExactIsRunning();
+extern ABC_DLL Abc_Obj_t * Abc_ExactBuildNode( word * pTruth, int nVars, int * pArrTimeProfile, Abc_Obj_t ** pFanins, Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Ntk_t * Abc_NtkFindExact( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrivalTimes, int fVerbose );
/*=== abcFanio.c ==========================================================*/
extern ABC_DLL void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin );
extern ABC_DLL void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin );
@@ -820,7 +825,7 @@ extern ABC_DLL void Abc_NtkDontCareFree( Odc_Man_t * p );
extern ABC_DLL int Abc_NtkDontCareCompute( Odc_Man_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth );
/*=== abcPrint.c ==========================================================*/
extern ABC_DLL float Abc_NtkMfsTotalSwitching( Abc_Ntk_t * pNtk );
-extern ABC_DLL void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower, int fGlitch, int fSkipBuf, int fPrintMem );
+extern ABC_DLL void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower, int fGlitch, int fSkipBuf, int fSkipSmall, int fPrintMem );
extern ABC_DLL void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintFlops );
extern ABC_DLL void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk );
extern ABC_DLL void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk, int fUseFanio, int fUsePio, int fUseSupp, int fUseCone );
@@ -986,6 +991,7 @@ extern ABC_DLL double Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk );
extern ABC_DLL int Abc_NtkGetExorNum( Abc_Ntk_t * pNtk );
extern ABC_DLL int Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk );
extern ABC_DLL int Abc_NtkGetBufNum( Abc_Ntk_t * pNtk );
+extern ABC_DLL int Abc_NtkGetLargeNodeNum( Abc_Ntk_t * pNtk );
extern ABC_DLL int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk );
extern ABC_DLL int Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk );
extern ABC_DLL int Abc_NtkGetFanoutMax( Abc_Ntk_t * pNtk );
diff --git a/src/base/abc/abcFunc.c b/src/base/abc/abcFunc.c
index 94706504..5d0261d7 100644
--- a/src/base/abc/abcFunc.c
+++ b/src/base/abc/abcFunc.c
@@ -810,7 +810,7 @@ int Abc_NtkSopToAig( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pNode;
Hop_Man_t * pMan;
- int i;
+ int i, Max;
assert( Abc_NtkHasSop(pNtk) );
@@ -819,7 +819,8 @@ int Abc_NtkSopToAig( Abc_Ntk_t * pNtk )
// start the functionality manager
pMan = Hop_ManStart();
- Hop_IthVar( pMan, Abc_NtkGetFaninMax(pNtk)-1 );
+ Max = Abc_NtkGetFaninMax(pNtk);
+ if ( Max ) Hop_IthVar( pMan, Max-1 );
// convert each node from SOP to BDD
Abc_NtkForEachNode( pNtk, pNode, i )
@@ -979,7 +980,7 @@ Gia_Man_t * Abc_NtkAigToGia( Abc_Ntk_t * p, int fGiaSimple )
Vec_Int_t * vMapping = NULL;
Vec_Ptr_t * vNodes;
Abc_Obj_t * pNode, * pFanin;
- int i, k, nObjs;
+ int i, k, nObjs, iGiaObj;
assert( Abc_NtkIsAigLogic(p) );
pHopMan = (Hop_Man_t *)p->pManFunc;
// create new manager
@@ -1015,15 +1016,14 @@ Gia_Man_t * Abc_NtkAigToGia( Abc_Ntk_t * p, int fGiaSimple )
{
assert( Abc_ObjFaninNum(pNode) <= Hop_ManPiNum(pHopMan) );
Abc_ConvertAigToGia( pNew, pHopObj );
- if ( !Gia_ObjIsAnd(Gia_ManObj(pNew, Abc_Lit2Var(pHopObj->iData))) )
- continue;
- if ( vMapping && !Vec_IntEntry(vMapping, Abc_Lit2Var(pHopObj->iData)) )
+ iGiaObj = Abc_Lit2Var( pHopObj->iData );
+ if ( vMapping && Gia_ObjIsAnd(Gia_ManObj(pNew, iGiaObj)) && !Vec_IntEntry(vMapping, iGiaObj) )
{
- Vec_IntWriteEntry( vMapping, Abc_Lit2Var(pHopObj->iData), Vec_IntSize(vMapping) );
+ Vec_IntWriteEntry( vMapping, iGiaObj, Vec_IntSize(vMapping) );
Vec_IntPush( vMapping, Abc_ObjFaninNum(pNode) );
Abc_ObjForEachFanin( pNode, pFanin, k )
Vec_IntPush( vMapping, Abc_Lit2Var(pFanin->iTemp) );
- Vec_IntPush( vMapping, Abc_Lit2Var(pHopObj->iData) );
+ Vec_IntPush( vMapping, iGiaObj );
}
}
pNode->iTemp = Abc_LitNotCond( pHopObj->iData, Hop_IsComplement( (Hop_Obj_t *)pNode->pData ) );
diff --git a/src/base/abc/abcUtil.c b/src/base/abc/abcUtil.c
index 59993614..f01ef07a 100644
--- a/src/base/abc/abcUtil.c
+++ b/src/base/abc/abcUtil.c
@@ -429,6 +429,26 @@ int Abc_NtkGetBufNum( Abc_Ntk_t * pNtk )
/**Function*************************************************************
+ Synopsis [Counts the number of exors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkGetLargeNodeNum( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i, Counter = 0;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ Counter += (Abc_ObjFaninNum(pNode) > 1);
+ return Counter;
+}
+
+/**Function*************************************************************
+
Synopsis [Returns 1 if it is an AIG with choice nodes.]
Description []
diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c
index 699b5ec1..31f3a275 100644
--- a/src/base/abci/abc.c
+++ b/src/base/abci/abc.c
@@ -135,6 +135,10 @@ static int Abc_CommandCascade ( Abc_Frame_t * pAbc, int argc, cha
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_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 );
+static int Abc_CommandBmsPs ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandComb ( Abc_Frame_t * pAbc, int argc, char ** argv );
@@ -232,6 +236,7 @@ static int Abc_CommandFraigRestore ( Abc_Frame_t * pAbc, int argc, cha
static int Abc_CommandFraigClean ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandFraigSweep ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandFraigDress ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDumpEquiv ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandRecStart3 ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandRecStop3 ( Abc_Frame_t * pAbc, int argc, char ** argv );
@@ -773,6 +778,11 @@ void Abc_Init( Abc_Frame_t * pAbc )
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", "exact", Abc_CommandExact, 1 );
+
+ Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_start", Abc_CommandBmsStart, 0 );
+ Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_stop", Abc_CommandBmsStop, 0 );
+ Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_ps", Abc_CommandBmsPs, 0 );
Cmd_CommandAdd( pAbc, "Various", "logic", Abc_CommandLogic, 1 );
Cmd_CommandAdd( pAbc, "Various", "comb", Abc_CommandComb, 1 );
@@ -867,6 +877,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Fraiging", "fraig_clean", Abc_CommandFraigClean, 0 );
Cmd_CommandAdd( pAbc, "Fraiging", "fraig_sweep", Abc_CommandFraigSweep, 1 );
Cmd_CommandAdd( pAbc, "Fraiging", "dress", Abc_CommandFraigDress, 1 );
+ Cmd_CommandAdd( pAbc, "Fraiging", "dump_equiv", Abc_CommandDumpEquiv, 0 );
Cmd_CommandAdd( pAbc, "Choicing", "rec_start3", Abc_CommandRecStart3, 0 );
Cmd_CommandAdd( pAbc, "Choicing", "rec_stop3", Abc_CommandRecStop3, 0 );
@@ -1223,6 +1234,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
int fPower;
int fGlitch;
int fSkipBuf;
+ int fSkipSmall;
int fPrintMem;
int c;
@@ -1238,9 +1250,10 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
fPower = 0;
fGlitch = 0;
fSkipBuf = 0;
+ fSkipSmall = 0;
fPrintMem = 0;
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "fbdltmpgsuh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "fbdltmpgscuh" ) ) != EOF )
{
switch ( c )
{
@@ -1271,6 +1284,9 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
case 's':
fSkipBuf ^= 1;
break;
+ case 'c':
+ fSkipSmall ^= 1;
+ break;
case 'u':
fPrintMem ^= 1;
break;
@@ -1291,7 +1307,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Print( -1, "Cannot print LUT delay for a non-logic network.\n" );
return 1;
}
- Abc_NtkPrintStats( pNtk, fFactor, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf, fPrintMem );
+ Abc_NtkPrintStats( pNtk, fFactor, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf, fSkipSmall, fPrintMem );
if ( fPrintTime )
{
pAbc->TimeTotal += pAbc->TimeCommand;
@@ -1301,7 +1317,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- Abc_Print( -2, "usage: print_stats [-fbdltmpgsuh]\n" );
+ Abc_Print( -2, "usage: print_stats [-fbdltmpgscuh]\n" );
Abc_Print( -2, "\t prints the network statistics\n" );
Abc_Print( -2, "\t-f : toggles printing the literal count in the factored forms [default = %s]\n", fFactor? "yes": "no" );
Abc_Print( -2, "\t-b : toggles saving the best logic network in \"best.blif\" [default = %s]\n", fSaveBest? "yes": "no" );
@@ -1312,6 +1328,7 @@ usage:
Abc_Print( -2, "\t-p : toggles printing power dissipation due to switching [default = %s]\n", fPower? "yes": "no" );
Abc_Print( -2, "\t-g : toggles printing percentage of increased power due to glitching [default = %s]\n", fGlitch? "yes": "no" );
Abc_Print( -2, "\t-s : toggles not counting single-output nodes as nodes [default = %s]\n", fSkipBuf? "yes": "no" );
+ Abc_Print( -2, "\t-c : toggles not counting constants and single-output nodes as nodes [default = %s]\n", fSkipSmall? "yes": "no" );
Abc_Print( -2, "\t-u : toggles printing memory usage [default = %s]\n", fPrintMem? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
@@ -1393,7 +1410,7 @@ int Abc_CommandPrintExdc( Abc_Frame_t * pAbc, int argc, char ** argv )
}
else
Abc_Print( 1, "EXDC network statistics: \n" );
- Abc_NtkPrintStats( pNtk->pExdc, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
+ Abc_NtkPrintStats( pNtk->pExdc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
return 0;
usage:
@@ -7218,15 +7235,18 @@ usage:
***********************************************************************/
int Abc_CommandDetect( Abc_Frame_t * pAbc, int argc, char ** argv )
{
- extern void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fVerbose );
+ extern void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fSeq, int fVerbose );
Abc_Ntk_t * pNtk;
- int c, fVerbose = 0;
+ int c, fSeq = 0, fVerbose = 0;
pNtk = Abc_FrameReadNtk(pAbc);
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF )
{
switch ( c )
{
+ case 's':
+ fSeq ^= 1;
+ break;
case 'v':
fVerbose ^= 1;
break;
@@ -7246,12 +7266,13 @@ 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, fVerbose );
+ Abc_NtkDetectClassesTest( pNtk, fSeq, fVerbose );
return 0;
usage:
- Abc_Print( -2, "usage: detect [-vh]\n" );
+ 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, "\t-h : print the command usage\n");
return 1;
@@ -7268,6 +7289,310 @@ usage:
SeeAlso []
***********************************************************************/
+int Abc_CommandExact( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ extern Gia_Man_t * Gia_ManFindExact( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrivalTimes, int fVerbose );
+
+ int c, nMaxDepth = -1, fMakeAIG = 0, fTest = 0, fVerbose = 0, nVars = 0, nVarsTmp, nFunc = 0;
+ word pTruth[64];
+ Abc_Ntk_t * pNtkRes;
+ Gia_Man_t * pGiaRes;
+
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Datvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'D':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nMaxDepth = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nMaxDepth < 0 )
+ goto usage;
+ break;
+ case 'a':
+ fMakeAIG ^= 1;
+ break;
+ case 't':
+ fTest ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( fTest )
+ {
+ extern void Abc_ExactTest( int fVerbose );
+ extern void Abc_ExactStoreTest( int fVerbose );
+
+ printf( "run test suite, ignore all other settings\n" );
+ Abc_ExactTest( fVerbose );
+ Abc_ExactStoreTest( fVerbose );
+ return 0;
+ }
+
+ if ( argc == globalUtilOptind )
+ goto usage;
+
+ memset( pTruth, 0, 64 );
+ while ( globalUtilOptind < argc )
+ {
+ if ( nFunc == 16 )
+ {
+ Abc_Print( -1, "Too many functions (at most 16 supported).\n" );
+ goto usage;
+ }
+ nVarsTmp = Abc_TtReadHex( &pTruth[nFunc << 2], argv[globalUtilOptind++] );
+ nFunc++;
+ if ( nVars == 0 )
+ nVars = nVarsTmp;
+ else if ( nVars > 8 )
+ {
+ Abc_Print( -1, "Only 8-variable functions are supported.\n" );
+ goto usage;
+ }
+ else if ( nVars != nVarsTmp )
+ {
+ Abc_Print( -1, "All functions need to have the same size.\n" );
+ goto usage;
+ }
+ }
+
+ if ( fMakeAIG )
+ {
+ pGiaRes = Gia_ManFindExact( pTruth, nVars, nFunc, nMaxDepth, NULL, fVerbose );
+ if ( pGiaRes )
+ Abc_FrameUpdateGia( pAbc, pGiaRes );
+ else
+ Abc_Print( 0, "Could not find AIG within given resource constraints.\n" );
+ }
+ else
+ {
+ pNtkRes = Abc_NtkFindExact( pTruth, nVars, nFunc, nMaxDepth, NULL, fVerbose );
+ if ( pNtkRes )
+ {
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ Abc_FrameClearVerifStatus( pAbc );
+ }
+ else
+ Abc_Print( 0, "Could not find network within given resource constraints.\n" );
+ }
+ return 0;
+
+usage:
+ Abc_Print( -2, "usage: exact [-D <num>] [-atvh] <truth1> <truth2> ...\n" );
+ 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 : toggle create AIG [default = %s]\n", fMakeAIG ? "yes" : "no" );
+ Abc_Print( -2, "\t-t : run test suite\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" );
+ Abc_Print( -2, "\t\n" );
+ Abc_Print( -2, "\t This command was contributed by Mathias Soeken from EPFL in July 2016.\n" );
+ Abc_Print( -2, "\t The author can be contacted as mathias.soeken at epfl.ch\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandBmsStart( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ extern int Abc_ExactIsRunning();
+ extern void Abc_ExactStart( int nBTLimit, int fMakeAIG, int fVerbose, const char *pFilename );
+
+ int c, fMakeAIG = 0, fVerbose = 0, nBTLimit = 10000;
+ char * pFilename = NULL;
+
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Cavh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nBTLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ break;
+ case 'a':
+ fMakeAIG ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( argc > globalUtilOptind )
+ {
+ pFilename = argv[globalUtilOptind++];
+ }
+
+ if ( Abc_ExactIsRunning() )
+ {
+ Abc_Print( -1, "BMS manager is already started." );
+ return 1;
+ }
+
+ Abc_ExactStart( nBTLimit, fMakeAIG, fVerbose, pFilename );
+ return 0;
+
+usage:
+ Abc_Print( -2, "usage: bms_start [-C <num>] [-avh] [<file>]\n" );
+ Abc_Print( -2, "\t starts BMS manager for recording optimum networks\n" );
+ Abc_Print( -2, "\t if <file> is specified, store entries are read from that file\n" );
+ Abc_Print( -2, "\t-C <num> : the limit on the number of conflicts [default = %d]\n", nBTLimit );
+ Abc_Print( -2, "\t-a : toggle create AIG [default = %s]\n", fMakeAIG ? "yes" : "no" );
+ Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no" );
+ Abc_Print( -2, "\t-h : print the command usage\n" );
+ Abc_Print( -2, "\t\n" );
+ Abc_Print( -2, "\t This command was contributed by Mathias Soeken from EPFL in July 2016.\n" );
+ Abc_Print( -2, "\t The author can be contacted as mathias.soeken at epfl.ch\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandBmsStop( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ extern int Abc_ExactIsRunning();
+ extern void Abc_ExactStop( const char *pFilename );
+
+ int c;
+ char * pFilename = NULL;
+
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( argc > globalUtilOptind )
+ {
+ pFilename = argv[globalUtilOptind++];
+ }
+
+ if ( !Abc_ExactIsRunning() )
+ {
+ Abc_Print( -1, "BMS manager is not started." );
+ return 1;
+ }
+
+ Abc_ExactStop( pFilename );
+ return 0;
+
+usage:
+ Abc_Print( -2, "usage: bms_stop [-C <num>] [-vh] [<file>]\n" );
+ Abc_Print( -2, "\t stops BMS manager for recording optimum networks\n" );
+ Abc_Print( -2, "\t if <file> is specified, store entries are written to that file\n" );
+ Abc_Print( -2, "\t-h : print the command usage\n" );
+ Abc_Print( -2, "\t\n" );
+ Abc_Print( -2, "\t This command was contributed by Mathias Soeken from EPFL in July 2016.\n" );
+ Abc_Print( -2, "\t The author can be contacted as mathias.soeken at epfl.ch\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandBmsPs( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ extern int Abc_ExactIsRunning();
+ extern void Abc_ExactStats();
+
+ int c;
+
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( !Abc_ExactIsRunning() )
+ {
+ Abc_Print( -1, "BMS manager is not started." );
+ return 1;
+ }
+
+ Abc_ExactStats();
+ return 0;
+
+usage:
+ Abc_Print( -2, "usage: bms_ps [-h]\n" );
+ Abc_Print( -2, "\t shows statistics about BMS manager\n" );
+ Abc_Print( -2, "\t-h : print the command usage\n" );
+ Abc_Print( -2, "\t\n" );
+ Abc_Print( -2, "\t This command was contributed by Mathias Soeken from EPFL in July 2016.\n" );
+ Abc_Print( -2, "\t The author can be contacted as mathias.soeken at epfl.ch\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Abc_Ntk_t * pNtk, * pNtkRes;
@@ -14745,6 +15070,93 @@ usage:
SeeAlso []
***********************************************************************/
+int Abc_CommandDumpEquiv( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ extern void Abc_NtkDumpEquiv( Abc_Ntk_t * pNtks[2], char * pFileName, int nConfs, int fByName, int fVerbose );
+ Abc_Ntk_t * pNtks[2] = {NULL};
+ char * pFileName[2], * pFileNameOut;
+ int c, nConfs = 1000, fByName = 1, fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Cnvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfs = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfs < 0 )
+ goto usage;
+ break;
+ case 'n':
+ fByName ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( argc != globalUtilOptind + 3 )
+ {
+ Abc_Print( -1, "Expecting three file names on the command line.\n" );
+ goto usage;
+ }
+ pFileName[0] = argv[globalUtilOptind];
+ pFileName[1] = argv[globalUtilOptind+1];
+ pFileNameOut = argv[globalUtilOptind+2];
+ for ( c = 0; c < 2; c++ )
+ {
+ pNtks[c] = Io_Read( pFileName[c], Io_ReadFileType(pFileName[c]), 1, 0 );
+ if ( pNtks[c] == NULL )
+ goto usage;
+ Abc_NtkToAig( pNtks[c] );
+ }
+// if ( Abc_NtkCiNum(pNtks[0]) != Abc_NtkCiNum(pNtks[1]) )
+// Abc_Print( -1, "The number of primary inputs of networks \"%s\" and \"%s\" does not match.\n", Abc_NtkName(pNtks[0]), Abc_NtkName(pNtks[1]) );
+// else if ( Abc_NtkCoNum(pNtks[0]) != Abc_NtkCoNum(pNtks[1]) )
+// Abc_Print( -1, "The number of primary outputs of networks \"%s\" and \"%s\" does not match.\n", Abc_NtkName(pNtks[0]), Abc_NtkName(pNtks[1]) );
+// else
+ Abc_NtkDumpEquiv( pNtks, pFileNameOut, nConfs, fByName, fVerbose );
+ Abc_NtkDelete( pNtks[0] );
+ Abc_NtkDelete( pNtks[1] );
+ return 0;
+
+usage:
+ Abc_Print( -2, "usage: dump_equiv [-C num] [-nvh] <file1.blif> <file2.blif> <file_dump_equiv.txt>\n" );
+ Abc_Print( -2, "\t computes equivalence classes of nodes in <file1> and <file2>\n" );
+ Abc_Print( -2, "\t By default this procedure performs matching of primary inputs by name.\n" );
+ Abc_Print( -2, "\t Those inputs that cannot be matched are treated as free variables.\n" );
+ Abc_Print( -2, "\t There is no effort to match primary outputs. Indeed, if two outputs\n" );
+ Abc_Print( -2, "\t are equivalent, they will belong to the same equivalence class in the end.\n" );
+ Abc_Print( -2, "\t-C num : the maximum number of conflicts at each node [default = %d]\n", nConfs );
+ Abc_Print( -2, "\t-n : enable matching of primary inputs by name [default = %s]\n", fByName? "yes": "no" );
+ Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ Abc_Print( -2, "\t-h : print the command usage\n");
+ Abc_Print( -2, "\t<file1> : first network whose nodes are considered\n" );
+ Abc_Print( -2, "\t<file2> : second network whose nodes are considered\n" );
+ Abc_Print( -2, "\t<file_dump_equiv> : text file with node equivalence classes\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Abc_CommandRecStart3( Abc_Frame_t * pAbc, int argc, char ** argv )
{
char * FileName, * pTemp;
@@ -16277,7 +16689,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
If_ManSetDefaultPars( pPars );
pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut();
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYDEWSqaflepmrsdbgxyojiktncvh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYDEWSqaflepmrsdbgxyuojiktncvh" ) ) != EOF )
{
switch ( c )
{
@@ -16482,6 +16894,9 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'y':
pPars->fUserRecLib ^= 1;
break;
+ case 'u':
+ pPars->fUserSesLib ^= 1;
+ break;
case 'o':
pPars->fUseBuffs ^= 1;
break;
@@ -16625,7 +17040,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
pPars->fExpRed = 0;
}
// modify the subgraph recording
- if ( pPars->fUserRecLib )
+ if ( pPars->fUserRecLib || pPars->fUserSesLib )
{
pPars->fTruth = 1;
pPars->fCutMin = 1;
@@ -16699,7 +17114,21 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
}
if ( Abc_NtkRecInputNum3() != pPars->nLutSize )
{
- printf( "The number of library inputs (%d) different from the K parameters (%d).\n", Abc_NtkRecInputNum3(), pPars->nLutSize );
+ printf( "The number of library inputs (%d) is different from the K parameters (%d).\n", Abc_NtkRecInputNum3(), pPars->nLutSize );
+ return 0;
+ }
+ }
+
+ if ( pPars->fUserSesLib )
+ {
+ if ( !Abc_ExactIsRunning() )
+ {
+ printf( "BMS manager is not running (use \"bms_start\").\n" );
+ return 0;
+ }
+ if ( Abc_ExactInputNum() < pPars->nLutSize )
+ {
+ printf( "The number of library inputs (%d) is smaller than the K parameters (%d).\n", Abc_ExactInputNum(), pPars->nLutSize );
return 0;
}
}
@@ -16766,7 +17195,7 @@ usage:
sprintf(LutSize, "library" );
else
sprintf(LutSize, "%d", pPars->nLutSize );
- Abc_Print( -2, "usage: if [-KCFAGRNTXY num] [-DEW float] [-S str] [-qarlepmsdbgxyojiktncvh]\n" );
+ Abc_Print( -2, "usage: if [-KCFAGRNTXY num] [-DEW float] [-S str] [-qarlepmsdbgxyuojiktncvh]\n" );
Abc_Print( -2, "\t performs FPGA technology mapping of the network\n" );
Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize );
Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax );
@@ -16795,6 +17224,7 @@ usage:
Abc_Print( -2, "\t-g : toggles delay optimization by SOP balancing [default = %s]\n", pPars->fDelayOpt? "yes": "no" );
Abc_Print( -2, "\t-x : toggles delay optimization by DSD balancing [default = %s]\n", pPars->fDsdBalance? "yes": "no" );
Abc_Print( -2, "\t-y : toggles delay optimization with recorded library [default = %s]\n", pPars->fUserRecLib? "yes": "no" );
+ Abc_Print( -2, "\t-u : toggles delay optimization with SAT-based library [default = %s]\n", pPars->fUserSesLib? "yes": "no" );
Abc_Print( -2, "\t-o : toggles using buffers to decouple combinational outputs [default = %s]\n", pPars->fUseBuffs? "yes": "no" );
Abc_Print( -2, "\t-j : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck07? "yes": "no" );
Abc_Print( -2, "\t-i : toggles using cofactoring variables [default = %s]\n", pPars->fUseCofVars? "yes": "no" );
@@ -26955,7 +27385,7 @@ usage:
Abc_Print( -2, "\t converts the current network into GIA and moves it to the &-space\n" );
Abc_Print( -2, "\t (if the network is a sequential logic network, normalizes the flops\n" );
Abc_Print( -2, "\t to have const-0 initial values, equivalent to \"undc; st; zero\")\n" );
- Abc_Print( -2, "\t-c : toggles allowing simple GIA to be improved [default = %s]\n", fGiaSimple? "yes": "no" );
+ Abc_Print( -2, "\t-c : toggles allowing simple GIA to be imported [default = %s]\n", fGiaSimple? "yes": "no" );
Abc_Print( -2, "\t-m : toggles preserving the current mapping [default = %s]\n", fMapped? "yes": "no" );
Abc_Print( -2, "\t-n : toggles saving CI/CO names of the AIG [default = %s]\n", fNames? "yes": "no" );
Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" );
@@ -27110,7 +27540,7 @@ usage:
SeeAlso []
***********************************************************************/
-static inline int Gia_ManCompareWithBest( Gia_Man_t * pBest, Gia_Man_t * p, int * pnBestLuts, int * pnBestEdges, int * pnBestLevels )
+static inline int Gia_ManCompareWithBest( Gia_Man_t * pBest, Gia_Man_t * p, int * pnBestLuts, int * pnBestEdges, int * pnBestLevels, int fArea )
{
int nCurLuts, nCurEdges, nCurLevels;
Gia_ManLutParams( p, &nCurLuts, &nCurEdges, &nCurLevels );
@@ -27119,8 +27549,9 @@ static inline int Gia_ManCompareWithBest( Gia_Man_t * pBest, Gia_Man_t * p, int
Gia_ManPoNum(pBest) != Gia_ManPoNum(p) ||
Gia_ManRegNum(pBest) != Gia_ManRegNum(p) ||
strcmp(Gia_ManName(pBest), Gia_ManName(p)) ||
- (*pnBestLevels > nCurLevels) ||
- (*pnBestLevels == nCurLevels && 2*(*pnBestLuts) + *pnBestEdges > 2*nCurLuts + nCurEdges) )
+ (!fArea && (*pnBestLevels > nCurLevels || (*pnBestLevels == nCurLevels && 2*(*pnBestLuts) + *pnBestEdges > 2*nCurLuts + nCurEdges))) ||
+ ( fArea && (*pnBestLuts > nCurLuts || (*pnBestLuts == nCurLuts && *pnBestLevels > nCurLevels)))
+ )
{
*pnBestLuts = nCurLuts;
*pnBestEdges = nCurEdges;
@@ -27143,12 +27574,15 @@ static inline int Gia_ManCompareWithBest( Gia_Man_t * pBest, Gia_Man_t * p, int
***********************************************************************/
int Abc_CommandAbc9Save( Abc_Frame_t * pAbc, int argc, char ** argv )
{
- int c;
+ int c, fArea = 0;
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF )
{
switch ( c )
{
+ case 'a':
+ fArea ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -27165,7 +27599,7 @@ int Abc_CommandAbc9Save( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Print( -1, "GIA has no mapping.\n" );
return 1;
}
- if ( !Gia_ManCompareWithBest( pAbc->pGiaBest, pAbc->pGia, &pAbc->nBestLuts, &pAbc->nBestEdges, &pAbc->nBestLevels ) )
+ if ( !Gia_ManCompareWithBest( pAbc->pGiaBest, pAbc->pGia, &pAbc->nBestLuts, &pAbc->nBestEdges, &pAbc->nBestLevels, fArea ) )
return 0;
// save the design as best
Gia_ManStopP( &pAbc->pGiaBest );
@@ -27173,8 +27607,9 @@ int Abc_CommandAbc9Save( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- Abc_Print( -2, "usage: &save [-h]\n" );
+ Abc_Print( -2, "usage: &save [-ah]\n" );
Abc_Print( -2, "\t compares and possibly saves AIG with mapping\n" );
+ Abc_Print( -2, "\t-a : toggle using area as the primary metric [default = %s]\n", fArea? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
@@ -33363,7 +33798,7 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv )
{
if ( !Abc_FrameReadFlag("silentmode") )
Abc_Print( -1, "Empty GIA network.\n" );
- return 1;
+ return 0;
}
if ( Gia_ManBufNum(pAbc->pGia) )
{
@@ -35224,14 +35659,23 @@ int Abc_CommandAbc9Edge( Abc_Frame_t * pAbc, int argc, char ** argv )
{
extern int Edg_ManAssignEdgeNew( Gia_Man_t * p, int nEdges, int fVerbose );
extern void Seg_ManComputeDelay( Gia_Man_t * pGia, int Delay, int nFanouts, int fTwo, int fVerbose );
- extern void Sle_ManExplore( Gia_Man_t * pGia, int DelayInit, int fVerbose );
+ extern void Sle_ManExplore( Gia_Man_t * pGia, int nBTLimit, int DelayInit, int fDynamic, int fTwoEdges, int fVerbose );
- int c, DelayMax = 0, nFanouts = 0, nEdges = 1, fReverse = 0, fUsePack = 0, fUseOld = 0, fMapping = 0, fVerbose = 0;
+ int c, nBTLimit = 0, DelayMax = 0, nFanouts = 0, nEdges = 1, fReverse = 0, fUsePack = 0, fUseOld = 0, fMapping = 0, fDynamic = 1, fVerbose = 0;
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "DFErpomvh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "CDFErpomdvh" ) ) != EOF )
{
switch ( c )
{
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nBTLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ break;
case 'D':
if ( globalUtilOptind >= argc )
{
@@ -35276,6 +35720,9 @@ int Abc_CommandAbc9Edge( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'm':
fMapping ^= 1;
break;
+ case 'd':
+ fDynamic ^= 1;
+ break;
case 'v':
fVerbose ^= 1;
break;
@@ -35289,16 +35736,16 @@ int Abc_CommandAbc9Edge( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Print( -1, "Empty GIA network.\n" );
return 1;
}
+ if ( fMapping )
+ {
+ Sle_ManExplore( pAbc->pGia, nBTLimit, DelayMax, fDynamic, nEdges==2, fVerbose );
+ return 0;
+ }
if ( !Gia_ManHasMapping(pAbc->pGia) )
{
Abc_Print( -1, "Current AIG has no mapping. Run \"&if\".\n" );
return 1;
}
- if ( fMapping )
- {
- Sle_ManExplore( pAbc->pGia, DelayMax, fVerbose );
- return 0;
- }
if ( Gia_ManLutSizeMax(pAbc->pGia) > 6 )
{
Abc_Print( 0, "Current AIG has mapping into %d-LUTs.\n", Gia_ManLutSizeMax(pAbc->pGia) );
@@ -35333,8 +35780,9 @@ int Abc_CommandAbc9Edge( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- Abc_Print( -2, "usage: &edge [-DFE num] [-rpomvh]\n" );
+ Abc_Print( -2, "usage: &edge [-CDFE num] [-rpomdvh]\n" );
Abc_Print( -2, "\t find edge assignment of the LUT-mapped network\n" );
+ Abc_Print( -2, "\t-C num : the SAT solver conflict limit (0 = unused) [default = %d]\n", nBTLimit );
Abc_Print( -2, "\t-D num : the upper bound on delay [default = %d]\n", DelayMax );
Abc_Print( -2, "\t-F num : skip using edge if fanout higher than this [default = %d]\n", nFanouts );
Abc_Print( -2, "\t-E num : the limit on the number of edges (1 <= num <= 2) [default = %d]\n", nEdges );
@@ -35342,6 +35790,7 @@ usage:
Abc_Print( -2, "\t-p : toggles deriving edges from packing [default = %s]\n", fUsePack? "yes": "no" );
Abc_Print( -2, "\t-o : toggles using old algorithm [default = %s]\n", fUseOld? "yes": "no" );
Abc_Print( -2, "\t-m : toggles combining edge assignment with mapping [default = %s]\n", fMapping? "yes": "no" );
+ Abc_Print( -2, "\t-d : toggles dynamic addition of clauses [default = %s]\n", fDynamic? "yes": "no" );
Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : prints the command usage\n");
return 1;
@@ -35505,6 +35954,8 @@ int Abc_CommandAbc9Unmap( Abc_Frame_t * pAbc, int argc, char ** argv )
Vec_IntFreeP( &pAbc->pGia->vMapping );
Vec_IntFreeP( &pAbc->pGia->vPacking );
Vec_IntFreeP( &pAbc->pGia->vCellMapping );
+ Vec_IntFreeP( &pAbc->pGia->vEdge1 );
+ Vec_IntFreeP( &pAbc->pGia->vEdge2 );
return 0;
usage:
@@ -39675,7 +40126,7 @@ usage:
int Abc_CommandAbc9Polyn( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Vec_Int_t * vOrder = NULL;
- int c, fSimple = 0, fSigned = 0, fVerbose = 0, fVeryVerbose = 0;
+ int c, fSimple = 1, fSigned = 0, fVerbose = 0, fVeryVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "asvwh" ) ) != EOF )
{
diff --git a/src/base/abci/abcDetect.c b/src/base/abci/abcDetect.c
index 8fa395e8..c87169b5 100644
--- a/src/base/abci/abcDetect.c
+++ b/src/base/abci/abcDetect.c
@@ -193,7 +193,7 @@ finish:
SeeAlso []
***********************************************************************/
-void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fVerbose )
+void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fSeq, int fVerbose )
{
printf( "This procedure is currently not used.\n" );
}
diff --git a/src/base/abci/abcDress3.c b/src/base/abci/abcDress3.c
new file mode 100644
index 00000000..33545f0a
--- /dev/null
+++ b/src/base/abci/abcDress3.c
@@ -0,0 +1,344 @@
+/**CFile****************************************************************
+
+ FileName [abcDress3.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Transfers names from one netlist to the other.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcDress3.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/io/ioAbc.h"
+#include "proof/cec/cec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Compute equivalence classes of nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkComputeGiaEquivs( Gia_Man_t * pGia, int nConfs, int fVerbose )
+{
+ Gia_Man_t * pTemp;
+ Cec_ParFra_t ParsFra, * pPars = &ParsFra;
+ Cec_ManFraSetDefaultParams( pPars );
+ pPars->fUseOrigIds = 1;
+ pPars->fSatSweeping = 1;
+ pPars->nBTLimit = nConfs;
+ pPars->fVerbose = fVerbose;
+ pTemp = Cec_ManSatSweeping( pGia, pPars, 0 );
+ Gia_ManStop( pTemp );
+ pTemp = Gia_ManOrigIdsReduce( pGia, pGia->vIdsEquiv );
+ Gia_ManStop( pTemp );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts AIG from HOP to GIA.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ConvertHopToGia_rec1( Gia_Man_t * p, Hop_Obj_t * pObj )
+{
+ assert( !Hop_IsComplement(pObj) );
+ if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+ return;
+ Abc_ConvertHopToGia_rec1( p, Hop_ObjFanin0(pObj) );
+ Abc_ConvertHopToGia_rec1( p, Hop_ObjFanin1(pObj) );
+ pObj->iData = Gia_ManHashAnd( p, Hop_ObjChild0CopyI(pObj), Hop_ObjChild1CopyI(pObj) );
+ assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+ Hop_ObjSetMarkA( pObj );
+}
+void Abc_ConvertHopToGia_rec2( Hop_Obj_t * pObj )
+{
+ assert( !Hop_IsComplement(pObj) );
+ if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) )
+ return;
+ Abc_ConvertHopToGia_rec2( Hop_ObjFanin0(pObj) );
+ Abc_ConvertHopToGia_rec2( Hop_ObjFanin1(pObj) );
+ assert( Hop_ObjIsMarkA(pObj) ); // loop detection
+ Hop_ObjClearMarkA( pObj );
+}
+int Abc_ConvertHopToGia( Gia_Man_t * p, Hop_Obj_t * pRoot )
+{
+ assert( !Hop_IsComplement(pRoot) );
+ if ( Hop_ObjIsConst1( pRoot ) )
+ return 1;
+ Abc_ConvertHopToGia_rec1( p, pRoot );
+ Abc_ConvertHopToGia_rec2( pRoot );
+ return pRoot->iData;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Add logic from pNtk to the AIG manager p.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkAigToGiaOne( Gia_Man_t * p, Abc_Ntk_t * pNtk, Vec_Int_t * vMap )
+{
+ Hop_Man_t * pHopMan;
+ Hop_Obj_t * pHopObj;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNode, * pFanin;
+ int i, k;
+ assert( Abc_NtkIsAigLogic(pNtk) );
+ pHopMan = (Hop_Man_t *)pNtk->pManFunc;
+ Hop_ManConst1(pHopMan)->iData = 1;
+ // image primary inputs
+ Abc_NtkCleanCopy( pNtk );
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ pNode->iTemp = Gia_ManCiLit(p, Vec_IntEntry(vMap, i));
+ // iterate through nodes used in the mapping
+ vNodes = Abc_NtkDfs( pNtk, 1 );
+ Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+ {
+ Abc_ObjForEachFanin( pNode, pFanin, k )
+ Hop_ManPi(pHopMan, k)->iData = pFanin->iTemp;
+ pHopObj = Hop_Regular( (Hop_Obj_t *)pNode->pData );
+ assert( Abc_ObjFaninNum(pNode) <= Hop_ManPiNum(pHopMan) );
+ if ( Hop_DagSize(pHopObj) > 0 )
+ Abc_ConvertHopToGia( p, pHopObj );
+ pNode->iTemp = Abc_LitNotCond( pHopObj->iData, Hop_IsComplement( (Hop_Obj_t *)pNode->pData ) );
+ }
+ Vec_PtrFree( vNodes );
+ // create primary outputs
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ Gia_ManAppendCo( p, Abc_ObjFanin0(pNode)->iTemp );
+}
+Gia_Man_t * Abc_NtkAigToGiaTwo( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fByName )
+{
+ Gia_Man_t * p;
+ Gia_Obj_t * pObj;
+ Abc_Obj_t * pNode;
+ Vec_Int_t * vMap1, * vMap2;
+ int i, Index = 0;
+ assert( Abc_NtkIsAigLogic(pNtk1) );
+ assert( Abc_NtkIsAigLogic(pNtk2) );
+ // find common variables
+ if ( fByName )
+ {
+ int nCommon = 0;
+ vMap1 = Vec_IntStartNatural( Abc_NtkCiNum(pNtk1) );
+ vMap2 = Vec_IntAlloc( Abc_NtkCiNum(pNtk2) );
+ Abc_NtkForEachCi( pNtk1, pNode, i )
+ pNode->iTemp = Index++;
+ assert( Index == Abc_NtkCiNum(pNtk1) );
+ Abc_NtkForEachCi( pNtk2, pNode, i )
+ {
+ int Num = Nm_ManFindIdByName( pNtk1->pManName, Abc_ObjName(pNode), ABC_OBJ_PI );
+ if ( Num < 0 )
+ Num = Nm_ManFindIdByName( pNtk1->pManName, Abc_ObjName(pNode), ABC_OBJ_BO );
+ assert( Num < 0 || Abc_ObjIsCi(Abc_NtkObj(pNtk1, Num)) );
+ if ( Num >= 0 )
+ Vec_IntPush( vMap2, Abc_NtkObj(pNtk1, Num)->iTemp ), nCommon++;
+ else
+ Vec_IntPush( vMap2, Index++ );
+ }
+ // report
+ printf( "Matched %d vars by name.", nCommon );
+ if ( nCommon != Abc_NtkCiNum(pNtk1) )
+ printf( " Netlist1 has %d unmatched vars.", Abc_NtkCiNum(pNtk1) - nCommon );
+ if ( nCommon != Abc_NtkCiNum(pNtk2) )
+ printf( " Netlist2 has %d unmatched vars.", Abc_NtkCiNum(pNtk2) - nCommon );
+ printf( "\n" );
+ }
+ else
+ {
+ vMap1 = Vec_IntStartNatural( Abc_NtkCiNum(pNtk1) );
+ vMap2 = Vec_IntStartNatural( Abc_NtkCiNum(pNtk2) );
+ Index = Abc_MaxInt( Vec_IntSize(vMap1), Vec_IntSize(vMap2) );
+ // report
+ printf( "Matched %d vars by order.", Abc_MinInt(Abc_NtkCiNum(pNtk1), Abc_NtkCiNum(pNtk2)) );
+ if ( Abc_NtkCiNum(pNtk1) < Abc_NtkCiNum(pNtk2) )
+ printf( " The last %d vars of Netlist2 are unmatched vars.", Abc_NtkCiNum(pNtk2) - Abc_NtkCiNum(pNtk1) );
+ if ( Abc_NtkCiNum(pNtk1) > Abc_NtkCiNum(pNtk2) )
+ printf( " The last %d vars of Netlist1 are unmatched vars.", Abc_NtkCiNum(pNtk1) - Abc_NtkCiNum(pNtk2) );
+ printf( "\n" );
+ }
+ // create new manager
+ p = Gia_ManStart( 10000 );
+ p->pName = Abc_UtilStrsav( Abc_NtkName(pNtk1) );
+ p->pSpec = Abc_UtilStrsav( Abc_NtkSpec(pNtk1) );
+ for ( i = 0; i < Index; i++ )
+ Gia_ManAppendCi(p);
+ // add logic
+ Gia_ManHashAlloc( p );
+ Abc_NtkAigToGiaOne( p, pNtk1, vMap1 );
+ Abc_NtkAigToGiaOne( p, pNtk2, vMap2 );
+ Gia_ManHashStop( p );
+ Vec_IntFree( vMap1 );
+ Vec_IntFree( vMap2 );
+ // add extra POs to dangling nodes
+ Gia_ManCreateValueRefs( p );
+ Gia_ManForEachAnd( p, pObj, i )
+ if ( pObj->Value == 0 )
+ Gia_ManAppendCo( p, Abc_Var2Lit(i, 0) );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collect equivalence class information.]
+
+ Description [Each class is represented as follows:
+ <num_entries><entry1><entry2>...<entryN>
+ where <entry> is nodeId with 1-bit for complement and 1-bit for network.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Abc_NtkCollectAddOne( int iNtk, int iObj, int iGiaLit, Gia_Man_t * pGia, Vec_Int_t * vGia2Cla, Vec_Int_t * vNexts[2] )
+{
+ int iRepr = Gia_ObjReprSelf( pGia, Abc_Lit2Var(iGiaLit) );
+ int Compl = Abc_LitIsCompl(iGiaLit) ^ Gia_ObjPhase(Gia_ManObj(pGia, iRepr)) ^ Gia_ObjPhase(Gia_ManObj(pGia, Abc_Lit2Var(iGiaLit)));
+ int Added = Abc_Var2Lit( Abc_Var2Lit(iObj, Compl), iNtk );
+ int Entry = Vec_IntEntry( vGia2Cla, iRepr );
+ Vec_IntWriteEntry( vNexts[iNtk], iObj, Entry );
+ Vec_IntWriteEntry( vGia2Cla, iRepr, Added );
+}
+Vec_Int_t * Abc_NtkCollectEquivClasses( Abc_Ntk_t * pNtks[2], Gia_Man_t * pGia )
+{
+ Vec_Int_t * vClass = Vec_IntAlloc( 100 );
+ Vec_Int_t * vClasses = Vec_IntAlloc( 1000 );
+ Vec_Int_t * vGia2Cla = Vec_IntStartFull( Gia_ManObjNum(pGia) ); // mapping objId into classId
+ Vec_Int_t * vNexts[2] = { Vec_IntStartFull(Abc_NtkObjNumMax(pNtks[0])), Vec_IntStartFull(Abc_NtkObjNumMax(pNtks[1])) };
+ Abc_Obj_t * pObj;
+ int n, i, k, Entry, fCompl;
+ Abc_NtkForEachCi( pNtks[0], pObj, i )
+ Abc_NtkCollectAddOne( 0, Abc_ObjId(pObj), pObj->iTemp, pGia, vGia2Cla, vNexts );
+ for ( n = 0; n < 2; n++ )
+ Abc_NtkForEachNode( pNtks[n], pObj, i )
+ Abc_NtkCollectAddOne( n, Abc_ObjId(pObj), pObj->iTemp, pGia, vGia2Cla, vNexts );
+ Vec_IntForEachEntry( vGia2Cla, Entry, i )
+ {
+ Vec_IntClear( vClass );
+ for ( ; Entry >= 0; Entry = Vec_IntEntry(vNexts[Entry&1], Entry>>2) )
+ Vec_IntPush( vClass, Entry );
+ if ( Vec_IntSize(vClass) < 2 )
+ continue;
+ Vec_IntReverseOrder( vClass );
+ fCompl = 2 & Vec_IntEntry( vClass, 0 );
+ Vec_IntForEachEntry( vClass, Entry, k )
+ Vec_IntWriteEntry( vClass, k, Entry ^ fCompl );
+ Vec_IntPush( vClasses, Vec_IntSize(vClass) );
+ Vec_IntAppend( vClasses, vClass );
+ }
+ Vec_IntFree( vGia2Cla );
+ Vec_IntFree( vNexts[0] );
+ Vec_IntFree( vNexts[1] );
+ Vec_IntFree( vClass );
+ return vClasses;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Write the output file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDumpEquivFile( char * pFileName, Vec_Int_t * vClasses, Abc_Ntk_t * pNtks[2] )
+{
+ int i, c, k, Entry;
+ FILE * pFile = fopen( pFileName, "wb" );
+ if ( pFile == NULL ) { printf( "Cannot open file %s for writing.\n", pFileName ); return; }
+ fprintf( pFile, "# Node equivalences computed by ABC for networks \"%s\" and \"%s\" on %s\n\n", Abc_NtkName(pNtks[0]), Abc_NtkName(pNtks[1]), Extra_TimeStamp() );
+ for ( i = c = 0; i < Vec_IntSize(vClasses); c++, i += 1 + Vec_IntEntry(vClasses, i) )
+ {
+ Vec_IntForEachEntryStartStop( vClasses, Entry, k, i + 1, i + 1 + Vec_IntEntry(vClasses, i) )
+ {
+ Abc_Ntk_t * pNtk = pNtks[Entry & 1];
+ char * pObjName = Abc_ObjName( Abc_NtkObj(pNtk, Entry>>2) );
+ fprintf( pFile, "%d:%s:%s%s\n", c+1, Abc_NtkName(pNtk), (Entry&2) ? "NOT:":"", pObjName );
+ }
+ fprintf( pFile, "\n" );
+ }
+ fclose( pFile );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Compute and dump equivalent name classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDumpEquiv( Abc_Ntk_t * pNtks[2], char * pFileName, int nConfs, int fByName, int fVerbose )
+{
+ //abctime clk = Abc_Clock();
+ Vec_Int_t * vClasses;
+ // derive shared AIG for the two networks
+ Gia_Man_t * pGia = Abc_NtkAigToGiaTwo( pNtks[0], pNtks[1], fByName );
+ if ( fVerbose )
+ printf( "Computing equivalences for networks \"%s\" and \"%s\" with conflict limit %d.\n", Abc_NtkName(pNtks[0]), Abc_NtkName(pNtks[1]), nConfs );
+ // compute equivalences in this AIG
+ Abc_NtkComputeGiaEquivs( pGia, nConfs, fVerbose );
+ //if ( fVerbose )
+ // Abc_PrintTime( 1, "Equivalence computation time", Abc_Clock() - clk );
+ if ( fVerbose )
+ Gia_ManPrintStats( pGia, NULL );
+ // collect equivalence class information
+ vClasses = Abc_NtkCollectEquivClasses( pNtks, pGia );
+ Gia_ManStop( pGia );
+ // dump information into the output file
+ Abc_NtkDumpEquivFile( pFileName, vClasses, pNtks );
+ Vec_IntFree( vClasses );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/base/abci/abcExact.c b/src/base/abci/abcExact.c
new file mode 100644
index 00000000..8c508b63
--- /dev/null
+++ b/src/base/abci/abcExact.c
@@ -0,0 +1,1696 @@
+/**CFile****************************************************************
+
+ FileName [abcExact.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Find minimum size networks with a SAT solver.]
+
+ Author [Mathias Soeken]
+
+ Affiliation [EPFL]
+
+ Date [Ver. 1.0. Started - July 15, 2016.]
+
+ Revision [$Id: abcFanio.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+/* This implementation is based on Exercises 477 and 478 in
+ * Donald E. Knuth TAOCP Fascicle 6 (Satisfiability) Section 7.2.2.2
+ */
+
+#include "base/abc/abc.h"
+
+#include "aig/gia/gia.h"
+#include "bool/kit/kit.h"
+#include "misc/util/utilTruth.h"
+#include "misc/vec/vecInt.h"
+#include "misc/vec/vecPtr.h"
+#include "proof/cec/cec.h"
+#include "sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static word s_Truths8[32] = {
+ ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xAAAAAAAAAAAAAAAA),
+ ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xCCCCCCCCCCCCCCCC),
+ ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xF0F0F0F0F0F0F0F0),
+ ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFF00FF00FF00FF00),
+ ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFF0000FFFF0000),
+ ABC_CONST(0xFFFFFFFF00000000), ABC_CONST(0xFFFFFFFF00000000), ABC_CONST(0xFFFFFFFF00000000), ABC_CONST(0xFFFFFFFF00000000),
+ ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFFFFFFFFFF), ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFFFFFFFFFF),
+ ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFFFFFFFFFF), ABC_CONST(0xFFFFFFFFFFFFFFFF)
+};
+
+#define ABC_EXACT_SOL_NVARS 0
+#define ABC_EXACT_SOL_NFUNC 1
+#define ABC_EXACT_SOL_NGATES 2
+
+typedef struct Ses_Man_t_ Ses_Man_t;
+struct Ses_Man_t_
+{
+ sat_solver * pSat; /* SAT solver */
+
+ word * pSpec; /* specification */
+ int bSpecInv; /* remembers whether spec was inverted for normalization */
+ int nSpecVars; /* number of variables in specification */
+ int nSpecFunc; /* number of functions to synthesize */
+ int nRows; /* number of rows in the specification (without 0) */
+ int nMaxDepth; /* maximum depth (-1 if depth is not constrained) */
+ int * pArrTimeProfile; /* arrival times of inputs (NULL if arrival times are ignored) */
+ int nArrTimeDelta; /* delta to the original arrival times (arrival times are normalized to have 0 as minimum element) */
+ int nArrTimeMax; /* maximum normalized arrival time */
+ int nBTLimit; /* conflict limit */
+ int fMakeAIG; /* create AIG instead of general network */
+ int fVerbose; /* be verbose */
+ int fVeryVerbose; /* be very verbose */
+
+ int nGates; /* number of gates */
+
+ int nSimVars; /* number of simulation vars x(i, t) */
+ int nOutputVars; /* number of output variables g(h, i) */
+ int nGateVars; /* number of gate variables f(i, p, q) */
+ int nSelectVars; /* number of select variables s(i, j, k) */
+ int nDepthVars; /* number of depth variables d(i, j) */
+
+ int nOutputOffset; /* offset where output variables start */
+ int nGateOffset; /* offset where gate variables start */
+ int nSelectOffset; /* offset where select variables start */
+ int nDepthOffset; /* offset where depth variables start */
+
+ abctime timeSat; /* SAT runtime */
+ abctime timeSatSat; /* SAT runtime (sat instance) */
+ abctime timeSatUnsat; /* SAT runtime (unsat instance) */
+ abctime timeTotal; /* all runtime */
+};
+
+/***********************************************************************
+
+ Synopsis [Store truth tables based on normalized arrival times.]
+
+***********************************************************************/
+
+// The hash table is a list of pointers to Ses_TruthEntry_t elements, which
+// are arranged in a linked list, each of which pointing to a linked list
+// of Ses_TimesEntry_t elements which contain the char* representation of the
+// optimum netlist according to then normalized arrival times:
+
+typedef struct Ses_TimesEntry_t_ Ses_TimesEntry_t;
+struct Ses_TimesEntry_t_
+{
+ int pArrTimeProfile[8]; /* normalized arrival time profile */
+ Ses_TimesEntry_t * next; /* linked list pointer */
+ char * pNetwork; /* pointer to char array representation of optimum network */
+};
+
+typedef struct Ses_TruthEntry_t_ Ses_TruthEntry_t;
+struct Ses_TruthEntry_t_
+{
+ word pTruth[4]; /* truth table for comparison */
+ int nVars; /* number of variables */
+ Ses_TruthEntry_t * next; /* linked list pointer */
+ Ses_TimesEntry_t * head; /* pointer to head of sub list with arrival times */
+};
+
+#define SES_STORE_TABLE_SIZE 1024
+typedef struct Ses_Store_t_ Ses_Store_t;
+struct Ses_Store_t_
+{
+ int fMakeAIG; /* create AIG instead of general network */
+ int fVerbose; /* be verbose */
+ int nBTLimit; /* conflict limit */
+ int nEntriesCount; /* number of entries */
+ Ses_TruthEntry_t * pEntries[SES_STORE_TABLE_SIZE]; /* hash table for truth table entries */
+
+ unsigned long nCutCount;
+ unsigned long pCutCount[9];
+ unsigned long nCacheHit;
+};
+
+static Ses_Store_t * s_pSesStore = NULL;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_NormalizeArrivalTimes( int * pArrTimeProfile, int nVars, int * maxNormalized )
+{
+ int * p = pArrTimeProfile, * pEnd = pArrTimeProfile + nVars;
+ int delta = *p;
+
+ while ( ++p < pEnd )
+ if ( *p < delta )
+ delta = *p;
+
+ *maxNormalized = 0;
+ p = pArrTimeProfile;
+ while ( p < pEnd )
+ {
+ *p -= delta;
+ if ( *p > *maxNormalized )
+ *maxNormalized = *p;
+ ++p;
+ }
+
+ *maxNormalized += 1;
+
+ return delta;
+}
+
+static inline Ses_Store_t * Ses_StoreAlloc( int nBTLimit, int fMakeAIG, int fVerbose )
+{
+ Ses_Store_t * pStore = ABC_CALLOC( Ses_Store_t, 1 );
+ pStore->fMakeAIG = fMakeAIG;
+ pStore->fVerbose = fVerbose;
+ pStore->nBTLimit = nBTLimit;
+ pStore->nEntriesCount = 0;
+ memset( pStore->pEntries, 0, SES_STORE_TABLE_SIZE );
+
+ pStore->nCutCount = 0;
+ memset( pStore->pCutCount, 0, 9 );
+ pStore->nCacheHit = 0;
+
+ return pStore;
+}
+
+static inline void Ses_StoreClean( Ses_Store_t * pStore )
+{
+ int i;
+ Ses_TruthEntry_t * pTEntry, * pTEntry2;
+ Ses_TimesEntry_t * pTiEntry, * pTiEntry2;
+
+ for ( i = 0; i < SES_STORE_TABLE_SIZE; ++i )
+ if ( pStore->pEntries[i] )
+ {
+ pTEntry = pStore->pEntries[i];
+
+ while ( pTEntry )
+ {
+ pTiEntry = pTEntry->head;
+ while ( pTiEntry )
+ {
+ ABC_FREE( pTiEntry->pNetwork );
+ pTiEntry2 = pTiEntry;
+ pTiEntry = pTiEntry->next;
+ ABC_FREE( pTiEntry2 );
+ }
+ pTEntry2 = pTEntry;
+ pTEntry = pTEntry->next;
+ ABC_FREE( pTEntry2 );
+ }
+ }
+
+ ABC_FREE( pStore );
+}
+
+static inline int Ses_StoreTableHash( word * pTruth, int nVars )
+{
+ static int s_Primes[4] = { 1291, 1699, 1999, 2357 };
+ int i;
+ unsigned uHash = 0;
+ for ( i = 0; i < Kit_TruthWordNum( nVars ); ++i )
+ uHash ^= pTruth[i] * s_Primes[i & 0xf];
+ return (int)(uHash % SES_STORE_TABLE_SIZE );
+}
+
+static inline int Ses_StoreTruthEqual( Ses_TruthEntry_t * pEntry, word * pTruth, int nVars )
+{
+ int i;
+
+ if ( pEntry->nVars != nVars )
+ return 0;
+
+ for ( i = 0; i < Kit_TruthWordNum( nVars ); ++i )
+ if ( pEntry->pTruth[i] != pTruth[i] )
+ return 0;
+ return 1;
+}
+
+static inline void Ses_StoreTruthCopy( Ses_TruthEntry_t * pEntry, word * pTruthSrc, int nVars )
+{
+ int i;
+ pEntry->nVars = nVars;
+ for ( i = 0; i < Kit_TruthWordNum( nVars ); ++i )
+ pEntry->pTruth[i] = pTruthSrc[i];
+}
+
+static inline int Ses_StoreTimesEqual( int * pTimes1, int * pTimes2, int nVars )
+{
+ int i;
+ for ( i = 0; i < nVars; ++i )
+ if ( pTimes1[i] != pTimes2[i] )
+ return 0;
+ return 1;
+}
+
+static inline void Ses_StoreTimesCopy( int * pTimesDest, int * pTimesSrc, int nVars )
+{
+ int i;
+ for ( i = 0; i < nVars; ++i )
+ pTimesDest[i] = pTimesSrc[i];
+}
+
+// pArrTimeProfile is not normalized
+// returns 1 if and only if a new TimesEntry has been created
+int Ses_StoreAddEntry( Ses_Store_t * pStore, word * pTruth, int nVars, int * pArrTimeProfile, char * pSol )
+{
+ int i, nDelta, maxNormalized, key, fAdded;
+ Ses_TruthEntry_t * pTEntry;
+ Ses_TimesEntry_t * pTiEntry;
+
+ nDelta = Abc_NormalizeArrivalTimes( pArrTimeProfile, nVars, &maxNormalized );
+
+ key = Ses_StoreTableHash( pTruth, nVars );
+ pTEntry = pStore->pEntries[key];
+
+ /* does truth table already exist? */
+ while ( pTEntry )
+ {
+ if ( Ses_StoreTruthEqual( pTEntry, pTruth, nVars ) )
+ break;
+ else
+ pTEntry = pTEntry->next;
+ }
+
+ /* entry does not yet exist, so create new one and enqueue */
+ if ( !pTEntry )
+ {
+ pTEntry = ABC_CALLOC( Ses_TruthEntry_t, 1 );
+ Ses_StoreTruthCopy( pTEntry, pTruth, nVars );
+ pTEntry->next = pStore->pEntries[key];
+ pStore->pEntries[key] = pTEntry;
+ }
+
+ /* does arrival time already exist? */
+ pTiEntry = pTEntry->head;
+ while ( pTiEntry )
+ {
+ if ( Ses_StoreTimesEqual( pArrTimeProfile, pTiEntry->pArrTimeProfile, nVars ) )
+ break;
+ else
+ pTiEntry = pTiEntry->next;
+ }
+
+ /* entry does not yet exist, so create new one and enqueue */
+ if ( !pTiEntry )
+ {
+ pTiEntry = ABC_CALLOC( Ses_TimesEntry_t, 1 );
+ Ses_StoreTimesCopy( pTiEntry->pArrTimeProfile, pArrTimeProfile, nVars );
+ pTiEntry->pNetwork = pSol;
+ pTiEntry->next = pTEntry->head;
+ pTEntry->head = pTiEntry;
+
+ /* item has been added */
+ fAdded = 1;
+ pStore->nEntriesCount++;
+ }
+ else
+ /* item was already present */
+ fAdded = 0;
+
+ for ( i = 0; i < nVars; ++i )
+ pArrTimeProfile[i] += nDelta;
+ return fAdded;
+}
+
+// pArrTimeProfile is not normalized
+// returns 0 if no solution was found
+char * Ses_StoreGetEntry( Ses_Store_t * pStore, word * pTruth, int nVars, int * pArrTimeProfile )
+{
+ int i, nDelta, maxNormalized, key;
+ Ses_TruthEntry_t * pTEntry;
+ Ses_TimesEntry_t * pTiEntry;
+
+ key = Ses_StoreTableHash( pTruth, nVars );
+ pTEntry = pStore->pEntries[key];
+
+ /* find truth table entry */
+ while ( pTEntry )
+ {
+ if ( Ses_StoreTruthEqual( pTEntry, pTruth, nVars ) )
+ break;
+ else
+ pTEntry = pTEntry->next;
+ }
+
+ /* no entry found? */
+ if ( !pTEntry )
+ return 0;
+
+ nDelta = Abc_NormalizeArrivalTimes( pArrTimeProfile, nVars, &maxNormalized );
+
+ /* find times entry */
+ pTiEntry = pTEntry->head;
+ while ( pTiEntry )
+ {
+ if ( Ses_StoreTimesEqual( pArrTimeProfile, pTiEntry->pArrTimeProfile, nVars ) )
+ break;
+ else
+ pTiEntry = pTiEntry->next;
+ }
+
+ for ( i = 0; i < nVars; ++i )
+ pArrTimeProfile[i] += nDelta;
+
+ /* no entry found? */
+ if ( !pTiEntry )
+ return 0;
+
+ return pTiEntry->pNetwork;
+}
+
+static void Ses_StoreWrite( Ses_Store_t * pStore, const char * pFilename )
+{
+ int i;
+ Ses_TruthEntry_t * pTEntry;
+ Ses_TimesEntry_t * pTiEntry;
+ FILE * pFile;
+
+ pFile = fopen( pFilename, "wb" );
+ if (pFile == NULL)
+ {
+ printf( "cannot open file \"%s\" for writing\n", pFilename );
+ return;
+ }
+
+ fwrite( &pStore->nEntriesCount, sizeof( int ), 1, pFile );
+
+ for ( i = 0; i < SES_STORE_TABLE_SIZE; ++i )
+ if ( pStore->pEntries[i] )
+ {
+ pTEntry = pStore->pEntries[i];
+
+ while ( pTEntry )
+ {
+ pTiEntry = pTEntry->head;
+ while ( pTiEntry )
+ {
+ fwrite( pTEntry->pTruth, sizeof( word ), 4, pFile );
+ fwrite( &pTEntry->nVars, sizeof( int ), 1, pFile );
+ fwrite( pTiEntry->pArrTimeProfile, sizeof( int ), 8, pFile );
+ fwrite( pTiEntry->pNetwork, sizeof( char ), 3 + 4 * pTiEntry->pNetwork[ABC_EXACT_SOL_NGATES] + 2 + pTiEntry->pNetwork[ABC_EXACT_SOL_NVARS], pFile );
+ pTiEntry = pTiEntry->next;
+ }
+ pTEntry = pTEntry->next;
+ }
+ }
+
+
+ fclose( pFile );
+}
+
+static void Ses_StoreRead( Ses_Store_t * pStore, const char * pFilename )
+{
+ int i, nEntries;
+ word pTruth[4];
+ int nVars;
+ int pArrTimeProfile[8];
+ char pHeader[3];
+ char * pNetwork;
+ FILE * pFile;
+ int value;
+
+ pFile = fopen( pFilename, "rb" );
+ if (pFile == NULL)
+ {
+ printf( "cannot open file \"%s\" for reading\n", pFilename );
+ return;
+ }
+
+ value = fread( &nEntries, sizeof( int ), 1, pFile );
+
+ for ( i = 0; i < nEntries; ++i )
+ {
+ value = fread( pTruth, sizeof( word ), 4, pFile );
+ value = fread( &nVars, sizeof( int ), 1, pFile );
+ value = fread( pArrTimeProfile, sizeof( int ), 8, pFile );
+ value = fread( pHeader, sizeof( char ), 3, pFile );
+
+ pNetwork = ABC_CALLOC( char, 3 + 4 * pHeader[ABC_EXACT_SOL_NGATES] + 2 + pHeader[ABC_EXACT_SOL_NVARS] );
+ pNetwork[0] = pHeader[0];
+ pNetwork[1] = pHeader[1];
+ pNetwork[2] = pHeader[2];
+
+ value = fread( pNetwork + 3, sizeof( char ), 4 * pHeader[ABC_EXACT_SOL_NGATES] + 2 + pHeader[ABC_EXACT_SOL_NVARS], pFile );
+
+ Ses_StoreAddEntry( pStore, pTruth, nVars, pArrTimeProfile, pNetwork );
+ }
+
+ fclose( pFile );
+}
+
+static inline Ses_Man_t * Ses_ManAlloc( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrTimeProfile, int fMakeAIG, int fVerbose )
+{
+ int h, i;
+
+ Ses_Man_t * p = ABC_CALLOC( Ses_Man_t, 1 );
+ p->pSat = NULL;
+ p->bSpecInv = 0;
+ for ( h = 0; h < nFunc; ++h )
+ if ( pTruth[h << 2] & 1 )
+ {
+ for ( i = 0; i < 4; ++i )
+ pTruth[(h << 2) + i] = ~pTruth[(h << 2) + i];
+ p->bSpecInv |= ( 1 << h );
+ }
+ p->pSpec = pTruth;
+ p->nSpecVars = nVars;
+ p->nSpecFunc = nFunc;
+ p->nRows = ( 1 << nVars ) - 1;
+ p->nMaxDepth = nMaxDepth;
+ p->pArrTimeProfile = nMaxDepth >= 0 ? pArrTimeProfile : NULL;
+ if ( p->pArrTimeProfile )
+ p->nArrTimeDelta = Abc_NormalizeArrivalTimes( p->pArrTimeProfile, nVars, &p->nArrTimeMax );
+ else
+ p->nArrTimeDelta = p->nArrTimeMax = 0;
+ p->fMakeAIG = fMakeAIG;
+ p->nBTLimit = nMaxDepth >= 0 ? 50000 : 0;
+ p->fVerbose = fVerbose;
+ p->fVeryVerbose = 0;
+
+ return p;
+}
+
+static inline void Ses_ManClean( Ses_Man_t * pSes )
+{
+ int h, i;
+ for ( h = 0; h < pSes->nSpecFunc; ++h )
+ if ( ( pSes->bSpecInv >> h ) & 1 )
+ for ( i = 0; i < 4; ++i )
+ pSes->pSpec[(h << 2) + i] = ~( pSes->pSpec[(h << 2) + i] );
+
+ if ( pSes->pArrTimeProfile )
+ for ( i = 0; i < pSes->nSpecVars; ++i )
+ pSes->pArrTimeProfile[i] += pSes->nArrTimeDelta;
+
+ if ( pSes->pSat )
+ sat_solver_delete( pSes->pSat );
+
+ ABC_FREE( pSes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Access variables based on indexes.]
+
+***********************************************************************/
+static inline int Ses_ManSimVar( Ses_Man_t * pSes, int i, int t )
+{
+ assert( i < pSes->nGates );
+ assert( t < pSes->nRows );
+
+ return pSes->nRows * i + t;
+}
+
+static inline int Ses_ManOutputVar( Ses_Man_t * pSes, int h, int i )
+{
+ assert( h < pSes->nSpecFunc );
+ assert( i < pSes->nGates );
+
+ return pSes->nOutputOffset + pSes->nGates * h + i;
+}
+
+static inline int Ses_ManGateVar( Ses_Man_t * pSes, int i, int p, int q )
+{
+ assert( i < pSes->nGates );
+ assert( p < 2 );
+ assert( q < 2 );
+ assert( p > 0 || q > 0 );
+
+ return pSes->nGateOffset + i * 3 + ( p << 1 ) + q - 1;
+}
+
+static inline int Ses_ManSelectVar( Ses_Man_t * pSes, int i, int j, int k )
+{
+ int a;
+ int offset;
+
+ assert( i < pSes->nGates );
+ assert( k < pSes->nSpecVars + i );
+ assert( j < k );
+
+ offset = pSes->nSelectOffset;
+ for ( a = pSes->nSpecVars; a < pSes->nSpecVars + i; ++a )
+ offset += a * ( a - 1 ) / 2;
+
+ return offset + ( -j * ( 1 + j - 2 * ( pSes->nSpecVars + i ) ) ) / 2 + ( k - j - 1 );
+}
+
+static inline int Ses_ManDepthVar( Ses_Man_t * pSes, int i, int j )
+{
+ assert( i < pSes->nGates );
+ assert( j <= pSes->nArrTimeMax + i );
+
+ return pSes->nDepthOffset + i * pSes->nArrTimeMax + ( ( i * ( i + 1 ) ) / 2 ) + j;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Setup variables to find network with nGates gates.]
+
+***********************************************************************/
+static void Ses_ManCreateVars( Ses_Man_t * pSes, int nGates )
+{
+ int i;
+
+ if ( pSes->fVerbose )
+ {
+ printf( "create variables for network with %d functions over %d variables and %d gates\n", pSes->nSpecFunc, pSes->nSpecVars, nGates );
+ }
+
+ pSes->nGates = nGates;
+ pSes->nSimVars = nGates * pSes->nRows;
+ pSes->nOutputVars = pSes->nSpecFunc * nGates;
+ pSes->nGateVars = nGates * 3;
+ pSes->nSelectVars = 0;
+ for ( i = pSes->nSpecVars; i < pSes->nSpecVars + nGates; ++i )
+ pSes->nSelectVars += ( i * ( i - 1 ) ) / 2;
+ pSes->nDepthVars = pSes->nMaxDepth > 0 ? nGates * pSes->nArrTimeMax + ( nGates * ( nGates + 1 ) ) / 2 : 0;
+
+ pSes->nOutputOffset = pSes->nSimVars;
+ pSes->nGateOffset = pSes->nSimVars + pSes->nOutputVars;
+ pSes->nSelectOffset = pSes->nSimVars + pSes->nOutputVars + pSes->nGateVars;
+ pSes->nDepthOffset = pSes->nSimVars + pSes->nOutputVars + pSes->nGateVars + pSes->nSelectVars;
+
+ if ( pSes->pSat )
+ sat_solver_delete( pSes->pSat );
+ pSes->pSat = sat_solver_new();
+ sat_solver_setnvars( pSes->pSat, pSes->nSimVars + pSes->nOutputVars + pSes->nGateVars + pSes->nSelectVars + pSes->nDepthVars );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create clauses.]
+
+***********************************************************************/
+static inline void Ses_ManCreateMainClause( Ses_Man_t * pSes, int t, int i, int j, int k, int a, int b, int c )
+{
+ int pLits[5], ctr = 0, value;
+
+ pLits[ctr++] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 1 );
+ pLits[ctr++] = Abc_Var2Lit( Ses_ManSimVar( pSes, i, t ), a );
+
+ if ( j < pSes->nSpecVars )
+ {
+ if ( Abc_TtGetBit( s_Truths8 + ( j << 2 ), t + 1 ) != b ) /* 1 in clause, we can omit the clause */
+ return;
+ }
+ else
+ pLits[ctr++] = Abc_Var2Lit( Ses_ManSimVar( pSes, j - pSes->nSpecVars, t ), b );
+
+ if ( k < pSes->nSpecVars )
+ {
+ if ( Abc_TtGetBit( s_Truths8 + ( k << 2 ), t + 1 ) != c ) /* 1 in clause, we can omit the clause */
+ return;
+ }
+ else
+ pLits[ctr++] = Abc_Var2Lit( Ses_ManSimVar( pSes, k - pSes->nSpecVars, t ), c );
+
+ if ( b > 0 || c > 0 )
+ pLits[ctr++] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, b, c ), 1 - a );
+
+ value = sat_solver_addclause( pSes->pSat, pLits, pLits + ctr );
+ assert( value );
+}
+
+static int Ses_ManCreateClauses( Ses_Man_t * pSes )
+{
+ extern int Extra_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 );
+
+ int h, i, j, k, t, ii, jj, kk, p, q, d;
+ int pLits[3];
+ Vec_Int_t * vLits;
+
+ for ( t = 0; t < pSes->nRows; ++t )
+ for ( i = 0; i < pSes->nGates; ++i )
+ {
+ /* main clauses */
+ for ( j = 0; j < pSes->nSpecVars + i; ++j )
+ for ( k = j + 1; k < pSes->nSpecVars + i; ++k )
+ {
+ Ses_ManCreateMainClause( pSes, t, i, j, k, 0, 0, 1 );
+ Ses_ManCreateMainClause( pSes, t, i, j, k, 0, 1, 0 );
+ Ses_ManCreateMainClause( pSes, t, i, j, k, 0, 1, 1 );
+ Ses_ManCreateMainClause( pSes, t, i, j, k, 1, 0, 0 );
+ Ses_ManCreateMainClause( pSes, t, i, j, k, 1, 0, 1 );
+ Ses_ManCreateMainClause( pSes, t, i, j, k, 1, 1, 0 );
+ Ses_ManCreateMainClause( pSes, t, i, j, k, 1, 1, 1 );
+ }
+
+ /* output clauses */
+ for ( h = 0; h < pSes->nSpecFunc; ++h )
+ {
+ pLits[0] = Abc_Var2Lit( Ses_ManOutputVar( pSes, h, i ), 1 );
+ pLits[1] = Abc_Var2Lit( Ses_ManSimVar( pSes, i, t ), 1 - Abc_TtGetBit( &pSes->pSpec[h << 2], t + 1 ) );
+ assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 2 ) );
+ }
+ }
+
+ /* some output is selected */
+ for ( h = 0; h < pSes->nSpecFunc; ++h )
+ {
+ vLits = Vec_IntAlloc( pSes->nGates );
+ for ( i = 0; i < pSes->nGates; ++i )
+ Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManOutputVar( pSes, h, i ), 0 ) );
+ assert( sat_solver_addclause( pSes->pSat, Vec_IntArray( vLits ), Vec_IntLimit( vLits ) ) );
+ Vec_IntFree( vLits );
+ }
+
+ /* each gate has two operands */
+ for ( i = 0; i < pSes->nGates; ++i )
+ {
+ vLits = Vec_IntAlloc( ( ( pSes->nSpecVars + i ) * ( pSes->nSpecVars + i - 1 ) ) / 2 );
+ for ( j = 0; j < pSes->nSpecVars + i; ++j )
+ for ( k = j + 1; k < pSes->nSpecVars + i; ++k )
+ Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 0 ) );
+ assert( sat_solver_addclause( pSes->pSat, Vec_IntArray( vLits ), Vec_IntLimit( vLits ) ) );
+ Vec_IntFree( vLits );
+ }
+
+ /* only AIG */
+ if ( pSes->fMakeAIG )
+ {
+ for ( i = 0; i < pSes->nGates; ++i )
+ {
+ /* not 2 ones */
+ pLits[0] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 0, 1 ), 1 );
+ pLits[1] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 0 ), 1 );
+ pLits[2] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 1 ), 0 );
+ assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ) );
+
+ pLits[0] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 0, 1 ), 1 );
+ pLits[1] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 0 ), 0 );
+ pLits[2] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 1 ), 1 );
+ assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ) );
+
+ pLits[0] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 0, 1 ), 0 );
+ pLits[1] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 0 ), 1 );
+ pLits[2] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 1 ), 1 );
+ assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ) );
+ }
+ }
+
+ /* EXTRA clauses: use gate i at least once */
+ for ( i = 0; i < pSes->nGates; ++i )
+ {
+ vLits = Vec_IntAlloc( 0 );
+ for ( h = 0; h < pSes->nSpecFunc; ++h )
+ Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManOutputVar( pSes, h, i ), 0 ) );
+ for ( ii = i + 1; ii < pSes->nGates; ++ii )
+ {
+ for ( j = 0; j < pSes->nSpecVars + i; ++j )
+ Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManSelectVar( pSes, ii, j, pSes->nSpecVars + i ), 0 ) );
+ for ( j = pSes->nSpecVars + i + 1; j < pSes->nSpecVars + ii; ++j )
+ Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManSelectVar( pSes, ii, pSes->nSpecVars + i, j ), 0 ) );
+ }
+ assert( sat_solver_addclause( pSes->pSat, Vec_IntArray( vLits ), Vec_IntLimit( vLits ) ) );
+ Vec_IntFree( vLits );
+ }
+
+ /* EXTRA clauses: co-lexicographic order */
+ for ( i = 0; i < pSes->nGates - 1; ++i )
+ {
+ for ( k = 2; k < pSes->nSpecVars + i; ++k )
+ {
+ for ( j = 1; j < k; ++j )
+ for ( jj = 0; jj < j; ++jj )
+ {
+ pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 1 );
+ pLits[1] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i + 1, jj, k ), 1 );
+ }
+
+ for ( j = 0; j < k; ++j )
+ for ( kk = 1; kk < k; ++kk )
+ for ( jj = 0; jj < kk; ++jj )
+ {
+ pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 1 );
+ pLits[1] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i + 1, jj, kk ), 1 );
+ }
+ }
+ }
+
+ /* EXTRA clauses: symmetric variables */
+ if ( pSes->nSpecFunc == 1 ) /* only check if there is one output function */
+ for ( q = 1; q < pSes->nSpecVars; ++q )
+ for ( p = 0; p < q; ++p )
+ if ( Extra_TruthVarsSymm( (unsigned*)( &pSes->pSpec[h << 2] ), pSes->nSpecVars, p, q ) )
+ {
+ if ( pSes->fVeryVerbose )
+ printf( "variables %d and %d are symmetric\n", p, q );
+ for ( i = 0; i < pSes->nGates; ++i )
+ for ( j = 0; j < q; ++j )
+ {
+ if ( j == p ) continue;
+
+ vLits = Vec_IntAlloc( 0 );
+ Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, q ), 1 ) );
+ for ( ii = 0; ii < i; ++ii )
+ for ( kk = 1; kk < pSes->nSpecVars + ii; ++kk )
+ for ( jj = 0; jj < kk; ++jj )
+ if ( jj == p || kk == p )
+ Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManSelectVar( pSes, ii, jj, kk ), 0 ) );
+ assert( sat_solver_addclause( pSes->pSat, Vec_IntArray( vLits ), Vec_IntLimit( vLits ) ) );
+ Vec_IntFree( vLits );
+ }
+ }
+
+ /* DEPTH clauses */
+ if ( pSes->nMaxDepth > 0 )
+ {
+ for ( i = 0; i < pSes->nGates; ++i )
+ {
+ /* propagate depths from children */
+ for ( k = 1; k < i; ++k )
+ for ( j = 0; j < k; ++j )
+ {
+ pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, pSes->nSpecVars + j, pSes->nSpecVars + k ), 1 );
+ for ( jj = 0; jj <= pSes->nArrTimeMax + j; ++jj )
+ {
+ pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, j, jj ), 1 );
+ pLits[2] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, jj + 1 ), 0 );
+ assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ) );
+ }
+ }
+
+ for ( k = 0; k < i; ++k )
+ for ( j = 0; j < pSes->nSpecVars + k; ++j )
+ {
+ pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, pSes->nSpecVars + k ), 1 );
+ for ( kk = 0; kk <= pSes->nArrTimeMax + k; ++kk )
+ {
+ pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, k, kk ), 1 );
+ pLits[2] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, kk + 1 ), 0 );
+ assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ) );
+ }
+ }
+
+ /* propagate depths from arrival times at PIs */
+ if ( pSes->pArrTimeProfile )
+ {
+ for ( k = 1; k < pSes->nSpecVars + i; ++k )
+ for ( j = 0; j < ( ( k < pSes->nSpecVars ) ? k : pSes->nSpecVars ); ++j )
+ {
+ d = pSes->pArrTimeProfile[j];
+ if ( k < pSes->nSpecVars && pSes->pArrTimeProfile[k] > d )
+ d = pSes->pArrTimeProfile[k];
+
+ pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 1 );
+ pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, d + 1 ), 0 );
+ assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 2 ) );
+ }
+ }
+ else
+ {
+ /* arrival times are 0 */
+ pLits[0] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, 0 ), 0 );
+ assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 1 ) );
+ }
+
+ /* reverse order encoding of depth variables */
+ for ( j = 1; j <= pSes->nArrTimeMax + i; ++j )
+ {
+ pLits[0] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, j ), 1 );
+ pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, j - 1 ), 0 );
+ assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 2 ) );
+ }
+
+ /* constrain maximum depth */
+ if ( pSes->nMaxDepth < pSes->nArrTimeMax + i )
+ for ( h = 0; h < pSes->nSpecFunc; ++h )
+ {
+ pLits[0] = Abc_Var2Lit( Ses_ManOutputVar( pSes, h, i ), 1 );
+ pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, pSes->nMaxDepth ), 1 );
+ if ( !sat_solver_addclause( pSes->pSat, pLits, pLits + 2 ) )
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Solve.]
+
+***********************************************************************/
+static inline int Ses_ManSolve( Ses_Man_t * pSes )
+{
+ int status;
+ abctime timeStart, timeDelta;
+
+ if ( pSes->fVeryVerbose )
+ {
+ printf( "solve SAT instance with %d clauses and %d variables\n", sat_solver_nclauses( pSes->pSat ), sat_solver_nvars( pSes->pSat ) );
+ }
+
+ timeStart = Abc_Clock();
+ status = sat_solver_solve( pSes->pSat, NULL, NULL, pSes->nBTLimit, 0, 0, 0 );
+ timeDelta = Abc_Clock() - timeStart;
+
+ pSes->timeSat += timeDelta;
+
+ if ( status == l_True )
+ {
+ pSes->timeSatSat += timeDelta;
+ return 1;
+ }
+ else if ( status == l_False )
+ {
+ pSes->timeSatUnsat += timeDelta;
+ return 0;
+ }
+ else
+ {
+ if ( pSes->fVerbose )
+ {
+ printf( "resource limit reached\n" );
+ }
+ return 2;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Extract solution.]
+
+***********************************************************************/
+// char is an array of short integers that stores the synthesized network
+// using the following format
+// | nvars | nfunc | ngates | gate[1] | ... | gate[ngates] | func[1] | .. | func[nfunc] |
+// nvars: integer with number of variables
+// nfunc: integer with number of functions
+// ngates: integer with number of gates
+// gate[i]: | op | nfanin | fanin[1] | ... | fanin[nfanin] |
+// op: integer of gate's truth table (divided by 2, because gate is normal)
+// nfanin[i]: integer with number of fanins
+// fanin: integer to primary input or other gate
+// func[i]: | fanin | delay | pin[1] | ... | pin[nvars] |
+// fanin: integer as literal to some gate (not primary input), can be complemented
+// delay: maximum delay to output (taking arrival times into account, not normalized) or 0 if not specified
+// pin[i]: pin to pin delay to input i or 0 if not specified or if there is no connection to input i
+// NOTE: since outputs can only point to gates, delay and pin-to-pin times cannot be 0
+static char * Ses_ManExtractSolution( Ses_Man_t * pSes )
+{
+ int nSol, h, i, j, k, l, aj, ak, d, nOp;
+ char * pSol, * p;
+ int * pPerm = NULL; /* will be a 2d array [i][l] where is is gate id and l is PI id */
+
+ /* compute length of solution, for now all gates have 2 inputs */
+ nSol = 3 + pSes->nGates * 4 + pSes->nSpecFunc * ( 2 + pSes->nSpecVars );
+
+ p = pSol = ABC_CALLOC( char, nSol );
+
+ /* header */
+ *p++ = pSes->nSpecVars;
+ *p++ = pSes->nSpecFunc;
+ *p++ = pSes->nGates;
+
+ /* gates */
+ for ( i = 0; i < pSes->nGates; ++i )
+ {
+ nOp = sat_solver_var_value( pSes->pSat, Ses_ManGateVar( pSes, i, 0, 1 ) );
+ nOp |= sat_solver_var_value( pSes->pSat, Ses_ManGateVar( pSes, i, 1, 0 ) ) << 1;
+ nOp |= sat_solver_var_value( pSes->pSat, Ses_ManGateVar( pSes, i, 1, 1 ) ) << 2;
+
+ *p++ = nOp;
+ *p++ = 2;
+
+ if ( pSes->fVeryVerbose )
+ printf( "add gate %d with operation %d", pSes->nSpecVars + i, nOp );
+
+ for ( k = 0; k < pSes->nSpecVars + i; ++k )
+ for ( j = 0; j < k; ++j )
+ if ( sat_solver_var_value( pSes->pSat, Ses_ManSelectVar( pSes, i, j, k ) ) )
+ {
+ if ( pSes->fVeryVerbose )
+ printf( " and operands %d and %d", j, k );
+ *p++ = j;
+ *p++ = k;
+ break;
+ }
+
+ if ( pSes->fVeryVerbose )
+ {
+ if ( pSes->nMaxDepth > 0 )
+ {
+ printf( " and depth vector " );
+ for ( j = 0; j <= pSes->nArrTimeMax + i; ++j )
+ printf( "%d", sat_solver_var_value( pSes->pSat, Ses_ManDepthVar( pSes, i, j ) ) );
+ }
+ printf( "\n" );
+ }
+ }
+
+ /* pin-to-pin delay */
+ if ( pSes->nMaxDepth != -1 )
+ {
+ pPerm = ABC_CALLOC( int, pSes->nGates * pSes->nSpecVars );
+ for ( i = 0; i < pSes->nGates; ++i )
+ {
+ /* since all gates are binary for now */
+ j = pSol[3 + i * 4 + 2];
+ k = pSol[3 + i * 4 + 3];
+
+ for ( l = 0; l < pSes->nSpecVars; ++l )
+ {
+ /* pin-to-pin delay to input l of child nodes */
+ aj = j < pSes->nSpecVars ? 0 : pPerm[(j - pSes->nSpecVars) * pSes->nSpecVars + l];
+ ak = k < pSes->nSpecVars ? 0 : pPerm[(k - pSes->nSpecVars) * pSes->nSpecVars + l];
+
+ if ( aj == 0 && ak == 0 )
+ pPerm[i * pSes->nSpecVars + l] = ( l == j || l == k ) ? 1 : 0;
+ else
+ pPerm[i * pSes->nSpecVars + l] = Abc_MaxInt( aj, ak ) + 1;
+ }
+ }
+ }
+
+ /* outputs */
+ for ( h = 0; h < pSes->nSpecFunc; ++h )
+ for ( i = 0; i < pSes->nGates; ++i )
+ if ( sat_solver_var_value( pSes->pSat, Ses_ManOutputVar( pSes, h, i ) ) )
+ {
+ *p++ = Abc_Var2Lit( i, ( pSes->bSpecInv >> h ) & 1 );
+ d = 0;
+ if ( pSes->nMaxDepth != -1 )
+ while ( d < pSes->nArrTimeMax + i && sat_solver_var_value( pSes->pSat, Ses_ManDepthVar( pSes, i, d ) ) )
+ ++d;
+ *p++ = d + pSes->nArrTimeDelta;
+ if ( pSes->fVeryVerbose )
+ printf( "output %d points to %d and has normalized delay %d\n", h, i, d );
+ for ( l = 0; l < pSes->nSpecVars; ++l )
+ {
+ d = ( pSes->nMaxDepth != -1 ) ? pPerm[i * pSes->nSpecVars + l] : 0;
+ if ( pSes->fVeryVerbose )
+ printf( " pin-to-pin arrival time from input %d is %d\n", l, d );
+ *p++ = d;
+ }
+ }
+
+ /* pin-to-pin delays */
+ if ( pSes->nMaxDepth != -1 )
+ ABC_FREE( pPerm );
+
+ /* have we used all the fields? */
+ assert( ( p - pSol ) == nSol );
+
+ return pSol;
+}
+
+static Abc_Ntk_t * Ses_ManExtractNtk( char const * pSol )
+{
+ int h, i;
+ char const * p;
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pObj;
+ Vec_Ptr_t * pGates, * vNames;
+ char pGateTruth[5];
+ char * pSopCover;
+
+ pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 );
+ pNtk->pName = Extra_UtilStrsav( "exact" );
+ pGates = Vec_PtrAlloc( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NGATES] );
+ pGateTruth[3] = '0';
+ pGateTruth[4] = '\0';
+ vNames = Abc_NodeGetFakeNames( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NFUNC] );
+
+ /* primary inputs */
+ Vec_PtrPush( pNtk->vObjs, NULL );
+ for ( i = 0; i < pSol[ABC_EXACT_SOL_NVARS]; ++i )
+ {
+ pObj = Abc_NtkCreatePi( pNtk );
+ Abc_ObjAssignName( pObj, (char*)Vec_PtrEntry( vNames, i ), NULL );
+ Vec_PtrPush( pGates, pObj );
+ }
+
+ /* gates */
+ p = pSol + 3;
+ for ( i = 0; i < pSol[ABC_EXACT_SOL_NGATES]; ++i )
+ {
+ pGateTruth[2] = '0' + ( *p & 1 );
+ pGateTruth[1] = '0' + ( ( *p >> 1 ) & 1 );
+ pGateTruth[0] = '0' + ( ( *p >> 2 ) & 1 );
+ ++p;
+
+ assert( *p == 2 ); /* binary gate */
+ ++p;
+
+ pSopCover = Abc_SopFromTruthBin( pGateTruth );
+ pObj = Abc_NtkCreateNode( pNtk );
+ pObj->pData = Abc_SopRegister( (Mem_Flex_t*)pNtk->pManFunc, pSopCover );
+ Vec_PtrPush( pGates, pObj );
+ ABC_FREE( pSopCover );
+
+ Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, *p++ ) );
+ Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, *p++ ) );
+ }
+
+ /* outputs */
+ for ( h = 0; h < pSol[ABC_EXACT_SOL_NFUNC]; ++h )
+ {
+ pObj = Abc_NtkCreatePo( pNtk );
+ Abc_ObjAssignName( pObj, (char*)Vec_PtrEntry( vNames, pSol[ABC_EXACT_SOL_NVARS] + h ), NULL );
+ if ( Abc_LitIsCompl( *p ) )
+ Abc_ObjAddFanin( pObj, Abc_NtkCreateNodeInv( pNtk, (Abc_Obj_t *)Vec_PtrEntry( pGates, pSol[ABC_EXACT_SOL_NVARS] + Abc_Lit2Var( *p ) ) ) );
+ else
+ Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, pSol[ABC_EXACT_SOL_NVARS] + Abc_Lit2Var( *p ) ) );
+ p += ( 2 + pSol[ABC_EXACT_SOL_NVARS] );
+ }
+ Abc_NodeFreeNames( vNames );
+
+ Vec_PtrFree( pGates );
+
+ if ( !Abc_NtkCheck( pNtk ) )
+ printf( "Ses_ManExtractSolution(): Network check has failed.\n" );
+
+ return pNtk;
+}
+
+static Gia_Man_t * Ses_ManExtractGia( char const * pSol )
+{
+ int h, i;
+ char const * p;
+ Gia_Man_t * pGia;
+ Vec_Int_t * pGates;
+ Vec_Ptr_t * vNames;
+ int nObj, nChild1, nChild2, fChild1Comp, fChild2Comp;
+
+ pGia = Gia_ManStart( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NGATES] + pSol[ABC_EXACT_SOL_NFUNC] + 1 );
+ pGia->nConstrs = 0;
+ pGia->pName = Extra_UtilStrsav( "exact" );
+
+ pGates = Vec_IntAlloc( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NGATES] );
+ vNames = Abc_NodeGetFakeNames( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NFUNC] );
+
+ /* primary inputs */
+ pGia->vNamesIn = Vec_PtrStart( pSol[ABC_EXACT_SOL_NVARS] );
+ for ( i = 0; i < pSol[ABC_EXACT_SOL_NVARS]; ++i )
+ {
+ nObj = Gia_ManAppendCi( pGia );
+ Vec_IntPush( pGates, nObj );
+ Vec_PtrSetEntry( pGia->vNamesIn, i, Extra_UtilStrsav( Vec_PtrEntry( vNames, i ) ) );
+ }
+
+ /* gates */
+ p = pSol + 3;
+ for ( i = 0; i < pSol[ABC_EXACT_SOL_NGATES]; ++i )
+ {
+ assert( p[1] == 2 );
+ nChild1 = Vec_IntEntry( pGates, p[2] );
+ nChild2 = Vec_IntEntry( pGates, p[3] );
+ fChild1Comp = fChild2Comp = 0;
+
+ if ( *p & 1 )
+ {
+ nChild1 = Abc_LitNot( nChild1 );
+ fChild1Comp = 1;
+ }
+ if ( ( *p >> 1 ) & 1 )
+ {
+ nChild2 = Abc_LitNot( nChild2 );
+ fChild2Comp = 1;
+ }
+ nObj = Gia_ManAppendAnd( pGia, nChild1, nChild2 );
+ if ( fChild1Comp && fChild2Comp )
+ {
+ assert( ( *p >> 2 ) & 1 );
+ nObj = Abc_LitNot( nObj );
+ }
+
+ Vec_IntPush( pGates, nObj );
+
+ p += 4;
+ }
+
+ /* outputs */
+ pGia->vNamesOut = Vec_PtrStart( pSol[ABC_EXACT_SOL_NFUNC] );
+ for ( h = 0; h < pSol[ABC_EXACT_SOL_NFUNC]; ++h )
+ {
+ nObj = Vec_IntEntry( pGates, pSol[ABC_EXACT_SOL_NVARS] + Abc_Lit2Var( *p ) );
+ if ( Abc_LitIsCompl( *p ) )
+ nObj = Abc_LitNot( nObj );
+ Gia_ManAppendCo( pGia, nObj );
+ Vec_PtrSetEntry( pGia->vNamesOut, h, Extra_UtilStrsav( Vec_PtrEntry( vNames, pSol[ABC_EXACT_SOL_NVARS] + h ) ) );
+ p += ( 2 + pSol[ABC_EXACT_SOL_NVARS] );
+ }
+ Abc_NodeFreeNames( vNames );
+
+ Vec_IntFree( pGates );
+
+ return pGia;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Debug.]
+
+***********************************************************************/
+static void Ses_ManPrintRuntime( Ses_Man_t * pSes )
+{
+ printf( "Runtime breakdown:\n" );
+ ABC_PRTP( "Sat ", pSes->timeSat, pSes->timeTotal );
+ ABC_PRTP( " Sat ", pSes->timeSatSat, pSes->timeTotal );
+ ABC_PRTP( " Unsat", pSes->timeSatUnsat, pSes->timeTotal );
+ ABC_PRTP( "ALL ", pSes->timeTotal, pSes->timeTotal );
+}
+
+static inline void Ses_ManPrintFuncs( Ses_Man_t * pSes )
+{
+ int h;
+
+ printf( "find optimum circuit for %d %d-variable functions:\n", pSes->nSpecFunc, pSes->nSpecVars );
+ for ( h = 0; h < pSes->nSpecFunc; ++h )
+ {
+ printf( " func %d: ", h + 1 );
+ Abc_TtPrintHexRev( stdout, &pSes->pSpec[h >> 2], pSes->nSpecVars );
+ printf( "\n" );
+ }
+}
+
+static inline void Ses_ManPrintVars( Ses_Man_t * pSes )
+{
+ int h, i, j, k, p, q, t;
+
+ for ( i = 0; i < pSes->nGates; ++i )
+ for ( t = 0; t < pSes->nRows; ++t )
+ printf( "x(%d, %d) : %d\n", i, t, Ses_ManSimVar( pSes, i, t ) );
+
+ for ( h = 0; h < pSes->nSpecFunc; ++h )
+ for ( i = 0; i < pSes->nGates; ++i )
+ printf( "h(%d, %d) : %d\n", h, i, Ses_ManOutputVar( pSes, h, i ) );
+
+ for ( i = 0; i < pSes->nGates; ++i )
+ for ( p = 0; p <= 1; ++p )
+ for ( q = 0; q <= 1; ++ q)
+ {
+ if ( p == 0 && q == 0 ) { continue; }
+ printf( "f(%d, %d, %d) : %d\n", i, p, q, Ses_ManGateVar( pSes, i, p, q ) );
+ }
+
+ for ( i = 0; i < pSes->nGates; ++i )
+ for ( j = 0; j < pSes->nSpecVars + i; ++j )
+ for ( k = j + 1; k < pSes->nSpecVars + i; ++k )
+ printf( "s(%d, %d, %d) : %d\n", i, j, k, Ses_ManSelectVar( pSes, i, j, k ) );
+
+ if ( pSes->nMaxDepth > 0 )
+ for ( i = 0; i < pSes->nGates; ++i )
+ for ( j = 0; j <= i; ++j )
+ printf( "d(%d, %d) : %d\n", i, j, Ses_ManDepthVar( pSes, i, j ) );
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Synthesis algorithm.]
+
+***********************************************************************/
+static int Ses_ManFindMinimumSize( Ses_Man_t * pSes )
+{
+ int nGates = 0;
+
+ while ( true )
+ {
+ ++nGates;
+
+ /* give up if number of gates is impossible for given depth */
+ if ( pSes->nMaxDepth != -1 && nGates >= ( 1 << pSes->nMaxDepth ) )
+ return 0;
+
+ Ses_ManCreateVars( pSes, nGates );
+ if ( !Ses_ManCreateClauses( pSes ) )
+ return 0; /* proven UNSAT while creating clauses */
+
+ switch ( Ses_ManSolve( pSes ) )
+ {
+ case 1: return 1; /* SAT */
+ case 2: return 0; /* resource limit */
+ }
+ }
+
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find minimum size networks with a SAT solver.]
+
+ Description [If nMaxDepth is -1, then depth constraints are ignored.
+ If nMaxDepth is not -1, one can set pArrTimeProfile which should have the length of nVars.
+ One can ignore pArrTimeProfile by setting it to NULL.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFindExact( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrTimeProfile, int fVerbose )
+{
+ Ses_Man_t * pSes;
+ char * pSol;
+ Abc_Ntk_t * pNtk = NULL;
+ abctime timeStart;
+
+ /* some checks */
+ assert( nVars >= 2 && nVars <= 8 );
+
+ timeStart = Abc_Clock();
+
+ pSes = Ses_ManAlloc( pTruth, nVars, nFunc, nMaxDepth, pArrTimeProfile, 0, fVerbose );
+ if ( fVerbose )
+ Ses_ManPrintFuncs( pSes );
+
+ if ( Ses_ManFindMinimumSize( pSes ) )
+ {
+ pSol = Ses_ManExtractSolution( pSes );
+ pNtk = Ses_ManExtractNtk( pSol );
+ ABC_FREE( pSol );
+ }
+
+ pSes->timeTotal = Abc_Clock() - timeStart;
+
+ if ( fVerbose )
+ Ses_ManPrintRuntime( pSes );
+
+ /* cleanup */
+ Ses_ManClean( pSes );
+
+ return pNtk;
+}
+
+Gia_Man_t * Gia_ManFindExact( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrTimeProfile, int fVerbose )
+{
+ Ses_Man_t * pSes;
+ char * pSol;
+ Gia_Man_t * pGia = NULL;
+ abctime timeStart;
+
+ /* some checks */
+ assert( nVars >= 2 && nVars <= 8 );
+
+ timeStart = Abc_Clock();
+
+ pSes = Ses_ManAlloc( pTruth, nVars, nFunc, nMaxDepth, pArrTimeProfile, 1, fVerbose );
+ if ( fVerbose )
+ Ses_ManPrintFuncs( pSes );
+
+ if ( Ses_ManFindMinimumSize( pSes ) )
+ {
+ pSol = Ses_ManExtractSolution( pSes );
+ pGia = Ses_ManExtractGia( pSol );
+ ABC_FREE( pSol );
+ }
+
+ pSes->timeTotal = Abc_Clock() - timeStart;
+
+ if ( fVerbose )
+ Ses_ManPrintRuntime( pSes );
+
+ /* cleanup */
+ Ses_ManClean( pSes );
+
+ return pGia;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Some test cases.]
+
+***********************************************************************/
+
+Abc_Ntk_t * Abc_NtkFromTruthTable( word * pTruth, int nVars )
+{
+ Abc_Ntk_t * pNtk;
+ Mem_Flex_t * pMan;
+ char * pSopCover;
+
+ pMan = Mem_FlexStart();
+ pSopCover = Abc_SopCreateFromTruth( pMan, nVars, (unsigned*)pTruth );
+ pNtk = Abc_NtkCreateWithNode( pSopCover );
+ Abc_NtkShortNames( pNtk );
+ Mem_FlexStop( pMan, 0 );
+
+ return pNtk;
+}
+
+void Abc_ExactTestSingleOutput( int fVerbose )
+{
+ extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit );
+
+ word pTruth[4] = {0xcafe, 0, 0, 0};
+ Abc_Ntk_t * pNtk, * pNtk2, * pNtk3, * pNtk4;
+ int pArrTimeProfile[4] = {6, 2, 8, 5};
+
+ pNtk = Abc_NtkFromTruthTable( pTruth, 4 );
+
+ pNtk2 = Abc_NtkFindExact( pTruth, 4, 1, -1, NULL, fVerbose );
+ Abc_NtkShortNames( pNtk2 );
+ Abc_NtkCecSat( pNtk, pNtk2, 10000, 0 );
+ assert( pNtk2 );
+ assert( Abc_NtkNodeNum( pNtk2 ) == 6 );
+ Abc_NtkDelete( pNtk2 );
+
+ pNtk3 = Abc_NtkFindExact( pTruth, 4, 1, 3, NULL, fVerbose );
+ Abc_NtkShortNames( pNtk3 );
+ Abc_NtkCecSat( pNtk, pNtk3, 10000, 0 );
+ assert( pNtk3 );
+ assert( Abc_NtkLevel( pNtk3 ) <= 3 );
+ Abc_NtkDelete( pNtk3 );
+
+ pNtk4 = Abc_NtkFindExact( pTruth, 4, 1, 9, pArrTimeProfile, fVerbose );
+ Abc_NtkShortNames( pNtk4 );
+ Abc_NtkCecSat( pNtk, pNtk4, 10000, 0 );
+ assert( pNtk4 );
+ assert( Abc_NtkLevel( pNtk4 ) <= 9 );
+ Abc_NtkDelete( pNtk4 );
+
+ assert( !Abc_NtkFindExact( pTruth, 4, 1, 2, NULL, fVerbose ) );
+
+ assert( !Abc_NtkFindExact( pTruth, 4, 1, 8, pArrTimeProfile, fVerbose ) );
+
+ Abc_NtkDelete( pNtk );
+}
+
+void Abc_ExactTestSingleOutputAIG( int fVerbose )
+{
+ word pTruth[4] = {0xcafe, 0, 0, 0};
+ Abc_Ntk_t * pNtk;
+ Gia_Man_t * pGia, * pGia2, * pGia3, * pGia4, * pMiter;
+ Cec_ParCec_t ParsCec, * pPars = &ParsCec;
+ int pArrTimeProfile[4] = {6, 2, 8, 5};
+
+ Cec_ManCecSetDefaultParams( pPars );
+
+ pNtk = Abc_NtkFromTruthTable( pTruth, 4 );
+ Abc_NtkToAig( pNtk );
+ pGia = Abc_NtkAigToGia( pNtk, 1 );
+
+ pGia2 = Gia_ManFindExact( pTruth, 4, 1, -1, NULL, fVerbose );
+ pMiter = Gia_ManMiter( pGia, pGia2, 0, 1, 0, 0, 1 );
+ assert( pMiter );
+ Cec_ManVerify( pMiter, pPars );
+ Gia_ManStop( pMiter );
+
+ pGia3 = Gia_ManFindExact( pTruth, 4, 1, 3, NULL, fVerbose );
+ pMiter = Gia_ManMiter( pGia, pGia3, 0, 1, 0, 0, 1 );
+ assert( pMiter );
+ Cec_ManVerify( pMiter, pPars );
+ Gia_ManStop( pMiter );
+
+ pGia4 = Gia_ManFindExact( pTruth, 4, 1, 9, pArrTimeProfile, fVerbose );
+ pMiter = Gia_ManMiter( pGia, pGia4, 0, 1, 0, 0, 1 );
+ assert( pMiter );
+ Cec_ManVerify( pMiter, pPars );
+ Gia_ManStop( pMiter );
+
+ assert( !Gia_ManFindExact( pTruth, 4, 1, 2, NULL, fVerbose ) );
+
+ assert( !Gia_ManFindExact( pTruth, 4, 1, 8, pArrTimeProfile, fVerbose ) );
+
+ Gia_ManStop( pGia );
+ Gia_ManStop( pGia2 );
+ Gia_ManStop( pGia3 );
+ Gia_ManStop( pGia4 );
+}
+
+void Abc_ExactTest( int fVerbose )
+{
+ Abc_ExactTestSingleOutput( fVerbose );
+ Abc_ExactTestSingleOutputAIG( fVerbose );
+
+ printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [APIs for integraging with the mapper.]
+
+***********************************************************************/
+// may need to have a static pointer to the SAT-based synthesis engine and/or loaded library
+// this procedure should return 1, if the engine/library are available, and 0 otherwise
+int Abc_ExactIsRunning()
+{
+ return s_pSesStore != NULL;
+}
+// this procedure returns the number of inputs of the library
+// for example, somebody may try to map into 10-cuts while the library only contains 8-functions
+int Abc_ExactInputNum()
+{
+ return 8;
+}
+// start exact store manager
+void Abc_ExactStart( int nBTLimit, int fMakeAIG, int fVerbose, const char * pFilename )
+{
+ if ( !s_pSesStore )
+ {
+ s_pSesStore = Ses_StoreAlloc( nBTLimit, fMakeAIG, fVerbose );
+ if ( pFilename )
+ Ses_StoreRead( s_pSesStore, pFilename );
+ }
+ else
+ printf( "BMS manager already started\n" );
+}
+// stop exact store manager
+void Abc_ExactStop( const char * pFilename )
+{
+ if ( s_pSesStore )
+ {
+ if ( pFilename )
+ Ses_StoreWrite( s_pSesStore, pFilename );
+ Ses_StoreClean( s_pSesStore );
+ }
+ else
+ printf( "BMS manager has not been started\n" );
+}
+// show statistics about store manager
+void Abc_ExactStats()
+{
+ int i;
+
+ if ( !s_pSesStore )
+ {
+ printf( "BMS manager has not been started\n" );
+ return;
+ }
+
+ printf( "number of considered cuts :" );
+ for ( i = 2; i < 9; ++i )
+ printf( " %d = %lu ", i, s_pSesStore->pCutCount[i] );
+ printf( " total = %lu\n", s_pSesStore->nCutCount );
+ printf( "cache hits : %lu\n", s_pSesStore->nCacheHit );
+ printf( "number of entries : %d\n", s_pSesStore->nEntriesCount );
+}
+// this procedure takes TT and input arrival times (pArrTimeProfile) and return the smallest output arrival time;
+// it also returns the pin-to-pin delays (pPerm) between each cut leaf and the cut output and the cut area cost (Cost)
+// the area cost should not exceed 2048, if the cut is implementable; otherwise, it should be ABC_INFINITY
+int Abc_ExactDelayCost( word * pTruth, int nVars, int * pArrTimeProfile, char * pPerm, int * Cost, int AigLevel )
+{
+ int i, l, fExists = 0;
+ Ses_Man_t * pSes = NULL;
+ char * pSol = NULL, * p;
+ int Delay = ABC_INFINITY, nMaxDepth;
+ abctime timeStart;
+
+ /* some checks */
+ if ( nVars < 0 || nVars > 8 )
+ {
+ printf( "invalid truth table size %d\n", nVars );
+ assert( 0 );
+ }
+
+ if ( nVars == 0 )
+ {
+ *Cost = 0;
+ return 0;
+ }
+
+ if ( nVars == 1 )
+ {
+ *Cost = 0;
+ pPerm[0] = (char)0;
+ return pArrTimeProfile[0];
+ }
+
+ /* statistics */
+ s_pSesStore->nCutCount++;
+ s_pSesStore->pCutCount[nVars]++;
+
+ pSol = Ses_StoreGetEntry( s_pSesStore, pTruth, nVars, pArrTimeProfile );
+ if ( pSol )
+ {
+ s_pSesStore->nCacheHit++;
+ fExists = 1;
+ }
+ else
+ {
+ nMaxDepth = pArrTimeProfile[0];
+ for ( i = 1; i < nVars; ++i )
+ nMaxDepth = Abc_MaxInt( nMaxDepth, pArrTimeProfile[i] );
+ nMaxDepth = Abc_MinInt( AigLevel, nMaxDepth + nVars + 1 );
+
+ timeStart = Abc_Clock();
+
+ *Cost = ABC_INFINITY;
+
+ pSes = Ses_ManAlloc( pTruth, nVars, 1 /* fSpecFunc */, nMaxDepth, pArrTimeProfile, s_pSesStore->fMakeAIG, s_pSesStore->fVerbose );
+ pSes->nBTLimit = s_pSesStore->nBTLimit;
+
+ while ( 1 ) /* there is improvement */
+ {
+ if ( Ses_ManFindMinimumSize( pSes ) )
+ {
+ if ( pSol )
+ ABC_FREE( pSol );
+ pSol = Ses_ManExtractSolution( pSes );
+ pSes->nMaxDepth--;
+ }
+ else
+ break;
+ }
+
+ pSes->timeTotal = Abc_Clock() - timeStart;
+
+ /* cleanup */
+ Ses_ManClean( pSes );
+ }
+
+ if ( pSol )
+ {
+ *Cost = pSol[ABC_EXACT_SOL_NGATES];
+ p = pSol + 3 + 4 * pSol[ABC_EXACT_SOL_NGATES] + 1;
+ Delay = *p++;
+ for ( l = 0; l < nVars; ++l )
+ pPerm[l] = *p++;
+
+ /* store solution */
+ if ( !fExists )
+ Ses_StoreAddEntry( s_pSesStore, pTruth, nVars, pArrTimeProfile, pSol );
+ }
+
+ return Delay;
+}
+// this procedure returns a new node whose output in terms of the given fanins
+// has the smallest possible arrival time (in agreement with the above Abc_ExactDelayCost)
+Abc_Obj_t * Abc_ExactBuildNode( word * pTruth, int nVars, int * pArrTimeProfile, Abc_Obj_t ** pFanins, Abc_Ntk_t * pNtk )
+{
+ char * pSol;
+ int i, j;
+ char const * p;
+ Abc_Obj_t * pObj;
+ Vec_Ptr_t * pGates;
+ char pGateTruth[5];
+ char * pSopCover;
+
+ if ( nVars == 0 )
+ return (pTruth[0] & 1) ? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk);
+ if ( nVars == 1 )
+ return (pTruth[0] & 1) ? Abc_NtkCreateNodeInv(pNtk, pFanins[0]) : Abc_NtkCreateNodeBuf(pNtk, pFanins[0]);
+
+ pSol = Ses_StoreGetEntry( s_pSesStore, pTruth, nVars, pArrTimeProfile );
+ if ( !pSol )
+ return NULL;
+
+ assert( pSol[ABC_EXACT_SOL_NVARS] == nVars );
+ assert( pSol[ABC_EXACT_SOL_NFUNC] == 1 );
+
+ pGates = Vec_PtrAlloc( nVars + pSol[ABC_EXACT_SOL_NGATES] );
+ pGateTruth[3] = '0';
+ pGateTruth[4] = '\0';
+
+ /* primary inputs */
+ for ( i = 0; i < nVars; ++i )
+ {
+ Vec_PtrPush( pGates, pFanins[i] );
+ }
+
+ /* gates */
+ p = pSol + 3;
+ for ( i = 0; i < pSol[ABC_EXACT_SOL_NGATES]; ++i )
+ {
+ pGateTruth[2] = '0' + ( *p & 1 );
+ pGateTruth[1] = '0' + ( ( *p >> 1 ) & 1 );
+ pGateTruth[0] = '0' + ( ( *p >> 2 ) & 1 );
+ ++p;
+
+ assert( *p == 2 ); /* binary gate */
+ ++p;
+
+ /* invert truth table if we are last gate and inverted */
+ if ( i + 1 == pSol[ABC_EXACT_SOL_NGATES] && Abc_LitIsCompl( *( p + 2 ) ) )
+ for ( j = 0; j < 4; ++j )
+ pGateTruth[j] = ( pGateTruth[j] == '0' ) ? '1' : '0';
+
+ pSopCover = Abc_SopFromTruthBin( pGateTruth );
+ pObj = Abc_NtkCreateNode( pNtk );
+ pObj->pData = Abc_SopRegister( (Mem_Flex_t*)pNtk->pManFunc, pSopCover );
+ Vec_PtrPush( pGates, pObj );
+ ABC_FREE( pSopCover );
+
+ Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, *p++ ) );
+ Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, *p++ ) );
+ }
+
+ /* output */
+ pObj = (Abc_Obj_t *)Vec_PtrEntry( pGates, nVars + Abc_Lit2Var( *p ) );
+
+ Vec_PtrFree( pGates );
+
+ return pObj;
+}
+
+void Abc_ExactStoreTest( int fVerbose )
+{
+ int i;
+ word pTruth[4] = {0xcafe, 0, 0, 0};
+ int pArrTimeProfile[4] = {6, 2, 8, 5};
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pFanins[4];
+ Vec_Ptr_t * vNames;
+ char pPerm[4];
+ int Cost;
+
+ pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 );
+ pNtk->pName = Extra_UtilStrsav( "exact" );
+ vNames = Abc_NodeGetFakeNames( 4u );
+
+ /* primary inputs */
+ Vec_PtrPush( pNtk->vObjs, NULL );
+ for ( i = 0; i < 4; ++i )
+ {
+ pFanins[i] = Abc_NtkCreatePi( pNtk );
+ Abc_ObjAssignName( pFanins[i], (char*)Vec_PtrEntry( vNames, i ), NULL );
+ }
+ Abc_NodeFreeNames( vNames );
+
+ Abc_ExactStart( 10000, 1, fVerbose, NULL );
+
+ assert( !Abc_ExactBuildNode( pTruth, 4, pArrTimeProfile, pFanins, pNtk ) );
+
+ assert( Abc_ExactDelayCost( pTruth, 4, pArrTimeProfile, pPerm, &Cost, 12 ) == 1 );
+
+ assert( Abc_ExactBuildNode( pTruth, 4, pArrTimeProfile, pFanins, pNtk ) );
+
+ (*pArrTimeProfile)++;
+ assert( !Abc_ExactBuildNode( pTruth, 4, pArrTimeProfile, pFanins, pNtk ) );
+ (*pArrTimeProfile)--;
+
+ Abc_ExactStop( NULL );
+
+ Abc_NtkDelete( pNtk );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/src/base/abci/abcFx.c b/src/base/abci/abcFx.c
index 60f2e562..81b3e802 100644
--- a/src/base/abci/abcFx.c
+++ b/src/base/abci/abcFx.c
@@ -8,9 +8,9 @@
Synopsis [Implementation of traditional "fast_extract" algorithm.]
- Author [Alan Mishchenko]
+ Author [Alan Mishchenko, Bruno Schmitt]
- Affiliation [UC Berkeley]
+ Affiliation [UC Berkeley, UFRGS]
Date [Ver. 1.0. Started - April 26, 2013.]
@@ -103,6 +103,7 @@ struct Fx_Man_t_
Vec_Int_t * vCompls; // complemented attribute of each cube pair
Vec_Int_t * vCubeFree; // cube-free divisor
Vec_Int_t * vDiv; // selected divisor
+ Vec_Int_t * vSCC; // single cubes containment cubes
// statistics
abctime timeStart; // starting time
int nVars; // original problem variables
@@ -312,11 +313,6 @@ int Abc_NtkFxPerform( Abc_Ntk_t * pNtk, int nNewNodesMax, int LitCountMax, int f
printf( "Abc_NtkFastExtract: Nodes have duplicated fanins. FX is not performed.\n" );
return 0;
}
- // sweep removes useless nodes
- Abc_NtkCleanup( pNtk, 0 );
-// Abc_NtkOrderFanins( pNtk );
- // makes sure the SOPs are SCC-free and D1C-free
- Abc_NtkMakeLegit( pNtk );
// collect information about the covers
vCubes = Abc_NtkFxRetrieve( pNtk );
// call the fast extract procedure
@@ -359,6 +355,7 @@ Fx_Man_t * Fx_ManStart( Vec_Wec_t * vCubes )
p->vCompls = Vec_IntAlloc( 100 );
p->vCubeFree = Vec_IntAlloc( 100 );
p->vDiv = Vec_IntAlloc( 100 );
+ p->vSCC = Vec_IntAlloc( 100 );
return p;
}
void Fx_ManStop( Fx_Man_t * p )
@@ -377,6 +374,7 @@ void Fx_ManStop( Fx_Man_t * p )
Vec_IntFree( p->vCompls );
Vec_IntFree( p->vCubeFree );
Vec_IntFree( p->vDiv );
+ Vec_IntFree( p->vSCC );
ABC_FREE( p );
}
@@ -435,39 +433,16 @@ void Fx_ManComputeLevel( Fx_Man_t * p )
SeeAlso []
***********************************************************************/
-static inline char Fx_PrintDivLit( int Lit ) { return (Abc_LitIsCompl(Lit) ? 'A' : 'a') + Abc_Lit2Var(Lit); }
-static inline void Fx_PrintDivOneReal( Vec_Int_t * vDiv )
-{
- int i, Lit;
- Vec_IntForEachEntry( vDiv, Lit, i )
- if ( !Abc_LitIsCompl(Lit) )
- printf( "%c", Fx_PrintDivLit(Abc_Lit2Var(Lit)) );
- printf( " + " );
- Vec_IntForEachEntry( vDiv, Lit, i )
- if ( Abc_LitIsCompl(Lit) )
- printf( "%c", Fx_PrintDivLit(Abc_Lit2Var(Lit)) );
-}
-static inline void Fx_PrintDivOne( Vec_Int_t * vDiv )
-{
- int i, Lit;
- Vec_IntForEachEntry( vDiv, Lit, i )
- if ( !Abc_LitIsCompl(Lit) )
- printf( "%c", Fx_PrintDivLit( Abc_Var2Lit(i, Abc_LitIsCompl(Lit)) ) );
- printf( " + " );
- Vec_IntForEachEntry( vDiv, Lit, i )
- if ( Abc_LitIsCompl(Lit) )
- printf( "%c", Fx_PrintDivLit( Abc_Var2Lit(i, Abc_LitIsCompl(Lit)) ) );
-}
static inline void Fx_PrintDivArray( Vec_Int_t * vDiv )
{
int i, Lit;
Vec_IntForEachEntry( vDiv, Lit, i )
if ( !Abc_LitIsCompl(Lit) )
- printf( "%d(1) ", Abc_Lit2Var(Lit) );
+ printf( "%d(1)", Abc_Lit2Var(Lit) );
printf( " + " );
Vec_IntForEachEntry( vDiv, Lit, i )
if ( Abc_LitIsCompl(Lit) )
- printf( "%d(2) ", Abc_Lit2Var(Lit) );
+ printf( "%d(2)", Abc_Lit2Var(Lit) );
}
static inline void Fx_PrintDiv( Fx_Man_t * p, int iDiv )
{
@@ -475,8 +450,7 @@ static inline void Fx_PrintDiv( Fx_Man_t * p, int iDiv )
printf( "%4d : ", p->nDivs );
printf( "Div %7d : ", iDiv );
printf( "Weight %12.5f ", Vec_FltEntry(p->vWeights, iDiv) );
-// printf( "Compl %4d ", p->nCompls );
- Fx_PrintDivOne( Hsh_VecReadEntry(p->pHash, iDiv) );
+ Fx_PrintDivArray( Hsh_VecReadEntry(p->pHash, iDiv) );
for ( i = Vec_IntSize(Hsh_VecReadEntry(p->pHash, iDiv)) + 3; i < 16; i++ )
printf( " " );
printf( "Lits =%7d ", p->nLits );
@@ -489,45 +463,6 @@ static void Fx_PrintDivisors( Fx_Man_t * p )
for ( iDiv = 0; iDiv < Vec_FltSize(p->vWeights); iDiv++ )
Fx_PrintDiv( p, iDiv );
}
-static void Fx_PrintLiterals( Fx_Man_t * p )
-{
- Vec_Int_t * vTemp;
- int i;
- Vec_WecForEachLevel( p->vLits, vTemp, i )
- {
- printf( "%c : ", Fx_PrintDivLit(i) );
- Vec_IntPrint( vTemp );
- }
-}
-static void Fx_PrintMatrix( Fx_Man_t * p )
-{
- Vec_Int_t * vCube;
- int i, v, Lit, nObjs;
- char * pLine;
- if ( Vec_WecSize(p->vLits)/2 > 26 )
- return;
- printf( " " );
- nObjs = Vec_WecSize(p->vLits)/2;
- for ( i = 0; i < Abc_MinInt(nObjs, 26); i++ )
- printf( "%c", 'a' + i );
- printf( "\n" );
- pLine = ABC_CALLOC( char, nObjs+1 );
- Vec_WecForEachLevel( p->vCubes, vCube, i )
- {
- if ( Vec_IntSize(vCube) == 0 )
- continue;
- memset( pLine, '-', nObjs );
- Vec_IntForEachEntryStart( vCube, Lit, v, 1 )
- {
- assert( Abc_Lit2Var(Lit) < nObjs );
- pLine[Abc_Lit2Var(Lit)] = Abc_LitIsCompl(Lit) ? '0' : '1';
- }
- printf( "%6d : %s %4d\n", i, pLine, Vec_IntEntry(vCube, 0) );
- }
- ABC_FREE( pLine );
- Fx_PrintLiterals( p );
- Fx_PrintDivisors( p );
-}
static void Fx_PrintStats( Fx_Man_t * p, abctime clk )
{
printf( "Cubes =%8d ", Vec_WecSizeUsed(p->vCubes) );
@@ -536,11 +471,7 @@ static void Fx_PrintStats( Fx_Man_t * p, abctime clk )
printf( "Divs+ =%8d ", Vec_QueSize(p->vPrio) );
printf( "Compl =%8d ", p->nDivMux[1] );
printf( "Extr =%7d ", p->nDivs );
-// printf( "DivsS =%6d ", p->nDivsS );
-// printf( "PairS =%6d ", p->nPairsS );
-// printf( "PairD =%6d ", p->nPairsD );
Abc_PrintTime( 1, "Time", clk );
-// printf( "\n" );
}
/**Function*************************************************************
@@ -638,10 +569,10 @@ static int Fx_ManDivNormalize( Vec_Int_t * vCubeFree ) // return 1 if complement
***********************************************************************/
int Fx_ManDivFindCubeFree( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vCubeFree, int * fWarning )
{
- int * pBeg1 = vArr1->pArray + 1; // skip variable ID
- int * pBeg2 = vArr2->pArray + 1; // skip variable ID
- int * pEnd1 = vArr1->pArray + vArr1->nSize;
- int * pEnd2 = vArr2->pArray + vArr2->nSize;
+ int * pBeg1 = Vec_IntArray( vArr1 ) + 1; // skip variable ID
+ int * pBeg2 = Vec_IntArray( vArr2 ) + 1; // skip variable ID
+ int * pEnd1 = Vec_IntLimit( vArr1 );
+ int * pEnd2 = Vec_IntLimit( vArr2 );
int Counter = 0, fAttr0 = 0, fAttr1 = 1;
Vec_IntClear( vCubeFree );
while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
@@ -664,9 +595,38 @@ int Fx_ManDivFindCubeFree( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vCu
if ( Vec_IntSize(vCubeFree) == 0 )
printf( "The SOP has duplicated cubes.\n" );
else if ( Vec_IntSize(vCubeFree) == 1 )
- printf( "The SOP has contained cubes.\n" );
-// else if ( Vec_IntSize(vCubeFree) == 2 && Abc_Lit2Var(Abc_Lit2Var(Vec_IntEntry(vCubeFree, 0))) == Abc_Lit2Var(Abc_Lit2Var(Vec_IntEntry(vCubeFree, 1))) && !*fWarning )
-// printf( "The SOP has distance-1 cubes or it is not a prime cover. Please make sure the result verifies.\n" ), *fWarning = 1;
+ return -1;
+ else if ( Vec_IntSize( vCubeFree ) == 3 )
+ {
+ int * pArray = Vec_IntArray( vCubeFree );
+
+ if ( Abc_Lit2Var( pArray[0] ) == Abc_LitNot( Abc_Lit2Var( pArray[1] ) ) )
+ {
+ if ( Abc_LitIsCompl( pArray[0] ) == Abc_LitIsCompl( pArray[2] ) )
+ Vec_IntDrop( vCubeFree, 0 );
+ else
+ Vec_IntDrop( vCubeFree, 1 );
+ }
+ else if ( Abc_Lit2Var( pArray[1] ) == Abc_LitNot( Abc_Lit2Var( pArray[2] ) ) )
+ {
+ if ( Abc_LitIsCompl( pArray[1] ) == Abc_LitIsCompl( pArray[0] ) )
+ Vec_IntDrop( vCubeFree, 1 );
+ else
+ Vec_IntDrop( vCubeFree, 2 );
+ }
+
+ if ( Vec_IntSize( vCubeFree ) == 2 )
+ {
+ int Lit0 = Abc_Lit2Var( pArray[0] ),
+ Lit1 = Abc_Lit2Var( pArray[1] );
+
+ if ( Lit0 > Lit1 )
+ ABC_SWAP( int, Lit0, Lit1 );
+
+ Vec_IntWriteEntry( vCubeFree, 0, Abc_Var2Lit( Lit0, 0 ) );
+ Vec_IntWriteEntry( vCubeFree, 1, Abc_Var2Lit( Lit1, 1 ) );
+ }
+ }
assert( !Abc_LitIsCompl(Vec_IntEntry(vCubeFree, 0)) );
return Counter;
}
@@ -708,7 +668,11 @@ static inline int Fx_ManDivRemoveLits( Vec_Int_t * vCube, Vec_Int_t * vDiv, int
int i, Lit, Count = 0;
assert( !fCompl || Vec_IntSize(vDiv) == 4 );
Vec_IntForEachEntry( vDiv, Lit, i )
+ {
Count += Vec_IntRemove1( vCube, Abc_Lit2Var(Lit) ^ (fCompl && i > 1) ); // the last two lits can be complemented
+ if ( Vec_IntSize( vDiv ) == 2 )
+ Count += Vec_IntRemove1( vCube, Abc_LitNot( Abc_Lit2Var(Lit) ) );
+ }
return Count;
}
static inline void Fx_ManDivAddLits( Vec_Int_t * vCube, Vec_Int_t * vCube2, Vec_Int_t * vDiv )
@@ -833,6 +797,17 @@ void Fx_ManCubeDoubleCubeDivisors( Fx_Man_t * p, int iFirst, Vec_Int_t * vPivot,
if ( Vec_IntEntry(vCube, 0) != Vec_IntEntry(vPivot, 0) )
break;
Base = Fx_ManDivFindCubeFree( vCube, vPivot, p->vCubeFree, fWarning );
+ if ( Base == -1 )
+ {
+ if ( fRemove == 0 )
+ {
+ if ( Vec_IntSize( vCube ) > Vec_IntSize( vPivot ) )
+ Vec_IntPush( p->vSCC, Vec_WecLevelId( p->vCubes, vCube ) );
+ else
+ Vec_IntPush( p->vSCC, Vec_WecLevelId( p->vCubes, vPivot ) );
+ }
+ continue;
+ }
if ( Vec_IntSize(p->vCubeFree) == 4 )
{
int Value = Fx_ManDivNormalize( p->vCubeFree );
@@ -988,10 +963,9 @@ void Fx_ManFindCommonPairs( Vec_Wec_t * vCubes, Vec_Int_t * vPart0, Vec_Int_t *
***********************************************************************/
void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning )
{
- Vec_Int_t * vCube, * vCube2, * vLitP, * vLitN;
+ Vec_Int_t * vCube, * vCube2, * vLitP = NULL, * vLitN = NULL;
Vec_Int_t * vDiv = p->vDiv;
- int nLitsNew = p->nLits - (int)Vec_FltEntry(p->vWeights, iDiv);
- int i, k, Lit0, Lit1, iVarNew, RetValue, Level;
+ int i, k, Lit0, Lit1, iVarNew = 0, RetValue, Level;
float Diff = Vec_FltEntry(p->vWeights, iDiv) - (float)((int)Vec_FltEntry(p->vWeights, iDiv));
assert( Diff > 0.0 && Diff < 1.0 );
@@ -1002,10 +976,6 @@ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning )
Fx_ManDivFindPivots( vDiv, &Lit0, &Lit1 );
assert( Lit0 >= 0 && Lit1 >= 0 );
- // if the input cover is not prime, it may happen that we are extracting divisor (x + !x)
- // although it is not strictly correct, it seems to be fine to just skip such divisors
- if ( Abc_Lit2Var(Lit0) == Abc_Lit2Var(Lit1) && Vec_IntSize(Hsh_VecReadEntry(p->pHash, iDiv)) == 2 )
- return;
// collect single-cube-divisor cubes
Vec_IntClear( p->vCubesS );
@@ -1041,6 +1011,9 @@ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning )
Vec_WecUnmarkLevels( p->vCubes, p->vCubesS );
Vec_WecUnmarkLevels( p->vCubes, p->vCubesD );
+ if ( Abc_Lit2Var(Lit0) == Abc_Lit2Var(Lit1) && Vec_IntSize(Hsh_VecReadEntry(p->pHash, iDiv)) == 2 )
+ goto ExtractFromPairs;
+
// create new divisor
iVarNew = Vec_WecSize( p->vLits ) / 2;
assert( Vec_IntSize(p->vVarCube) == iVarNew );
@@ -1080,6 +1053,7 @@ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning )
p->nLits--;
}
// create updated double-cube divisor cube pairs
+ExtractFromPairs:
k = 0;
p->nCompls = 0;
assert( Vec_IntSize(p->vCubesD) % 2 == 0 );
@@ -1092,18 +1066,22 @@ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning )
vCube2 = Vec_WecEntry( p->vCubes, Vec_IntEntry(p->vCubesD, i+1) );
RetValue = Fx_ManDivRemoveLits( vCube, vDiv, fCompl ); // cube 2*i
RetValue += Fx_ManDivRemoveLits( vCube2, vDiv, fCompl ); // cube 2*i+1
- assert( RetValue == Vec_IntSize(vDiv) );
- if ( Vec_IntSize(vDiv) == 2 || fCompl )
+ assert( RetValue == Vec_IntSize(vDiv) || RetValue == Vec_IntSize( vDiv ) + 1);
+ if ( iVarNew > 0 )
{
- Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 1) );
- Vec_IntPush( vLitN, Vec_WecLevelId(p->vCubes, vCube) ); // MAKE SURE vCube IS SORTED BY ID
- }
- else
- {
- Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 0) );
- Vec_IntPush( vLitP, Vec_WecLevelId(p->vCubes, vCube) ); // MAKE SURE vCube IS SORTED BY ID
+ if ( Vec_IntSize(vDiv) == 2 || fCompl )
+ {
+ Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 1) );
+ Vec_IntPush( vLitN, Vec_WecLevelId(p->vCubes, vCube) ); // MAKE SURE vCube IS SORTED BY ID
+ }
+ else
+ {
+ Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 0) );
+ Vec_IntPush( vLitP, Vec_WecLevelId(p->vCubes, vCube) ); // MAKE SURE vCube IS SORTED BY ID
+ }
}
p->nLits -= Vec_IntSize(vDiv) + Vec_IntSize(vCube2) - 2;
+
// remove second cube
Vec_IntWriteEntry( p->vCubesD, k++, Vec_WecLevelId(p->vCubes, vCube) );
Vec_IntClear( vCube2 );
@@ -1134,6 +1112,17 @@ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning )
Vec_WecUnmarkLevels( p->vCubes, p->vCubesS );
Vec_WecUnmarkLevels( p->vCubes, p->vCubesD );
+ // Deal with SCC
+ if ( Vec_IntSize( p->vSCC ) )
+ {
+ Vec_IntUniqify( p->vSCC );
+ Fx_ManForEachCubeVec( p->vSCC, p->vCubes, vCube, i )
+ {
+ Fx_ManCubeDoubleCubeDivisors( p, Fx_ManGetFirstVarCube(p, vCube), vCube, 1, 1, fWarning ); // remove - update
+ Vec_IntClear( vCube );
+ }
+ Vec_IntClear( p->vSCC );
+ }
// add cost of the new divisor
if ( Vec_IntSize(vDiv) > 2 )
{
@@ -1151,12 +1140,10 @@ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning )
Vec_IntForEachEntry( vDiv, Lit0, i )
{
Vec_IntTwoRemove( Vec_WecEntry(p->vLits, Abc_Lit2Var(Lit0)), p->vCubesD );
- if ( p->nCompls && i > 1 ) // the last two lits are possibly complemented
+ if ( (p->nCompls && i > 1) || Vec_IntSize( vDiv ) == 2 ) // the last two lits are possibly complemented
Vec_IntTwoRemove( Vec_WecEntry(p->vLits, Abc_LitNot(Abc_Lit2Var(Lit0))), p->vCubesD );
}
-
- // check predicted improvement: (new SOP lits == old SOP lits - divisor weight)
- assert( p->nLits == nLitsNew );
+
}
/**Function*************************************************************
@@ -1186,7 +1173,7 @@ int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitC
Fx_ManComputeLevel( p );
Fx_ManCreateDivisors( p );
if ( fVeryVerbose )
- Fx_PrintMatrix( p );
+ Fx_PrintDivisors( p );
if ( fVerbose )
Fx_PrintStats( p, Abc_Clock() - clk );
// perform extraction
@@ -1198,7 +1185,7 @@ int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitC
Fx_PrintDiv( p, iDiv );
Fx_ManUpdate( p, iDiv, &fWarning );
if ( fVeryVeryVerbose )
- Fx_PrintMatrix( p );
+ Fx_PrintDivisors( p );
}
if ( fVerbose )
Fx_PrintStats( p, Abc_Clock() - clk );
diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c
index c45eaec5..08e2a560 100644
--- a/src/base/abci/abcIf.c
+++ b/src/base/abci/abcIf.c
@@ -116,7 +116,7 @@ Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars )
pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk);
// update timing info to reflect logic level
- if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib) && pNtk->pManTime )
+ if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib) && pNtk->pManTime )
{
int c;
if ( pNtk->AndGateDelay == 0.0 )
@@ -318,7 +318,7 @@ Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk )
// create the new network
if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
- else if ( pIfMan->pPars->fUseSops || pIfMan->pPars->nGateSize > 0 )
+ else if ( pIfMan->pPars->fUseSops || pIfMan->pPars->fUserSesLib || pIfMan->pPars->nGateSize > 0 )
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
else
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG );
@@ -445,12 +445,22 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t
return pNodeNew;
assert( pIfObj->Type == IF_AND );
// get the parameters of the best cut
+ pCutBest = If_ObjCutBest( pIfObj );
+ if ( pIfMan->pPars->fUserSesLib )
+ {
+ // create the subgraph composed of Abc_Obj_t nodes based on the given cut
+ Abc_Obj_t * pFanins[IF_MAX_FUNC_LUTSIZE];
+ If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i )
+ pFanins[i] = Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover);
+ pNodeNew = Abc_ExactBuildNode( If_CutTruthW(pIfMan, pCutBest), If_CutLeaveNum(pCutBest), If_CutArrTimeProfile(pIfMan, pCutBest), pFanins, pNtkNew );
+ If_ObjSetCopy( pIfObj, pNodeNew );
+ return pNodeNew;
+ }
// create a new node
pNodeNew = Abc_NtkCreateNode( pNtkNew );
- pCutBest = If_ObjCutBest( pIfObj );
-// printf( "%d 0x%02X %d\n", pCutBest->nLeaves, 0xff & *If_CutTruth(pCutBest), pIfMan->pPars->pFuncCost(pCutBest) );
// if ( pIfMan->pPars->pLutLib && pIfMan->pPars->pLutLib->fVarPinDelays )
- if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->fUseTtPerm && !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->nGateSize )
+ if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->fUseTtPerm &&
+ !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize )
If_CutRotatePins( pIfMan, pCutBest );
if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
{
diff --git a/src/base/abci/abcMini.c b/src/base/abci/abcMini.c
index bd893b5b..876f4c8c 100644
--- a/src/base/abci/abcMini.c
+++ b/src/base/abci/abcMini.c
@@ -205,7 +205,7 @@ void Abc_NtkMiniAigTest( Abc_Ntk_t * pNtk )
p = Abc_NtkToMiniAig( pNtk );
pNtkNew = Abc_NtkFromMiniAig( p );
Mini_AigStop( p );
- Abc_NtkPrintStats( pNtkNew, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
+ Abc_NtkPrintStats( pNtkNew, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
Abc_NtkDelete( pNtkNew );
// test dumping
diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c
index 40ce38b4..2129782f 100644
--- a/src/base/abci/abcPrint.c
+++ b/src/base/abci/abcPrint.c
@@ -235,7 +235,7 @@ float Abc_NtkGetArea( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower, int fGlitch, int fSkipBuf, int fPrintMem )
+void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower, int fGlitch, int fSkipBuf, int fSkipSmall, int fPrintMem )
{
int nSingles = fSkipBuf ? Abc_NtkGetBufNum(pNtk) : 0;
if ( fPrintMuxes && Abc_NtkIsStrash(pNtk) )
@@ -283,7 +283,7 @@ void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDum
if ( Abc_NtkIsNetlist(pNtk) )
{
Abc_Print( 1," net =%5d", Abc_NtkNetNum(pNtk) );
- Abc_Print( 1," nd =%5d", Abc_NtkNodeNum(pNtk) - nSingles );
+ Abc_Print( 1," nd =%5d", fSkipSmall ? Abc_NtkGetLargeNodeNum(pNtk) : Abc_NtkNodeNum(pNtk) - nSingles );
Abc_Print( 1," wbox =%3d", Abc_NtkWhiteboxNum(pNtk) );
Abc_Print( 1," bbox =%3d", Abc_NtkBlackboxNum(pNtk) );
}
@@ -295,7 +295,7 @@ void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDum
}
else
{
- Abc_Print( 1," nd =%6d", Abc_NtkNodeNum(pNtk) - nSingles );
+ Abc_Print( 1," nd =%6d", fSkipSmall ? Abc_NtkGetLargeNodeNum(pNtk) : Abc_NtkNodeNum(pNtk) - nSingles );
Abc_Print( 1," edge =%7d", Abc_NtkGetTotalFanins(pNtk) - nSingles );
}
@@ -455,7 +455,7 @@ void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDum
fflush( stdout );
if ( pNtk->pExdc )
- Abc_NtkPrintStats( pNtk->pExdc, fFactored, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf, fPrintMem );
+ Abc_NtkPrintStats( pNtk->pExdc, fFactored, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf, fSkipSmall, fPrintMem );
}
/**Function*************************************************************
diff --git a/src/base/abci/module.make b/src/base/abci/module.make
index a3c343ee..b97f526f 100644
--- a/src/base/abci/module.make
+++ b/src/base/abci/module.make
@@ -15,7 +15,9 @@ SRC += src/base/abci/abc.c \
src/base/abci/abcDetect.c \
src/base/abci/abcDress.c \
src/base/abci/abcDress2.c \
+ src/base/abci/abcDress3.c \
src/base/abci/abcDsd.c \
+ src/base/abci/abcExact.c \
src/base/abci/abcExtract.c \
src/base/abci/abcFraig.c \
src/base/abci/abcFx.c \
diff --git a/src/base/io/ioReadBench.c b/src/base/io/ioReadBench.c
index 4fb21ad1..4d038200 100644
--- a/src/base/io/ioReadBench.c
+++ b/src/base/io/ioReadBench.c
@@ -94,6 +94,7 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p )
// allocate the empty network
pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) );
+ pNtk->nConstrs = 0;
// go through the lines of the file
vString = Vec_StrAlloc( 100 );
@@ -140,6 +141,7 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p )
pTerm = Abc_NtkCreatePo( pNtk );
Abc_ObjAddFanin( pTerm, pNet );
}
+ pNtk->nConstrs++;
}
else
{
diff --git a/src/base/io/ioReadPlaMo.c b/src/base/io/ioReadPlaMo.c
index 1cd453d2..d190d30a 100644
--- a/src/base/io/ioReadPlaMo.c
+++ b/src/base/io/ioReadPlaMo.c
@@ -297,6 +297,32 @@ static inline void Mop_ManRemoveEmpty( Mop_Man_t * p )
/**Function*************************************************************
+ Synopsis [Count how many times each variable appears in the input parts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Mop_ManCollectStats( Mop_Man_t * p )
+{
+ int i, v, iCube, nVars = 32 * p->nWordsIn;
+ Vec_Int_t * vStats = Vec_IntStart( nVars );
+ Vec_IntForEachEntry( p->vCubes, iCube, i )
+ {
+ word * pCube = Mop_ManCubeIn(p, iCube);
+ int nOutLits = Mop_ManCountOnes( Mop_ManCubeOut(p, iCube), p->nWordsOut );
+ for ( v = 0; v < nVars; v++ )
+ if ( Abc_TtGetQua(pCube, v) )
+ Vec_IntAddToEntry( vStats, v, nOutLits );
+ }
+ return vStats;
+}
+
+/**Function*************************************************************
+
Synopsis []
Description []
@@ -306,6 +332,20 @@ static inline void Mop_ManRemoveEmpty( Mop_Man_t * p )
SeeAlso []
***********************************************************************/
+// knowing that cubes are distance-1, find the different input variable
+static inline int Mop_ManFindDiffVar( word * pCube1, word * pCube2, int nWords )
+{
+ int w, i;
+ for ( w = 0; w < nWords; w++ )
+ {
+ word Xor = pCube1[w] ^ pCube2[w];
+ for ( i = 0; i < 32; i++ )
+ if ( (Xor >> (i << 1)) & 0x3 )
+ return w * 32 + i;
+ }
+ assert( 0 );
+ return -1;
+}
// check containment of input parts of two cubes
static inline int Mop_ManCheckDist1( word * pCube1, word * pCube2, int nWords )
{
@@ -439,21 +479,30 @@ Vec_Int_t * Mop_ManFindDist1Pairs( Mop_Man_t * p, Vec_Int_t * vGroup )
return vPairs;
}
// merge distance-1 with identical output part
-int Mop_ManMergeDist1Pairs( Mop_Man_t * p, Vec_Int_t * vGroup, Vec_Int_t * vGroupPrev )
+int Mop_ManMergeDist1Pairs( Mop_Man_t * p, Vec_Int_t * vGroup, Vec_Int_t * vGroupPrev, Vec_Int_t * vStats, int nLimit )
{
Vec_Int_t * vPairs = Mop_ManFindDist1Pairs( p, vGroup );
Vec_Int_t * vPairsNew = Mop_ManCompatiblePairs( vPairs, Vec_IntSize(vGroup) );
- int w, i, c1, c2, nCubes = Vec_IntSize(vGroup) + Vec_IntSize(vGroupPrev);
+ int nCubes = Vec_IntSize(vGroup) + Vec_IntSize(vGroupPrev);
+ int w, i, c1, c2, iCubeNew, iVar;
// move cubes to the previous group
+ word * pCube, * pCube1, * pCube2;
+ Vec_Int_t * vToFree = Vec_IntAlloc( Vec_IntSize(vPairsNew) );
Vec_IntForEachEntryDouble( vPairsNew, c1, c2, i )
{
- int iCubeNew = Vec_IntPop( p->vFree );
+ pCube1 = Mop_ManCubeIn( p, Vec_IntEntry(vGroup, c1) );
+ pCube2 = Mop_ManCubeIn( p, Vec_IntEntry(vGroup, c2) );
+ assert( Mop_ManCheckDist1(pCube1, pCube2, p->nWordsIn) );
- word * pCube = Mop_ManCubeIn( p, iCubeNew );
- word * pCube1 = Mop_ManCubeIn( p, Vec_IntEntry(vGroup, c1) );
- word * pCube2 = Mop_ManCubeIn( p, Vec_IntEntry(vGroup, c2) );
+ // skip those cubes that have frequently appearing variables
+ iVar = Mop_ManFindDiffVar( pCube1, pCube2, p->nWordsIn );
+ if ( Vec_IntEntry( vStats, iVar ) > nLimit )
+ continue;
+ Vec_IntPush( vToFree, c1 );
+ Vec_IntPush( vToFree, c2 );
- assert( Mop_ManCheckDist1(pCube1, pCube2, p->nWordsIn) );
+ iCubeNew = Vec_IntPop( p->vFree );
+ pCube = Mop_ManCubeIn( p, iCubeNew );
for ( w = 0; w < p->nWordsIn; w++ )
pCube[w] = pCube1[w] & pCube2[w];
@@ -467,13 +516,15 @@ int Mop_ManMergeDist1Pairs( Mop_Man_t * p, Vec_Int_t * vGroup, Vec_Int_t * vGrou
Vec_IntPush( vGroupPrev, iCubeNew );
}
- Vec_IntForEachEntry( vPairsNew, c1, i )
+// Vec_IntForEachEntry( vPairsNew, c1, i )
+ Vec_IntForEachEntry( vToFree, c1, i )
{
if ( Vec_IntEntry(vGroup, c1) == -1 )
continue;
Vec_IntPush( p->vFree, Vec_IntEntry(vGroup, c1) );
Vec_IntWriteEntry( vGroup, c1, -1 );
}
+ Vec_IntFree( vToFree );
if ( Vec_IntSize(vPairsNew) > 0 )
Map_ManGroupCompact( vGroup );
Vec_IntFree( vPairs );
@@ -529,7 +580,7 @@ int Mop_ManMergeDist1Pairs2( Mop_Man_t * p, Vec_Int_t * vGroup, Vec_Int_t * vGro
Map_ManGroupCompact( vGroup );
return Count;
}
-int Mop_ManMergeDist1All( Mop_Man_t * p, Vec_Wec_t * vGroups )
+int Mop_ManMergeDist1All( Mop_Man_t * p, Vec_Wec_t * vGroups, Vec_Int_t * vStats, int nLimit )
{
Vec_Int_t * vGroup;
int i, nEqual, nReduce, Count = 0;
@@ -544,7 +595,7 @@ int Mop_ManMergeDist1All( Mop_Man_t * p, Vec_Wec_t * vGroups )
return -1;
}
nEqual = Mop_ManRemoveIdentical( p, vGroup );
- nReduce = Mop_ManMergeDist1Pairs( p, vGroup, Vec_WecEntry(vGroups, i-1) );
+ nReduce = Mop_ManMergeDist1Pairs( p, vGroup, Vec_WecEntry(vGroups, i-1), vStats, nLimit );
//Mop_ManMergeDist1Pairs2( p, vGroup, Vec_WecEntry(vGroups, i-1) );
Count += nEqual + nReduce;
//printf( "Group %3d : Equal =%5d. Reduce =%5d.\n", i, nEqual, nReduce );
@@ -599,16 +650,20 @@ void Mop_ManReduce2( Mop_Man_t * p )
{
abctime clk = Abc_Clock();
int nCubes = Vec_IntSize(p->vCubes);
+ Vec_Int_t * vStats = Mop_ManCollectStats( p );
Vec_Wec_t * vGroups = Mop_ManCreateGroups( p );
+ int nLimit = ABC_INFINITY; // 5 * Vec_IntSum(vStats) / Vec_IntSize(vStats) + 1;
int nOutLits = Mop_ManCountOutputLits( p );
int Count1 = Mop_ManMergeContainAll( p, vGroups );
- int Count2 = Mop_ManMergeDist1All( p, vGroups );
+ int Count2 = Mop_ManMergeDist1All( p, vGroups, vStats, nLimit );
int Count3 = Mop_ManMergeContainAll( p, vGroups );
- int Count4 = Mop_ManMergeDist1All( p, vGroups );
+ int Count4 = Mop_ManMergeDist1All( p, vGroups, vStats, nLimit );
int Count5 = Mop_ManMergeContainAll( p, vGroups );
int Removed = Mop_ManUnCreateGroups( p, vGroups );
int nOutLits2 = Mop_ManCountOutputLits( p );
Vec_WecFree( vGroups );
+//Vec_IntPrint( vStats );
+ Vec_IntFree( vStats );
assert( Removed == Count1 + Count2 + Count3 );
// report
printf( "Cubes: %d -> %d. C = %d. M = %d. C = %d. M = %d. C = %d. Output lits: %d -> %d. ",
diff --git a/src/base/wlc/wlc.h b/src/base/wlc/wlc.h
index 51152fa8..bb5c4bfe 100644
--- a/src/base/wlc/wlc.h
+++ b/src/base/wlc/wlc.h
@@ -259,7 +259,7 @@ extern Vec_Int_t * Wlc_NtkFindUifableMultiplierPairs( Wlc_Ntk_t * p );
extern Wlc_Ntk_t * Wlc_NtkAbstractNodes( Wlc_Ntk_t * pNtk, Vec_Int_t * vNodes );
extern Wlc_Ntk_t * Wlc_NtkUifNodePairs( Wlc_Ntk_t * pNtk, Vec_Int_t * vPairs );
/*=== wlcBlast.c ========================================================*/
-extern Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int fGiaSimple, int fAddOutputs );
+extern Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int iOutput, int nRange, int fGiaSimple, int fAddOutputs, int fBooth );
/*=== wlcCom.c ========================================================*/
extern void Wlc_SetNtk( Abc_Frame_t * pAbc, Wlc_Ntk_t * pNtk );
/*=== wlcNtk.c ========================================================*/
diff --git a/src/base/wlc/wlcBlast.c b/src/base/wlc/wlcBlast.c
index 79ad3659..c86c7cf0 100644
--- a/src/base/wlc/wlcBlast.c
+++ b/src/base/wlc/wlcBlast.c
@@ -143,16 +143,19 @@ void Wlc_BlastShiftRightInt( Gia_Man_t * pNew, int * pNum, int nNum, int * pShif
void Wlc_BlastShiftRight( Gia_Man_t * pNew, int * pNum, int nNum, int * pShift, int nShift, int fSticky, Vec_Int_t * vRes )
{
int nShiftMax = Abc_Base2Log(nNum);
+ int * pShiftNew = ABC_ALLOC( int, nShift );
+ memcpy( pShiftNew, pShift, sizeof(int)*nShift );
if ( nShiftMax < nShift )
{
- int i, iRes = pShift[nShiftMax];
+ int i, iRes = pShiftNew[nShiftMax];
for ( i = nShiftMax + 1; i < nShift; i++ )
- iRes = Gia_ManHashOr( pNew, iRes, pShift[i] );
- pShift[nShiftMax++] = iRes;
+ iRes = Gia_ManHashOr( pNew, iRes, pShiftNew[i] );
+ pShiftNew[nShiftMax++] = iRes;
}
else
nShiftMax = nShift;
- Wlc_BlastShiftRightInt( pNew, pNum, nNum, pShift, nShiftMax, fSticky, vRes );
+ Wlc_BlastShiftRightInt( pNew, pNum, nNum, pShiftNew, nShiftMax, fSticky, vRes );
+ ABC_FREE( pShiftNew );
}
void Wlc_BlastShiftLeftInt( Gia_Man_t * pNew, int * pNum, int nNum, int * pShift, int nShift, int fSticky, Vec_Int_t * vRes )
{
@@ -176,16 +179,19 @@ void Wlc_BlastShiftLeftInt( Gia_Man_t * pNew, int * pNum, int nNum, int * pShift
void Wlc_BlastShiftLeft( Gia_Man_t * pNew, int * pNum, int nNum, int * pShift, int nShift, int fSticky, Vec_Int_t * vRes )
{
int nShiftMax = Abc_Base2Log(nNum);
+ int * pShiftNew = ABC_ALLOC( int, nShift );
+ memcpy( pShiftNew, pShift, sizeof(int)*nShift );
if ( nShiftMax < nShift )
{
- int i, iRes = pShift[nShiftMax];
+ int i, iRes = pShiftNew[nShiftMax];
for ( i = nShiftMax + 1; i < nShift; i++ )
- iRes = Gia_ManHashOr( pNew, iRes, pShift[i] );
- pShift[nShiftMax++] = iRes;
+ iRes = Gia_ManHashOr( pNew, iRes, pShiftNew[i] );
+ pShiftNew[nShiftMax++] = iRes;
}
else
nShiftMax = nShift;
- Wlc_BlastShiftLeftInt( pNew, pNum, nNum, pShift, nShiftMax, fSticky, vRes );
+ Wlc_BlastShiftLeftInt( pNew, pNum, nNum, pShiftNew, nShiftMax, fSticky, vRes );
+ ABC_FREE( pShiftNew );
}
void Wlc_BlastRotateRight( Gia_Man_t * pNew, int * pNum, int nNum, int * pShift, int nShift, Vec_Int_t * vRes )
{
@@ -674,6 +680,7 @@ void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vL
Vec_IntPush( vProd, 0 );
assert( Vec_IntSize(vProd) == 2 );
}
+// Vec_WecPrint( vProds, 0 );
vLevel = Vec_WecEntry( vLevels, 0 );
Vec_IntClear( vRes );
@@ -684,7 +691,9 @@ void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vL
Vec_IntPush( vRes, Vec_IntEntry(vProd, 0) );
Vec_IntPush( vLevel, Vec_IntEntry(vProd, 1) );
}
- Wlc_BlastAdder( pNew, Vec_IntArray(vRes), Vec_IntArray(vLevel), nSize );
+ Vec_IntPush( vRes, 0 );
+ Vec_IntPush( vLevel, 0 );
+ Wlc_BlastAdder( pNew, Vec_IntArray(vRes), Vec_IntArray(vLevel), Vec_IntSize(vRes) );
}
void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes )
{
@@ -728,6 +737,81 @@ void Wlc_BlastSquare( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vTmp,
Vec_WecFree( vProds );
Vec_WecFree( vLevels );
}
+void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned )
+{
+ Vec_Wec_t * vProds = Vec_WecStart( nArgA + nArgB + 3 );
+ Vec_Wec_t * vLevels = Vec_WecStart( nArgA + nArgB + 3 );
+ int FillA = fSigned ? pArgA[nArgA-1] : 0;
+ int FillB = fSigned ? pArgB[nArgB-1] : 0;
+ int i, k, Sign;
+ // create new arguments
+ Vec_Int_t * vArgB = Vec_IntAlloc( nArgB + 3 );
+ Vec_IntPush( vArgB, 0 );
+ for ( i = 0; i < nArgB; i++ )
+ Vec_IntPush( vArgB, pArgB[i] );
+ Vec_IntPush( vArgB, FillB );
+ if ( Vec_IntSize(vArgB) % 2 == 0 )
+ Vec_IntPush( vArgB, FillB );
+ assert( Vec_IntSize(vArgB) % 2 == 1 );
+ // iterate through bit-pairs
+ for ( k = 0; k+2 < Vec_IntSize(vArgB); k+=2 )
+ {
+ int pp = -1;
+ int Q2jM1 = Vec_IntEntry(vArgB, k); // q(2*j-1)
+ int Q2j = Vec_IntEntry(vArgB, k+1); // q(2*j+0)
+ int Q2jP1 = Vec_IntEntry(vArgB, k+2); // q(2*j+1)
+ int Neg = Q2jP1;
+ int One = Gia_ManHashXor( pNew, Q2j, Q2jM1 );
+ int Two = Gia_ManHashMux( pNew, Neg, Gia_ManHashAnd(pNew, Abc_LitNot(Q2j), Abc_LitNot(Q2jM1)), Gia_ManHashAnd(pNew, Q2j, Q2jM1) );
+ for ( i = 0; i <= nArgA; i++ )
+ {
+ int This = i == nArgA ? FillA : pArgA[i];
+ int Prev = i ? pArgA[i-1] : 0;
+ int Part = Gia_ManHashOr( pNew, Gia_ManHashAnd(pNew, One, This), Gia_ManHashAnd(pNew, Two, Prev) );
+
+ pp = Gia_ManHashXor( pNew, Part, Neg );
+
+ if ( pp == 0 )
+ continue;
+ Vec_WecPush( vProds, k+i, pp );
+ Vec_WecPush( vLevels, k+i, 0 );
+ }
+ // perform sign extension
+ Sign = fSigned ? pp : Neg;
+ if ( k == 0 )
+ {
+ Vec_WecPush( vProds, k+i, Sign );
+ Vec_WecPush( vLevels, k+i, 0 );
+
+ Vec_WecPush( vProds, k+i+1, Sign );
+ Vec_WecPush( vLevels, k+i+1, 0 );
+
+ Vec_WecPush( vProds, k+i+2, Abc_LitNot(Sign) );
+ Vec_WecPush( vLevels, k+i+2, 0 );
+ }
+ else
+ {
+ Vec_WecPush( vProds, k+i, Abc_LitNot(Sign) );
+ Vec_WecPush( vLevels, k+i, 0 );
+
+ Vec_WecPush( vProds, k+i+1, 1 );
+ Vec_WecPush( vLevels, k+i+1, 0 );
+ }
+ // add neg to the first column
+ if ( Neg == 0 )
+ continue;
+ Vec_WecPush( vProds, k, Neg );
+ Vec_WecPush( vLevels, k, 0 );
+ }
+ //Vec_WecPrint( vProds, 0 );
+
+ Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes );
+
+ Vec_WecFree( vProds );
+ Vec_WecFree( vLevels );
+ Vec_IntFree( vArgB );
+}
+
/**Function*************************************************************
@@ -740,7 +824,7 @@ void Wlc_BlastSquare( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vTmp,
SeeAlso []
***********************************************************************/
-Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int fGiaSimple, int fAddOutputs )
+Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int iOutput, int nOutputRange, int fGiaSimple, int fAddOutputs, int fBooth )
{
int fVerbose = 0;
int fUseOldMultiplierBlasting = 0;
@@ -1149,9 +1233,12 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int fGiaSimple,
int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, fSigned );
if ( Wlc_NtkCountConstBits(pArg0, nRangeMax) < Wlc_NtkCountConstBits(pArg1, nRangeMax) )
ABC_SWAP( int *, pArg0, pArg1 );
- Wlc_BlastMultiplier( pNew, pArg0, pArg1, nRangeMax, nRangeMax, vTemp2, vRes, fSigned );
+ if ( fBooth )
+ Wlc_BlastBooth( pNew, pArg0, pArg1, nRange0, nRange1, vRes, fSigned );
+ else
+ Wlc_BlastMultiplier( pNew, pArg0, pArg1, nRangeMax, nRangeMax, vTemp2, vRes, fSigned );
//Wlc_BlastMultiplier3( pNew, pArg0, pArg1, nRange0, nRange1, vRes );
- if ( nRange > nRangeMax + nRangeMax )
+ if ( nRange > Vec_IntSize(vRes) )
Vec_IntFillExtra( vRes, nRange, fSigned ? Vec_IntEntryLast(vRes) : 0 );
else
Vec_IntShrink( vRes, nRange );
@@ -1233,6 +1320,9 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int fGiaSimple,
// create COs
Wlc_NtkForEachCo( p, pObj, i )
{
+ // skip all outputs except the given ones
+ if ( iOutput >= 0 && (i < iOutput || i >= iOutput + nOutputRange) )
+ continue;
// create additional PO literals
if ( vAddOutputs && pObj->fIsFi )
{
diff --git a/src/base/wlc/wlcCom.c b/src/base/wlc/wlcCom.c
index 77bf36ba..2c504127 100644
--- a/src/base/wlc/wlcCom.c
+++ b/src/base/wlc/wlcCom.c
@@ -128,10 +128,10 @@ int Abc_CommandReadWlc( Abc_Frame_t * pAbc, int argc, char ** argv )
switch ( c )
{
case 'o':
- fPrintTree ^= 1;
+ fOldParser ^= 1;
break;
case 'p':
- fOldParser ^= 1;
+ fPrintTree ^= 1;
break;
case 'v':
fVerbose ^= 1;
@@ -338,12 +338,34 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv )
Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc);
Vec_Int_t * vBoxIds = NULL;
Gia_Man_t * pNew = NULL;
- int c, fGiaSimple = 0, fAddOutputs = 0, fMulti = 0, fVerbose = 0;
+ int c, iOutput = -1, nOutputRange = 2, fGiaSimple = 0, fAddOutputs = 0, fMulti = 0, fBooth = 0, fVerbose = 0;
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "comvh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ORcombvh" ) ) != EOF )
{
switch ( c )
{
+ case 'O':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ iOutput = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( iOutput < 0 )
+ goto usage;
+ break;
+ case 'R':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nOutputRange = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nOutputRange < 0 )
+ goto usage;
+ break;
case 'c':
fGiaSimple ^= 1;
break;
@@ -353,6 +375,9 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'm':
fMulti ^= 1;
break;
+ case 'b':
+ fBooth ^= 1;
+ break;
case 'v':
fVerbose ^= 1;
break;
@@ -373,8 +398,13 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv )
if ( vBoxIds == NULL )
Abc_Print( 1, "Warning: There is no multipliers in the design.\n" );
}
+ if ( iOutput >= 0 && iOutput + nOutputRange > Wlc_NtkPoNum(pNtk) )
+ {
+ Abc_Print( 1, "Abc_CommandBlast(): The output range [%d:%d] is incorrect.\n", iOutput, iOutput + nOutputRange - 1 );
+ return 0;
+ }
// transform
- pNew = Wlc_NtkBitBlast( pNtk, vBoxIds, fGiaSimple, fAddOutputs );
+ pNew = Wlc_NtkBitBlast( pNtk, vBoxIds, iOutput, nOutputRange, fGiaSimple, fAddOutputs, fBooth );
Vec_IntFreeP( &vBoxIds );
if ( pNew == NULL )
{
@@ -384,11 +414,14 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_FrameUpdateGia( pAbc, pNew );
return 0;
usage:
- Abc_Print( -2, "usage: %%blast [-comvh]\n" );
+ Abc_Print( -2, "usage: %%blast [-OR num] [-combvh]\n" );
Abc_Print( -2, "\t performs bit-blasting of the word-level design\n" );
+ Abc_Print( -2, "\t-O num : zero-based index of the first word-level PO to bit-blast [default = %d]\n", iOutput );
+ Abc_Print( -2, "\t-R num : the total number of word-level POs to bit-blast [default = %d]\n", nOutputRange );
Abc_Print( -2, "\t-c : toggle using AIG w/o const propagation and strashing [default = %s]\n", fGiaSimple? "yes": "no" );
Abc_Print( -2, "\t-o : toggle using additional POs on the word-level boundaries [default = %s]\n", fAddOutputs? "yes": "no" );
Abc_Print( -2, "\t-m : toggle creating boxes for all multipliers in the design [default = %s]\n", fMulti? "yes": "no" );
+ Abc_Print( -2, "\t-b : toggle generating radix-4 Booth multipliers [default = %s]\n", fBooth? "yes": "no" );
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;
diff --git a/src/base/wlc/wlcReadSmt.c b/src/base/wlc/wlcReadSmt.c
index ed6092a5..fcd47274 100644
--- a/src/base/wlc/wlcReadSmt.c
+++ b/src/base/wlc/wlcReadSmt.c
@@ -276,13 +276,9 @@ static inline int Smt_PrsCreateNode( Wlc_Ntk_t * pNtk, int Type, int fSigned, in
assert( fSigned >= 0 );
Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj), vFanins );
if ( fSigned )
- {
Wlc_NtkObj(pNtk, iObj)->Signed = fSigned;
-// if ( Vec_IntSize(vFanins) > 0 )
-// Wlc_NtkObj(pNtk, Vec_IntEntry(vFanins, 0))->Signed = fSigned;
-// if ( Vec_IntSize(vFanins) > 1 )
-// Wlc_NtkObj(pNtk, Vec_IntEntry(vFanins, 1))->Signed = fSigned;
- }
+ if ( Type == WLC_OBJ_SHIFT_RA )
+ Wlc_NtkObj(pNtk, iObj)->Signed = 1;
if ( pName == NULL )
{
sprintf( Buffer, "_n%d_", iObj );
@@ -511,6 +507,13 @@ Wlc_Ntk_t * Smt_PrsBuild( Smt_Prs_t * p )
// skip ()
Fan = Vec_IntEntry(vFans, 2);
assert( !Smt_EntryIsName(Fan) );
+ vFans2 = Smt_VecEntryNode(p, vFans, 2);
+ if ( Vec_IntSize(vFans2) > 0 )
+ {
+ printf( "File parsing error: Uninterpreted functions are not supported.\n" );
+ Wlc_NtkFree( pNtk ); pNtk = NULL;
+ goto finish;
+ }
// check type (Bool or BitVec)
Fan = Vec_IntEntry(vFans, 3);
if ( Smt_EntryIsName(Fan) )
@@ -921,6 +924,13 @@ Wlc_Ntk_t * Smt_PrsBuild2( Smt_Prs_t * p )
// skip ()
Fan = Vec_IntEntry(vFans, 2);
assert( !Smt_EntryIsName(Fan) );
+ vFans2 = Smt_VecEntryNode(p, vFans, 2);
+ if ( Vec_IntSize(vFans2) > 0 )
+ {
+ printf( "File parsing error: Uninterpreted functions are not supported.\n" );
+ Wlc_NtkFree( pNtk ); pNtk = NULL;
+ goto finish;
+ }
// check type (Bool or BitVec)
Fan = Vec_IntEntry(vFans, 3);
if ( Smt_EntryIsName(Fan) )
diff --git a/src/base/wlc/wlcReadVer.c b/src/base/wlc/wlcReadVer.c
index 824cf80b..08dc8e98 100644
--- a/src/base/wlc/wlcReadVer.c
+++ b/src/base/wlc/wlcReadVer.c
@@ -1265,10 +1265,10 @@ Wlc_Ntk_t * Wlc_ReadVer( char * pFileName )
// derive topological order
pNtk = Wlc_NtkDupDfs( p->pNtk );
Wlc_NtkTransferNames( pNtk, p->pNtk );
+ pNtk->pSpec = Abc_UtilStrsav( pFileName );
finish:
Wlc_PrsPrintErrorMessage( p );
Wlc_PrsStop( p );
- pNtk->pSpec = Abc_UtilStrsav( pFileName );
return pNtk;
}
@@ -1291,7 +1291,7 @@ void Io_ReadWordTest( char * pFileName )
return;
Wlc_WriteVer( pNtk, "test.v", 0, 0 );
- pNew = Wlc_NtkBitBlast( pNtk, NULL, 0, 0 );
+ pNew = Wlc_NtkBitBlast( pNtk, NULL, -1, 0, 0, 0, 0 );
Gia_AigerWrite( pNew, "test.aig", 0, 0 );
Gia_ManStop( pNew );
diff --git a/src/base/wlc/wlcSim.c b/src/base/wlc/wlcSim.c
index 73d5307f..20ac8c61 100644
--- a/src/base/wlc/wlcSim.c
+++ b/src/base/wlc/wlcSim.c
@@ -129,7 +129,7 @@ Vec_Ptr_t * Wlc_NtkSimulate( Wlc_Ntk_t * p, Vec_Int_t * vNodes, int nWords, int
{
Gia_Obj_t * pObj;
Vec_Ptr_t * vOne, * vRes;
- Gia_Man_t * pGia = Wlc_NtkBitBlast( p, NULL, 0, 0 );
+ Gia_Man_t * pGia = Wlc_NtkBitBlast( p, NULL, -1, 0, 0, 0, 0 );
Wlc_Obj_t * pWlcObj;
int f, i, k, w, nBits, Counter = 0;
// allocate simulation info for one timeframe
diff --git a/src/map/if/if.h b/src/map/if/if.h
index 0282a1bd..ca7e0411 100644
--- a/src/map/if/if.h
+++ b/src/map/if/if.h
@@ -124,6 +124,7 @@ struct If_Par_t_
int fDelayOptLut; // delay optimization for LUTs
int fDsdBalance; // special delay optimization
int fUserRecLib; // use recorded library
+ int fUserSesLib; // use SAT-based synthesis
int fBidec; // use bi-decomposition
int fUse34Spec; // use specialized matching
int fUseBat; // use one specialized feature
@@ -263,6 +264,7 @@ struct If_Man_t_
int nBestCutSmall[2];
int nCountNonDec[2];
Vec_Int_t * vCutData; // cut data storage
+ int pArrTimeProfile[IF_MAX_FUNC_LUTSIZE];
// timing manager
Tim_Man_t * pManTim;
@@ -616,6 +618,7 @@ extern void If_ManDerefNodeCutSet( If_Man_t * p, If_Obj_t * pObj );
extern void If_ManDerefChoiceCutSet( If_Man_t * p, If_Obj_t * pObj );
extern void If_ManSetupSetAll( If_Man_t * p, int nCrossCut );
/*=== ifMap.c =============================================================*/
+extern int * If_CutArrTimeProfile( If_Man_t * p, If_Cut_t * pCut );
extern void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess, int fFirst );
extern void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess );
extern int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fPreprocess, int fFirst, char * pLabel );
diff --git a/src/map/if/ifCut.c b/src/map/if/ifCut.c
index 9e0c5a70..9b8d75ad 100644
--- a/src/map/if/ifCut.c
+++ b/src/map/if/ifCut.c
@@ -753,7 +753,7 @@ void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut )
if ( !pCut->fUseless &&
(p->pPars->fUseDsd || p->pPars->fUseBat ||
- p->pPars->pLutStruct || p->pPars->fUserRecLib ||
+ p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib ||
p->pPars->fEnableCheck07 || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec ||
p->pPars->fUseDsdTune || p->pPars->fEnableCheck75 || p->pPars->fEnableCheck75u) )
{
diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c
index c4053f52..76d3c757 100644
--- a/src/map/if/ifMap.c
+++ b/src/map/if/ifMap.c
@@ -28,7 +28,8 @@ ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
extern char * Dau_DsdMerge( char * pDsd0i, int * pPerm0, char * pDsd1i, int * pPerm1, int fCompl0, int fCompl1, int nVars );
-extern int If_CutDelayRecCost3(If_Man_t* p, If_Cut_t* pCut, If_Obj_t * pObj);
+extern int If_CutDelayRecCost3( If_Man_t* p, If_Cut_t* pCut, If_Obj_t * pObj );
+extern int Abc_ExactDelayCost( word * pTruth, int nVars, int * pArrTimeProfile, char * pPerm, int * Cost, int AigLevel );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
@@ -80,6 +81,25 @@ float If_CutDelaySpecial( If_Man_t * p, If_Cut_t * pCut, int fCarry )
return Delay;
}
+/**Function*************************************************************
+
+ Synopsis [Returns arrival time profile of the cut.]
+
+ Description [The procedure returns static storage, which should not be
+ deallocated and is only valid until before the procedure is called again.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int * If_CutArrTimeProfile( If_Man_t * p, If_Cut_t * pCut )
+{
+ int i;
+ for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+ p->pArrTimeProfile[i] = (int)If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay;
+ return p->pArrTimeProfile;
+}
/**Function*************************************************************
@@ -99,7 +119,8 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep
If_Cut_t * pCut0R, * pCut1R;
int fFunc0R, fFunc1R;
int i, k, v, iCutDsd, fChange;
- int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUseDsdTune || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->pLutStruct != NULL;
+ int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib ||
+ p->pPars->fUseDsdTune || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->pLutStruct != NULL;
int fUseAndCut = (p->pPars->nAndDelay > 0) || (p->pPars->nAndArea > 0);
assert( !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->pCutSet->nCuts > 0 );
assert( !If_ObjIsAnd(pObj->pFanin1) || pObj->pFanin1->pCutSet->nCuts > 0 );
@@ -127,6 +148,19 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep
pCut->Delay = If_CutDsdBalanceEval( p, pCut, NULL );
else if ( p->pPars->fUserRecLib )
pCut->Delay = If_CutDelayRecCost3( p, pCut, pObj );
+ else if ( p->pPars->fUserSesLib )
+ {
+ int Cost = 0;
+ pCut->fUser = 1;
+ pCut->Delay = (float)Abc_ExactDelayCost( If_CutTruthW(p, pCut), If_CutLeaveNum(pCut), If_CutArrTimeProfile(p, pCut), If_CutPerm(pCut), &Cost, (int)pObj->Level );
+ if ( Cost == ABC_INFINITY )
+ {
+ for ( v = 0; v < If_CutLeaveNum(pCut); v++ )
+ If_CutPerm(pCut)[v] = IF_BIG_CHAR;
+ pCut->Cost = IF_COST_MAX;
+ pCut->fUseless = 1;
+ }
+ }
else if ( p->pPars->fDelayOptLut )
pCut->Delay = If_CutLutBalanceEval( p, pCut );
else if( p->pPars->nGateSize > 0 )
@@ -333,22 +367,23 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep
continue;
// check if the cut satisfies the required times
if ( p->pPars->fDelayOpt )
- {
pCut->Delay = If_CutSopBalanceEval( p, pCut, NULL );
-// if ( pCut->Delay >= pObj->Level && pCut->nLeaves > 2 )
-// pCut->Delay += 1;
- }
else if ( p->pPars->fDsdBalance )
- {
pCut->Delay = If_CutDsdBalanceEval( p, pCut, NULL );
-// if ( pCut->Delay >= pObj->Level && pCut->nLeaves > 2 )
-// pCut->Delay += 1;
- }
else if ( p->pPars->fUserRecLib )
- {
pCut->Delay = If_CutDelayRecCost3( p, pCut, pObj );
-// if ( pCut->Delay >= pObj->Level && pCut->nLeaves > 2 )
-// pCut->Delay += 1;
+ else if ( p->pPars->fUserSesLib )
+ {
+ int Cost = 0;
+ pCut->fUser = 1;
+ pCut->Delay = (float)Abc_ExactDelayCost( If_CutTruthW(p, pCut), If_CutLeaveNum(pCut), If_CutArrTimeProfile(p, pCut), If_CutPerm(pCut), &Cost, (int)pObj->Level );
+ if ( Cost == ABC_INFINITY )
+ {
+ for ( v = 0; v < If_CutLeaveNum(pCut); v++ )
+ If_CutPerm(pCut)[v] = IF_BIG_CHAR;
+ pCut->Cost = IF_COST_MAX;
+ pCut->fUseless = 1;
+ }
}
else if ( p->pPars->fDelayOptLut )
pCut->Delay = If_CutLutBalanceEval( p, pCut );
@@ -378,7 +413,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep
if ( !fPreprocess || pCutSet->ppCuts[0]->Delay <= pObj->Required + p->fEpsilon )
{
If_CutCopy( p, If_ObjCutBest(pObj), pCutSet->ppCuts[0] );
- if(p->pPars->fUserRecLib)
+ if ( p->pPars->fUserRecLib || p->pPars->fUserSesLib )
assert(If_ObjCutBest(pObj)->Cost < IF_COST_MAX && If_ObjCutBest(pObj)->Delay < ABC_INFINITY);
}
// add the trivial cut to the set
@@ -421,7 +456,7 @@ void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fP
If_Set_t * pCutSet;
If_Obj_t * pTemp;
If_Cut_t * pCutTemp, * pCut;
- int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUse34Spec;
+ int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUse34Spec;
assert( pObj->pEquiv != NULL );
// prepare
diff --git a/src/opt/fxch/Fxch.c b/src/opt/fxch/Fxch.c
index 6c3983ef..84a4c566 100644
--- a/src/opt/fxch/Fxch.c
+++ b/src/opt/fxch/Fxch.c
@@ -15,7 +15,6 @@
Revision []
***********************************************************************/
-
#include "Fxch.h"
ABC_NAMESPACE_IMPL_START
@@ -26,6 +25,128 @@ ABC_NAMESPACE_IMPL_START
/**Function*************************************************************
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxch_CubesGruping(Fxch_Man_t* pFxchMan)
+{
+ Vec_Int_t* vCube;
+ int iCube, nOutputs, SizeOutputID;
+ Hsh_VecMan_t* pCubeHash;
+
+ /* Identify the number of Outputs and create the translation table */
+ pFxchMan->vTranslation = Vec_IntAlloc( 32 );
+ Vec_WecForEachLevel( pFxchMan->vCubes, vCube, iCube )
+ {
+ int Id = Vec_IntEntry( vCube, 0 );
+ int iTranslation = Vec_IntFind( pFxchMan->vTranslation, Id );
+
+ if ( iTranslation == -1 )
+ Vec_IntPush( pFxchMan->vTranslation, Id );
+ }
+ nOutputs = Vec_IntSize( pFxchMan->vTranslation );
+
+ /* Size of the OutputID in number o ints */
+ SizeOutputID = ( nOutputs >> 5 ) + ( ( nOutputs & 31 ) > 0 );
+
+ /* Initialize needed structures */
+ pFxchMan->vOutputID = Vec_IntAlloc( 4096 );
+ pFxchMan->pTempOutputID = ABC_CALLOC( int, SizeOutputID );
+ pFxchMan->nSizeOutputID = SizeOutputID;
+
+ pCubeHash = Hsh_VecManStart( 1024 );
+
+ /* Identify equal cubes */
+ Vec_WecForEachLevel( pFxchMan->vCubes, vCube, iCube )
+ {
+ int Id = Vec_IntEntry( vCube, 0 );
+ int iTranslation = Vec_IntFind( pFxchMan->vTranslation, Id );
+ int i, iCubeNoID, Temp, * pEntry;
+ Vec_IntWriteEntry( vCube, 0, 0 ); // Clear ID, Outputs will be identified by it later
+
+ iCubeNoID = Hsh_VecManAdd( pCubeHash, vCube );
+ Temp = ( 1 << ( iTranslation & 31 ) );
+ if ( iCubeNoID == Vec_IntSize( pFxchMan->vOutputID ) / SizeOutputID )
+ {
+ for ( i = 0; i < SizeOutputID; i++ )
+ pFxchMan->pTempOutputID[i] = 0;
+
+ pFxchMan->pTempOutputID[ iTranslation >> 5 ] = Temp;
+ Vec_IntPushArray( pFxchMan->vOutputID, pFxchMan->pTempOutputID, SizeOutputID );
+ }
+ else
+ {
+ Vec_IntClear( vCube );
+ pEntry = Vec_IntEntryP( pFxchMan->vOutputID, ( iCubeNoID * SizeOutputID ) + ( iTranslation >> 5 ) );
+ *pEntry |= Temp;
+ }
+ }
+
+ Hsh_VecManStop( pCubeHash );
+ Vec_WecRemoveEmpty( pFxchMan->vCubes );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxch_CubesUnGruping(Fxch_Man_t* pFxchMan)
+{
+ int iCube;
+ int i, j;
+ Vec_Int_t* vCube;
+ Vec_Int_t* vNewCube;
+
+ assert( Vec_WecSize( pFxchMan->vCubes ) == ( Vec_IntSize( pFxchMan->vOutputID ) / pFxchMan->nSizeOutputID ) );
+ Vec_WecForEachLevel( pFxchMan->vCubes, vCube, iCube )
+ {
+ int * pOutputID, nOnes;
+ if ( Vec_IntSize( vCube ) == 0 || Vec_IntEntry( vCube, 0 ) != 0 )
+ continue;
+
+ pOutputID = Vec_IntEntryP( pFxchMan->vOutputID, iCube * pFxchMan->nSizeOutputID );
+ nOnes = 0;
+
+ for ( i = 0; i < pFxchMan->nSizeOutputID; i++ )
+ nOnes += Fxch_CountOnes( (unsigned int) pOutputID[i] );
+
+ for ( i = 0; i < pFxchMan->nSizeOutputID && nOnes; i++ )
+ for ( j = 0; j < 32 && nOnes; j++ )
+ if ( pOutputID[i] & ( 1 << j ) )
+ {
+ if ( nOnes == 1 )
+ Vec_IntWriteEntry( vCube, 0, Vec_IntEntry( pFxchMan->vTranslation, ( i << 5 ) | j ) );
+ else
+ {
+ vNewCube = Vec_WecPushLevel( pFxchMan->vCubes );
+ Vec_IntAppend( vNewCube, vCube );
+ Vec_IntWriteEntry( vNewCube, 0, Vec_IntEntry( pFxchMan->vTranslation, (i << 5 ) | j ) );
+ }
+ nOnes -= 1;
+ }
+ }
+
+ Vec_IntFree( pFxchMan->vTranslation );
+ Vec_IntFree( pFxchMan->vOutputID );
+ ABC_FREE( pFxchMan->pTempOutputID );
+ return;
+}
+
+/**Function*************************************************************
+
Synopsis [ Performs fast extract with cube hashing on a set
of covers. ]
@@ -47,6 +168,7 @@ int Fxch_FastExtract( Vec_Wec_t* vCubes,
int i;
TempTime = Abc_Clock();
+ Fxch_CubesGruping( pFxchMan );
Fxch_ManMapLiteralsIntoCubes( pFxchMan, ObjIdMax );
Fxch_ManGenerateLitHashKeys( pFxchMan );
Fxch_ManComputeLevel( pFxchMan );
@@ -61,6 +183,7 @@ int Fxch_FastExtract( Vec_Wec_t* vCubes,
Fxch_ManPrintStats( pFxchMan );
TempTime = Abc_Clock();
+
for ( i = 0; (!nMaxDivExt || i < nMaxDivExt) && Vec_QueTopPriority( pFxchMan->vDivPrio ) > 0.0; i++ )
{
int iDiv = Vec_QuePop( pFxchMan->vDivPrio );
@@ -70,6 +193,7 @@ int Fxch_FastExtract( Vec_Wec_t* vCubes,
Fxch_ManUpdate( pFxchMan, iDiv );
}
+
pFxchMan->timeExt = Abc_Clock() - TempTime;
if ( fVerbose )
@@ -80,9 +204,12 @@ int Fxch_FastExtract( Vec_Wec_t* vCubes,
Abc_PrintTime( 1, "[FXCH] +-> Extr", pFxchMan->timeExt );
}
+ Fxch_CubesUnGruping( pFxchMan );
Fxch_ManSCHashTablesFree( pFxchMan );
Fxch_ManFree( pFxchMan );
+
Vec_WecRemoveEmpty( vCubes );
+ Vec_WecSortByFirstInt( vCubes, 0 );
return 1;
}
diff --git a/src/opt/fxch/Fxch.h b/src/opt/fxch/Fxch.h
index 5781846c..8291e042 100644
--- a/src/opt/fxch/Fxch.h
+++ b/src/opt/fxch/Fxch.h
@@ -28,6 +28,9 @@
ABC_NAMESPACE_HEADER_START
+typedef unsigned char uint8_t;
+typedef unsigned int uint32_t;
+
////////////////////////////////////////////////////////////////////////
/// TYPEDEF DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
@@ -52,25 +55,22 @@ typedef struct Fxch_SCHashTable_Entry_t_ Fxch_SCHashTable_Entry_t;
* its literals.
*
*/
+
struct Fxch_SubCube_t_
{
- unsigned int Id,
- iCube;
- unsigned int iLit0 : 16,
- iLit1 : 16;
+ uint32_t Id,
+ iCube;
+ uint32_t iLit0 : 16,
+ iLit1 : 16;
};
/* Sub-cube Hash Table
- *
*/
struct Fxch_SCHashTable_Entry_t_
{
- Fxch_SubCube_t SCData;
-
- unsigned int iTable : 31,
- Used : 1;
- unsigned int iPrev,
- iNext;
+ Fxch_SubCube_t* vSCData;
+ uint32_t Size : 16,
+ Cap : 16;
};
struct Fxch_SCHashTable_t_
@@ -80,7 +80,6 @@ struct Fxch_SCHashTable_t_
Fxch_SCHashTable_Entry_t* pBins;
unsigned int nEntries,
SizeMask;
- Vec_Int_t* vCubeLinks;
/* Temporary data */
Vec_Int_t vSubCube0;
@@ -91,6 +90,7 @@ struct Fxch_Man_t_
{
/* user's data */
Vec_Wec_t* vCubes;
+ int nCubesInit;
int LitCountMax;
/* internal data */
@@ -107,12 +107,21 @@ struct Fxch_Man_t_
Vec_Int_t* vLevels; /* variable levels */
+ // Cube Grouping
+ Vec_Int_t* vTranslation;
+ Vec_Int_t* vOutputID;
+ int* pTempOutputID;
+ int nSizeOutputID;
+
// temporary data to update the data-structure when a divisor is extracted
- Vec_Int_t* vCubesS; /* cubes for the given single cube divisor */
- Vec_Int_t* vPairs; /* cube pairs for the given double cube divisor */
- Vec_Int_t* vCubeFree; // cube-free divisor
- Vec_Int_t* vDiv; // selected divisor
- Vec_Int_t* vSCC;
+ Vec_Int_t* vCubesS; /* cubes for the given single cube divisor */
+ Vec_Int_t* vPairs; /* cube pairs for the given double cube divisor */
+ Vec_Int_t* vCubeFree; // cube-free divisor
+ Vec_Int_t* vDiv; // selected divisor
+
+ Vec_Int_t* vCubesToRemove;
+ Vec_Int_t* vCubesToUpdate;
+ Vec_Int_t* vSCC;
/* Statistics */
abctime timeInit; /* Initialization time */
@@ -135,6 +144,15 @@ extern Vec_Wec_t* Abc_NtkFxRetrieve( Abc_Ntk_t* pNtk );
extern void Abc_NtkFxInsert( Abc_Ntk_t* pNtk, Vec_Wec_t* vCubes );
extern int Abc_NtkFxCheck( Abc_Ntk_t* pNtk );
+static inline int Fxch_CountOnes( unsigned num )
+{
+ num = ( num & 0x55555555 ) + ( ( num >> 1) & 0x55555555 );
+ num = ( num & 0x33333333 ) + ( ( num >> 2) & 0x33333333 );
+ num = ( num & 0x0F0F0F0F ) + ( ( num >> 4) & 0x0F0F0F0F );
+ num = ( num & 0x00FF00FF ) + ( ( num >> 8) & 0x00FF00FF );
+ return ( num & 0x0000FFFF ) + ( num >> 16 );
+}
+
/*===== Fxch.c =======================================================*/
int Abc_NtkFxchPerform( Abc_Ntk_t* pNtk, int nMaxDivExt, int fVerbose, int fVeryVerbose );
int Fxch_FastExtract( Vec_Wec_t* vCubes, int ObjIdMax, int nMaxDivExt, int fVerbose, int fVeryVerbose );
@@ -177,26 +195,25 @@ static inline int Fxch_ManGetLit( Fxch_Man_t* pFxchMan,
}
/*===== FxchSCHashTable.c ============================================*/
-Fxch_SCHashTable_t* Fxch_SCHashTableCreate( Fxch_Man_t* pFxchMan, Vec_Int_t* vCubeLinks, int nEntries );
+Fxch_SCHashTable_t* Fxch_SCHashTableCreate( Fxch_Man_t* pFxchMan, int nEntries );
void Fxch_SCHashTableDelete( Fxch_SCHashTable_t* );
int Fxch_SCHashTableInsert( Fxch_SCHashTable_t* pSCHashTable,
Vec_Wec_t* vCubes,
- unsigned int SubCubeID,
- unsigned int iSubCube,
- unsigned int iCube,
- unsigned int iLit0,
- unsigned int iLit1,
+ uint32_t SubCubeID,
+ uint32_t iCube,
+ uint32_t iLit0,
+ uint32_t iLit1,
char fUpdate );
+
int Fxch_SCHashTableRemove( Fxch_SCHashTable_t* pSCHashTable,
Vec_Wec_t* vCubes,
- unsigned int SubCubeID,
- unsigned int iSubCube,
- unsigned int iCube,
- unsigned int iLit0,
- unsigned int iLit1,
+ uint32_t SubCubeID,
+ uint32_t iCube,
+ uint32_t iLit0,
+ uint32_t iLit1,
char fUpdate );
unsigned int Fxch_SCHashTableMemory( Fxch_SCHashTable_t* );
diff --git a/src/opt/fxch/FxchDiv.c b/src/opt/fxch/FxchDiv.c
index 18c8bbfb..99c260c6 100644
--- a/src/opt/fxch/FxchDiv.c
+++ b/src/opt/fxch/FxchDiv.c
@@ -142,10 +142,20 @@ int Fxch_DivCreate( Fxch_Man_t* pFxchMan,
SC0_Lit1 = Fxch_ManGetLit( pFxchMan, pSubCube0->iCube, pSubCube0->iLit1 );
SC1_Lit1 = Fxch_ManGetLit( pFxchMan, pSubCube1->iCube, pSubCube1->iLit1 );
- Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit0, 0 ) );
- Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit0, 1 ) );
- Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit1, 0 ) );
- Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit1, 1 ) );
+ if ( SC0_Lit0 < SC1_Lit0 )
+ {
+ Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit0, 0 ) );
+ Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit0, 1 ) );
+ Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit1, 0 ) );
+ Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit1, 1 ) );
+ }
+ else
+ {
+ Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit0, 0 ) );
+ Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit0, 1 ) );
+ Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit1, 0 ) );
+ Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit1, 1 ) );
+ }
RetValue = Fxch_DivNormalize( pFxchMan->vCubeFree );
if ( RetValue == -1 )
diff --git a/src/opt/fxch/FxchMan.c b/src/opt/fxch/FxchMan.c
index 44695f91..19ce1461 100644
--- a/src/opt/fxch/FxchMan.c
+++ b/src/opt/fxch/FxchMan.c
@@ -15,7 +15,6 @@
Revision []
***********************************************************************/
-
#include "Fxch.h"
ABC_NAMESPACE_IMPL_START
@@ -25,7 +24,6 @@ ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
static inline int Fxch_ManSCAddRemove( Fxch_Man_t* pFxchMan,
unsigned int SubCubeID,
- unsigned int iSubCube,
unsigned int iCube,
unsigned int iLit0,
unsigned int iLit1,
@@ -37,13 +35,13 @@ static inline int Fxch_ManSCAddRemove( Fxch_Man_t* pFxchMan,
if ( fAdd )
{
ret = Fxch_SCHashTableInsert( pFxchMan->pSCHashTable, pFxchMan->vCubes,
- SubCubeID, iSubCube,
+ SubCubeID,
iCube, iLit0, iLit1, fUpdate );
}
else
{
ret = Fxch_SCHashTableRemove( pFxchMan->pSCHashTable, pFxchMan->vCubes,
- SubCubeID, iSubCube,
+ SubCubeID,
iCube, iLit0, iLit1, fUpdate );
}
@@ -63,26 +61,38 @@ static inline int Fxch_ManDivSingleCube( Fxch_Man_t* pFxchMan,
fSingleCube = 1,
fBase = 0;
- if ( Vec_IntSize(vCube) < 2 )
+ if ( Vec_IntSize( vCube ) < 2 )
return 0;
Vec_IntForEachEntryStart( vCube, Lit0, i, 1)
Vec_IntForEachEntryStart( vCube, Lit1, k, (i + 1) )
{
+ int * pOutputID, nOnes, j, z;
assert( Lit0 < Lit1 );
Vec_IntClear( pFxchMan->vCubeFree );
Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( Abc_LitNot( Lit0 ), 0 ) );
Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( Abc_LitNot( Lit1 ), 1 ) );
+ pOutputID = Vec_IntEntryP( pFxchMan->vOutputID, iCube * pFxchMan->nSizeOutputID );
+ nOnes = 0;
+
+ for ( j = 0; j < pFxchMan->nSizeOutputID; j++ )
+ nOnes += Fxch_CountOnes( pOutputID[j] );
+
+ if ( nOnes == 0 )
+ nOnes = 1;
+
if (fAdd)
{
- Fxch_DivAdd( pFxchMan, fUpdate, fSingleCube, fBase );
+ for ( z = 0; z < nOnes; z++ )
+ Fxch_DivAdd( pFxchMan, fUpdate, fSingleCube, fBase );
pFxchMan->nPairsS++;
}
else
{
- Fxch_DivRemove( pFxchMan, fUpdate, fSingleCube, fBase );
+ for ( z = 0; z < nOnes; z++ )
+ Fxch_DivRemove( pFxchMan, fUpdate, fSingleCube, fBase );
pFxchMan->nPairsS--;
}
}
@@ -98,15 +108,13 @@ static inline void Fxch_ManDivDoubleCube( Fxch_Man_t* pFxchMan,
Vec_Int_t* vLitHashKeys = pFxchMan->vLitHashKeys,
* vCube = Vec_WecEntry( pFxchMan->vCubes, iCube );
int SubCubeID = 0,
- nHashedSC = 0,
iLit0,
Lit0;
Vec_IntForEachEntryStart( vCube, Lit0, iLit0, 1)
SubCubeID += Vec_IntEntry( vLitHashKeys, Lit0 );
- Fxch_ManSCAddRemove( pFxchMan,
- SubCubeID, nHashedSC++,
+ Fxch_ManSCAddRemove( pFxchMan, SubCubeID,
iCube, 0, 0,
(char)fAdd, (char)fUpdate );
@@ -115,8 +123,7 @@ static inline void Fxch_ManDivDoubleCube( Fxch_Man_t* pFxchMan,
/* 1 Lit remove */
SubCubeID -= Vec_IntEntry( vLitHashKeys, Lit0 );
- pFxchMan->nPairsD += Fxch_ManSCAddRemove( pFxchMan,
- SubCubeID, nHashedSC++,
+ pFxchMan->nPairsD += Fxch_ManSCAddRemove( pFxchMan, SubCubeID,
iCube, iLit0, 0,
(char)fAdd, (char)fUpdate );
@@ -130,8 +137,7 @@ static inline void Fxch_ManDivDoubleCube( Fxch_Man_t* pFxchMan,
/* 2 Lit remove */
SubCubeID -= Vec_IntEntry( vLitHashKeys, Lit1 );
- pFxchMan->nPairsD += Fxch_ManSCAddRemove( pFxchMan,
- SubCubeID, nHashedSC++,
+ pFxchMan->nPairsD += Fxch_ManSCAddRemove( pFxchMan, SubCubeID,
iCube, iLit0, iLit1,
(char)fAdd, (char)fUpdate );
@@ -165,14 +171,20 @@ Fxch_Man_t* Fxch_ManAlloc( Vec_Wec_t* vCubes )
Fxch_Man_t* pFxchMan = ABC_CALLOC( Fxch_Man_t, 1 );
pFxchMan->vCubes = vCubes;
- pFxchMan->pDivHash = Hsh_VecManStart( 1000 );
- pFxchMan->vDivWeights = Vec_FltAlloc( 1000 );
- pFxchMan->vDivCubePairs = Vec_WecAlloc( 1000 );
- pFxchMan->vCubeFree = Vec_IntAlloc( 100 );
- pFxchMan->vDiv = Vec_IntAlloc( 100 );
+ pFxchMan->nCubesInit = Vec_WecSize( vCubes );
+
+ pFxchMan->pDivHash = Hsh_VecManStart( 1024 );
+ pFxchMan->vDivWeights = Vec_FltAlloc( 1024 );
+ pFxchMan->vDivCubePairs = Vec_WecAlloc( 1024 );
+
+ pFxchMan->vCubeFree = Vec_IntAlloc( 4 );
+ pFxchMan->vDiv = Vec_IntAlloc( 4 );
+
+ pFxchMan->vCubesS = Vec_IntAlloc( 128 );
+ pFxchMan->vPairs = Vec_IntAlloc( 128 );
+ pFxchMan->vCubesToUpdate = Vec_IntAlloc( 64 );
+ pFxchMan->vCubesToRemove = Vec_IntAlloc( 64 );
pFxchMan->vSCC = Vec_IntAlloc( 64 );
- pFxchMan->vCubesS = Vec_IntAlloc( 100 );
- pFxchMan->vPairs = Vec_IntAlloc( 100 );
return pFxchMan;
}
@@ -187,11 +199,16 @@ void Fxch_ManFree( Fxch_Man_t* pFxchMan )
Vec_QueFree( pFxchMan->vDivPrio );
Vec_WecFree( pFxchMan->vDivCubePairs );
Vec_IntFree( pFxchMan->vLevels );
+
Vec_IntFree( pFxchMan->vCubeFree );
Vec_IntFree( pFxchMan->vDiv );
- Vec_IntFree( pFxchMan->vSCC );
+
Vec_IntFree( pFxchMan->vCubesS );
Vec_IntFree( pFxchMan->vPairs );
+ Vec_IntFree( pFxchMan->vCubesToUpdate );
+ Vec_IntFree( pFxchMan->vCubesToRemove );
+ Vec_IntFree( pFxchMan->vSCC );
+
ABC_FREE( pFxchMan );
}
@@ -248,22 +265,19 @@ void Fxch_ManGenerateLitHashKeys( Fxch_Man_t* pFxchMan )
void Fxch_ManSCHashTablesInit( Fxch_Man_t* pFxchMan )
{
Vec_Wec_t* vCubes = pFxchMan->vCubes;
- Vec_Int_t* vCube,
- * vCubeLinks;
+ Vec_Int_t* vCube;
int iCube,
nTotalHashed = 0;
- vCubeLinks = Vec_IntAlloc( Vec_WecSize( vCubes ) + 1 );
Vec_WecForEachLevel( vCubes, vCube, iCube )
{
int nLits = Vec_IntSize( vCube ) - 1,
nSubCubes = nLits <= 2? nLits + 1: ( nLits * nLits + nLits ) / 2;
- Vec_IntPush( vCubeLinks, ( nTotalHashed + 1 ) );
nTotalHashed += nSubCubes + 1;
}
- pFxchMan->pSCHashTable = Fxch_SCHashTableCreate( pFxchMan, vCubeLinks, nTotalHashed );
+ pFxchMan->pSCHashTable = Fxch_SCHashTableCreate( pFxchMan, nTotalHashed );
}
void Fxch_ManSCHashTablesFree( Fxch_Man_t* pFxchMan )
@@ -364,56 +378,135 @@ static inline void Fxch_ManExtractDivFromCube( Fxch_Man_t* pFxchMan,
Vec_IntPush( vCube0, Abc_Var2Lit( iVarNew, 0 ) );
Vec_IntPush( vLitP, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) );
+ Vec_IntPush( pFxchMan->vCubesToUpdate, iCube0 );
pFxchMan->nLits--;
}
}
/* Extract divisor from cube pairs */
-static inline int Fxch_ManExtractDivFromCubePairs( Fxch_Man_t* pFxchMan,
+static inline void Fxch_ManExtractDivFromCubePairs( Fxch_Man_t* pFxchMan,
const int iVarNew )
{
/* For each pair (Ci, Cj) */
- int k = 0,
- iCube0, iCube1, i;
+ int iCube0, iCube1, i;
- Vec_Int_t* vLitP = Vec_WecEntry( pFxchMan->vLits, Vec_WecSize( pFxchMan->vLits ) - 2 ),
- * vLitN = Vec_WecEntry( pFxchMan->vLits, Vec_WecSize( pFxchMan->vLits ) - 1 );
Vec_IntForEachEntryDouble( pFxchMan->vPairs, iCube0, iCube1, i )
{
- int RetValue,
+ int j, Lit,
+ RetValue,
fCompl = 0;
+ int * pOutputID0, * pOutputID1;
- Vec_Int_t* vCube0 = Fxch_ManGetCube( pFxchMan, iCube0 ),
- * vCube1 = Fxch_ManGetCube( pFxchMan, iCube1 );
+ Vec_Int_t* vCube = NULL,
+ * vCube0 = Fxch_ManGetCube( pFxchMan, iCube0 ),
+ * vCube1 = Fxch_ManGetCube( pFxchMan, iCube1 ),
+ * vCube0Copy = Vec_IntDup( vCube0 ),
+ * vCube1Copy = Vec_IntDup( vCube1 );
- RetValue = Fxch_DivRemoveLits( vCube0, vCube1, pFxchMan->vDiv, &fCompl );
+ RetValue = Fxch_DivRemoveLits( vCube0Copy, vCube1Copy, pFxchMan->vDiv, &fCompl );
assert( RetValue == Vec_IntSize( pFxchMan->vDiv ) );
pFxchMan->nLits -= Vec_IntSize( pFxchMan->vDiv ) + Vec_IntSize( vCube1 ) - 2;
- /* Remove second cube */
- Vec_IntClear( vCube1 );
- Vec_IntWriteEntry( pFxchMan->vPairs, k++, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) );
+ /* Identify type of Extraction */
+ pOutputID0 = Vec_IntEntryP( pFxchMan->vOutputID, iCube0 * pFxchMan->nSizeOutputID );
+ pOutputID1 = Vec_IntEntryP( pFxchMan->vOutputID, iCube1 * pFxchMan->nSizeOutputID );
+ RetValue = 1;
+ for ( j = 0; j < pFxchMan->nSizeOutputID && RetValue; j++ )
+ RetValue = ( pOutputID0[j] == pOutputID1[j] );
+
+ /* Exact Extractraion */
+ if ( RetValue )
+ {
+ Vec_IntClear( vCube0 );
+ Vec_IntAppend( vCube0, vCube0Copy );
+ vCube = vCube0;
+
+ Vec_IntPush( pFxchMan->vCubesToUpdate, iCube0 );
+ Vec_IntClear( vCube1 );
+
+ /* Update Lit -> Cube mapping */
+ Vec_IntForEachEntry( pFxchMan->vDiv, Lit, j )
+ {
+ Vec_IntRemove( Vec_WecEntry( pFxchMan->vLits, Abc_Lit2Var( Lit ) ),
+ Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) );
+ Vec_IntRemove( Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Abc_Lit2Var( Lit ) ) ),
+ Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) );
+ }
+
+ }
+ /* Unexact Extraction */
+ else
+ {
+ for ( j = 0; j < pFxchMan->nSizeOutputID; j++ )
+ pFxchMan->pTempOutputID[j] = ( pOutputID0[j] & pOutputID1[j] );
+
+ /* Create new cube */
+ vCube = Vec_WecPushLevel( pFxchMan->vCubes );
+ Vec_IntAppend( vCube, vCube0Copy );
+ Vec_IntPushArray( pFxchMan->vOutputID, pFxchMan->pTempOutputID, pFxchMan->nSizeOutputID );
+ Vec_IntPush( pFxchMan->vCubesToUpdate, Vec_WecLevelId( pFxchMan->vCubes, vCube ) );
+
+ /* Update Lit -> Cube mapping */
+ Vec_IntForEachEntryStart( vCube, Lit, j, 1 )
+ Vec_WecPush( pFxchMan->vLits, Lit, Vec_WecLevelId( pFxchMan->vCubes, vCube ) );
+
+ /*********************************************************/
+ RetValue = 0;
+ for ( j = 0; j < pFxchMan->nSizeOutputID; j++ )
+ {
+ pFxchMan->pTempOutputID[j] = pOutputID0[j];
+ RetValue |= ( pOutputID0[j] & ~( pOutputID1[j] ) );
+ pOutputID0[j] &= ~( pOutputID1[j] );
+ }
+
+ if ( RetValue != 0 )
+ Vec_IntPush( pFxchMan->vCubesToUpdate, iCube0 );
+ else
+ Vec_IntClear( vCube0 );
+
+ /*********************************************************/
+ RetValue = 0;
+ for ( j = 0; j < pFxchMan->nSizeOutputID; j++ )
+ {
+ RetValue |= ( pOutputID1[j] & ~( pFxchMan->pTempOutputID[j] ) );
+ pOutputID1[j] &= ~( pFxchMan->pTempOutputID[j] );
+ }
+
+ if ( RetValue != 0 )
+ Vec_IntPush( pFxchMan->vCubesToUpdate, iCube1 );
+ else
+ Vec_IntClear( vCube1 );
+
+ }
+ Vec_IntFree( vCube0Copy );
+ Vec_IntFree( vCube1Copy );
if ( iVarNew )
{
+ Vec_Int_t* vLitP = Vec_WecEntry( pFxchMan->vLits, Vec_WecSize( pFxchMan->vLits ) - 2 ),
+ * vLitN = Vec_WecEntry( pFxchMan->vLits, Vec_WecSize( pFxchMan->vLits ) - 1 );
+
+ assert( vCube );
if ( Vec_IntSize( pFxchMan->vDiv ) == 2 || fCompl )
{
- Vec_IntPush( vCube0, Abc_Var2Lit( iVarNew, 1 ) );
- Vec_IntPush( vLitN, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) );
+ Vec_IntPush( vCube, Abc_Var2Lit( iVarNew, 1 ) );
+ Vec_IntPush( vLitN, Vec_WecLevelId( pFxchMan->vCubes, vCube ) );
+ Vec_IntSort( vLitN, 0 );
}
else
{
- Vec_IntPush( vCube0, Abc_Var2Lit( iVarNew, 0 ) );
- Vec_IntPush( vLitP, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) );
+ Vec_IntPush( vCube, Abc_Var2Lit( iVarNew, 0 ) );
+ Vec_IntPush( vLitP, Vec_WecLevelId( pFxchMan->vCubes, vCube ) );
+ Vec_IntSort( vLitP, 0 );
}
}
}
- return k;
+ return;
}
static inline int Fxch_ManCreateCube( Fxch_Man_t* pFxchMan,
@@ -421,7 +514,8 @@ static inline int Fxch_ManCreateCube( Fxch_Man_t* pFxchMan,
int Lit1 )
{
int Level,
- iVarNew;
+ iVarNew,
+ j;
Vec_Int_t* vCube0,
* vCube1;
@@ -429,6 +523,10 @@ static inline int Fxch_ManCreateCube( Fxch_Man_t* pFxchMan,
iVarNew = pFxchMan->nVars;
pFxchMan->nVars++;
+ /* Clear temporary outputID vector */
+ for ( j = 0; j < pFxchMan->nSizeOutputID; j++ )
+ pFxchMan->pTempOutputID[j] = 0;
+
/* Create new Lit hash keys */
Vec_IntPush( pFxchMan->vLitHashKeys, Gia_ManRandom(0) & 0x3FFFFFF );
Vec_IntPush( pFxchMan->vLitHashKeys, Gia_ManRandom(0) & 0x3FFFFFF );
@@ -436,6 +534,7 @@ static inline int Fxch_ManCreateCube( Fxch_Man_t* pFxchMan,
/* Create new Cube */
vCube0 = Vec_WecPushLevel( pFxchMan->vCubes );
Vec_IntPush( vCube0, iVarNew );
+ Vec_IntPushArray( pFxchMan->vOutputID, pFxchMan->pTempOutputID, pFxchMan->nSizeOutputID );
if ( Vec_IntSize( pFxchMan->vDiv ) == 2 )
{
@@ -448,12 +547,27 @@ static inline int Fxch_ManCreateCube( Fxch_Man_t* pFxchMan,
}
else
{
+ int i;
+ int Lit;
+
vCube1 = Vec_WecPushLevel( pFxchMan->vCubes );
- vCube0 = Fxch_ManGetCube( pFxchMan, Vec_WecSize( pFxchMan->vCubes ) - 2 );
Vec_IntPush( vCube1, iVarNew );
+ Vec_IntPushArray( pFxchMan->vOutputID, pFxchMan->pTempOutputID, pFxchMan->nSizeOutputID );
+
+ vCube0 = Fxch_ManGetCube( pFxchMan, Vec_WecSize( pFxchMan->vCubes ) - 2 );
Fxch_DivSepareteCubes( pFxchMan->vDiv, vCube0, vCube1 );
Level = 2 + Abc_MaxInt( Fxch_ManComputeLevelCube( pFxchMan, vCube0 ),
Fxch_ManComputeLevelCube( pFxchMan, vCube1 ) );
+
+ Vec_IntPush( pFxchMan->vCubesToUpdate, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) );
+ Vec_IntPush( pFxchMan->vCubesToUpdate, Vec_WecLevelId( pFxchMan->vCubes, vCube1 ) );
+
+ /* Update Lit -> Cube mapping */
+ Vec_IntForEachEntryStart( vCube0, Lit, i, 1 )
+ Vec_WecPush( pFxchMan->vLits, Lit, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) );
+
+ Vec_IntForEachEntryStart( vCube1, Lit, i, 1 )
+ Vec_WecPush( pFxchMan->vLits, Lit, Vec_WecLevelId( pFxchMan->vCubes, vCube1 ) );
}
assert( Vec_IntSize( pFxchMan->vLevels ) == iVarNew );
Vec_IntPush( pFxchMan->vLevels, Level );
@@ -470,7 +584,7 @@ static inline int Fxch_ManCreateCube( Fxch_Man_t* pFxchMan,
void Fxch_ManUpdate( Fxch_Man_t* pFxchMan,
int iDiv )
{
- int i, k, iCube0, iCube1,
+ int i, iCube0, iCube1,
Lit0 = -1,
Lit1 = -1,
iVarNew;
@@ -519,89 +633,128 @@ void Fxch_ManUpdate( Fxch_Man_t* pFxchMan,
/* subtract cost of single-cube divisors */
Vec_IntForEachEntry( pFxchMan->vCubesS, iCube0, i )
- Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1); /* remove (fAdd = 0) - fUpdate = 1 */
-
- Vec_IntForEachEntryDouble( pFxchMan->vPairs, iCube0, iCube1, i )
- Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1), /* remove (fAdd = 0) - fUpdate = 1 */
- Fxch_ManDivSingleCube( pFxchMan, iCube1, 0, 1); /* remove (fAdd = 0) - fUpdate = 1 */
+ {
+ Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1);
- /* subtract cost of double-cube divisors */
- Vec_IntForEachEntry( pFxchMan->vCubesS, iCube0, i )
- if ( iCube0 < Vec_IntSize(pFxchMan->pSCHashTable->vCubeLinks) )
- Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 ); /* remove (fAdd = 0) - fUpdate = 1 */
+ if ( Vec_WecEntryEntry( pFxchMan->vCubes, iCube0, 0 ) == 0 )
+ Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 );
+ }
Vec_IntForEachEntry( pFxchMan->vPairs, iCube0, i )
- if ( iCube0 < Vec_IntSize(pFxchMan->pSCHashTable->vCubeLinks) )
- Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 ); /* remove (fAdd = 0) - fUpdate = 1 */
+ {
+ Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1);
- k = 0;
+ if ( Vec_WecEntryEntry( pFxchMan->vCubes, iCube0, 0 ) == 0 )
+ Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 );
+ }
+
+ Vec_IntClear( pFxchMan->vCubesToUpdate );
if ( Fxch_DivIsNotConstant1( pFxchMan->vDiv ) )
{
iVarNew = Fxch_ManCreateCube( pFxchMan, Lit0, Lit1 );
Fxch_ManExtractDivFromCube( pFxchMan, Lit0, Lit1, iVarNew );
- k = Fxch_ManExtractDivFromCubePairs( pFxchMan, iVarNew );
+ Fxch_ManExtractDivFromCubePairs( pFxchMan, iVarNew );
}
else
- k = Fxch_ManExtractDivFromCubePairs( pFxchMan, 0 );
+ Fxch_ManExtractDivFromCubePairs( pFxchMan, 0 );
- assert( k == Vec_IntSize( pFxchMan->vPairs ) / 2 );
- Vec_IntShrink( pFxchMan->vPairs, k );
-
- /* Add cost of single-cube divisors */
- Vec_IntForEachEntry( pFxchMan->vCubesS, iCube0, i )
- Fxch_ManDivSingleCube( pFxchMan, iCube0, 1, 1 ); /* fAdd = 1 - fUpdate = 1 */
-
- Vec_IntForEachEntry( pFxchMan->vPairs, iCube0, i )
- Fxch_ManDivSingleCube( pFxchMan, iCube0, 1, 1 ); /* fAdd = 1 - fUpdate = 1 */
+ assert( Vec_IntSize( pFxchMan->vCubesToUpdate ) );
- /* Add cost of double-cube divisors */
- Vec_IntForEachEntry( pFxchMan->vCubesS, iCube0, i )
- if ( iCube0 < Vec_IntSize(pFxchMan->pSCHashTable->vCubeLinks) )
- Fxch_ManDivDoubleCube( pFxchMan, iCube0, 1, 1 ); /* fAdd = 1 - fUpdate = 1 */
+ /* Add cost */
+ Vec_IntForEachEntry( pFxchMan->vCubesToUpdate, iCube0, i )
+ {
+ Fxch_ManDivSingleCube( pFxchMan, iCube0, 1, 1 );
- Vec_IntForEachEntry( pFxchMan->vPairs, iCube0, i )
- if ( iCube0 < Vec_IntSize(pFxchMan->pSCHashTable->vCubeLinks) )
- Fxch_ManDivDoubleCube( pFxchMan, iCube0, 1, 1 ); /* fAdd = 1 - fUpdate = 1 */
+ if ( Vec_WecEntryEntry( pFxchMan->vCubes, iCube0, 0 ) == 0 )
+ Fxch_ManDivDoubleCube( pFxchMan, iCube0, 1, 1 );
+ }
/* Deal with SCC */
- if ( Vec_IntSize( pFxchMan->vSCC ) )
+ if ( Vec_IntSize( pFxchMan->vSCC ) && pFxchMan->nExtDivs < 17 )
{
- Vec_IntUniqify( pFxchMan->vSCC );
- Vec_IntForEachEntry( pFxchMan->vSCC, iCube0, i )
- if ( iCube0 < Vec_IntSize(pFxchMan->pSCHashTable->vCubeLinks) )
+ Vec_IntUniqifyPairs( pFxchMan->vSCC );
+ assert( Vec_IntSize( pFxchMan->vSCC ) % 2 == 0 );
+
+ Vec_IntForEachEntryDouble( pFxchMan->vSCC, iCube0, iCube1, i )
+ {
+ int j, RetValue = 1;
+ int* pOutputID0 = Vec_IntEntryP( pFxchMan->vOutputID, iCube0 * pFxchMan->nSizeOutputID );
+ int* pOutputID1 = Vec_IntEntryP( pFxchMan->vOutputID, iCube1 * pFxchMan->nSizeOutputID );
+ vCube0 = Vec_WecEntry( pFxchMan->vCubes, iCube0 );
+ vCube1 = Vec_WecEntry( pFxchMan->vCubes, iCube1 );
+
+ if ( !Vec_WecIntHasMark( vCube0 ) )
{
- Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 ); /* remove (fAdd = 0) - fUpdate = 1 */
- vCube0 = Fxch_ManGetCube( pFxchMan, iCube0 ),
- Vec_IntClear( vCube0 );
+ Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1 );
+ Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 );
+ Vec_WecIntSetMark( vCube0 );
}
- Vec_IntClear( pFxchMan->vSCC );
- }
+ if ( !Vec_WecIntHasMark( vCube1 ) )
+ {
+ Fxch_ManDivSingleCube( pFxchMan, iCube1, 0, 1 );
+ Fxch_ManDivDoubleCube( pFxchMan, iCube1, 0, 1 );
+ Vec_WecIntSetMark( vCube1 );
+ }
+ if ( Vec_IntSize( vCube0 ) == Vec_IntSize( vCube1 ) )
+ {
+ for ( j = 0; j < pFxchMan->nSizeOutputID; j++ )
+ {
+ pOutputID1[j] |= pOutputID0[j];
+ pOutputID0[j] = 0;
+ }
+ Vec_IntClear( Vec_WecEntry( pFxchMan->vCubes, iCube0 ) );
+ Vec_WecIntXorMark( vCube0 );
+ continue;
+ }
- /* If it's a double-cube devisor add its cost */
- if ( Vec_IntSize( pFxchMan->vDiv ) > 2 )
- {
- iCube0 = Vec_WecSize( pFxchMan->vCubes ) - 2;
- iCube1 = Vec_WecSize( pFxchMan->vCubes ) - 1;
+ for ( j = 0; j < pFxchMan->nSizeOutputID && RetValue; j++ )
+ RetValue = ( pOutputID0[j] == pOutputID1[j] );
- Fxch_ManDivSingleCube( pFxchMan, iCube0, 1, 1 ); /* fAdd = 1 - fUpdate = 1 */
- Fxch_ManDivSingleCube( pFxchMan, iCube1, 1, 1 ); /* fAdd = 1 - fUpdate = 1 */
+ if ( RetValue )
+ {
+ Vec_IntClear( Vec_WecEntry( pFxchMan->vCubes, iCube0 ) );
+ Vec_WecIntXorMark( vCube0 );
+ }
+ else
+ {
+ RetValue = 0;
+ for ( j = 0; j < pFxchMan->nSizeOutputID; j++ )
+ {
+ RetValue |= ( pOutputID0[j] & ~( pOutputID1[j] ) );
+ pOutputID0[j] &= ~( pOutputID1[j] );
+ }
+
+ if ( RetValue == 0 )
+ {
+ Vec_IntClear( Vec_WecEntry( pFxchMan->vCubes, iCube0 ) );
+ Vec_WecIntXorMark( vCube0 );
+ }
+ }
+ }
- vCube0 = Vec_WecEntry( pFxchMan->vCubes, iCube0 );
- Vec_IntForEachEntryStart( vCube0, Lit0, i, 1 )
- Vec_WecPush( pFxchMan->vLits, Lit0, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) );
+ Vec_IntForEachEntryDouble( pFxchMan->vSCC, iCube0, iCube1, i )
+ {
+ vCube0 = Vec_WecEntry( pFxchMan->vCubes, iCube0 );
+ vCube1 = Vec_WecEntry( pFxchMan->vCubes, iCube1 );
- vCube1 = Vec_WecEntry( pFxchMan->vCubes, iCube1 );
- Vec_IntForEachEntryStart( vCube1, Lit0, i, 1 )
- Vec_WecPush( pFxchMan->vLits, Lit0, Vec_WecLevelId( pFxchMan->vCubes, vCube1 ) );
- }
+ if ( Vec_WecIntHasMark( vCube0 ) )
+ {
+ Fxch_ManDivSingleCube( pFxchMan, iCube0, 1, 1 );
+ Fxch_ManDivDoubleCube( pFxchMan, iCube0, 1, 1 );
+ Vec_WecIntXorMark( vCube0 );
+ }
- /* remove these cubes from the lit array of the divisor */
- Vec_IntForEachEntry( pFxchMan->vDiv, Lit0, i )
- {
- Vec_IntTwoRemove( Vec_WecEntry( pFxchMan->vLits, Abc_Lit2Var( Lit0 ) ), pFxchMan->vPairs );
- Vec_IntTwoRemove( Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Abc_Lit2Var( Lit0 ) ) ), pFxchMan->vPairs );
+ if ( Vec_WecIntHasMark( vCube1 ) )
+ {
+ Fxch_ManDivSingleCube( pFxchMan, iCube1, 1, 1 );
+ Fxch_ManDivDoubleCube( pFxchMan, iCube1, 1, 1 );
+ Vec_WecIntXorMark( vCube1 );
+ }
+ }
+
+ Vec_IntClear( pFxchMan->vSCC );
}
pFxchMan->nExtDivs++;
diff --git a/src/opt/fxch/FxchSCHashTable.c b/src/opt/fxch/FxchSCHashTable.c
index a37009eb..0796a28c 100644
--- a/src/opt/fxch/FxchSCHashTable.c
+++ b/src/opt/fxch/FxchSCHashTable.c
@@ -19,11 +19,6 @@
ABC_NAMESPACE_IMPL_START
-//#ifdef _WIN32
-typedef unsigned int uint32_t;
-typedef unsigned char uint8_t;
-//#endif
-
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
@@ -92,7 +87,6 @@ static inline void MurmurHash3_x86_32 ( const void* key,
}
Fxch_SCHashTable_t* Fxch_SCHashTableCreate( Fxch_Man_t* pFxchMan,
- Vec_Int_t* vCubeLinks,
int nEntries )
{
Fxch_SCHashTable_t* pSCHashTable = ABC_CALLOC( Fxch_SCHashTable_t, 1 );
@@ -101,7 +95,6 @@ Fxch_SCHashTable_t* Fxch_SCHashTableCreate( Fxch_Man_t* pFxchMan,
pSCHashTable->pFxchMan = pFxchMan;
pSCHashTable->SizeMask = (1 << nBits) - 1;
- pSCHashTable->vCubeLinks = vCubeLinks;
pSCHashTable->pBins = ABC_CALLOC( Fxch_SCHashTable_Entry_t, pSCHashTable->SizeMask + 1 );
return pSCHashTable;
@@ -109,7 +102,6 @@ Fxch_SCHashTable_t* Fxch_SCHashTableCreate( Fxch_Man_t* pFxchMan,
void Fxch_SCHashTableDelete( Fxch_SCHashTable_t* pSCHashTable )
{
- Vec_IntFree( pSCHashTable->vCubeLinks );
Vec_IntErase( &pSCHashTable->vSubCube0 );
Vec_IntErase( &pSCHashTable->vSubCube1 );
ABC_FREE( pSCHashTable->pBins );
@@ -122,49 +114,6 @@ static inline Fxch_SCHashTable_Entry_t* Fxch_SCHashTableBin( Fxch_SCHashTable_t*
return pSCHashTable->pBins + (SubCubeID & pSCHashTable->SizeMask);
}
-static inline Fxch_SCHashTable_Entry_t* Fxch_SCHashTableEntry( Fxch_SCHashTable_t* pSCHashTable,
- unsigned int iEntry )
-{
- if ( ( iEntry > 0 ) && ( iEntry < ( pSCHashTable->SizeMask + 1 ) ) )
- return pSCHashTable->pBins + iEntry;
-
- return NULL;
-}
-
-static inline void Fxch_SCHashTableInsertLink( Fxch_SCHashTable_t* pSCHashTable,
- unsigned int iEntry0,
- unsigned int iEntry1 )
-{
- Fxch_SCHashTable_Entry_t* pEntry0 = Fxch_SCHashTableEntry( pSCHashTable, iEntry0 ),
- * pEntry1 = Fxch_SCHashTableEntry( pSCHashTable, iEntry1 ),
- * pEntry0Next = Fxch_SCHashTableEntry( pSCHashTable, pEntry0->iNext );
-
- assert( pEntry0Next->iPrev == iEntry0 );
-
- pEntry1->iNext = pEntry0->iNext;
- pEntry0->iNext = iEntry1;
- pEntry1->iPrev = iEntry0;
- pEntry0Next->iPrev = iEntry1;
-}
-
-static inline void Fxch_SCHashTableRemoveLink( Fxch_SCHashTable_t* pSCHashTable,
- int iEntry0,
- int iEntry1 )
-{
- Fxch_SCHashTable_Entry_t* pEntry0 = Fxch_SCHashTableEntry( pSCHashTable, iEntry0 ),
- * pEntry1 = Fxch_SCHashTableEntry( pSCHashTable, iEntry1 ),
- * pEntry1Next = Fxch_SCHashTableEntry( pSCHashTable, pEntry1->iNext );
-
- assert( (int)pEntry0->iNext == iEntry1 );
- assert( (int)pEntry1->iPrev == iEntry0 );
- assert( (int)pEntry1Next->iPrev == iEntry1 );
-
- pEntry0->iNext = pEntry1->iNext;
- pEntry1->iNext = 0;
- pEntry1Next->iPrev = pEntry1->iPrev;
- pEntry1->iPrev = 0;
-}
-
static inline int Fxch_SCHashTableEntryCompare( Fxch_SCHashTable_t* pSCHashTable,
Vec_Wec_t* vCubes,
Fxch_SubCube_t* pSCData0,
@@ -173,12 +122,22 @@ static inline int Fxch_SCHashTableEntryCompare( Fxch_SCHashTable_t* pSCHashTable
Vec_Int_t* vCube0 = Vec_WecEntry( vCubes, pSCData0->iCube ),
* vCube1 = Vec_WecEntry( vCubes, pSCData1->iCube );
+ int* pOutputID0 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pSCData0->iCube * pSCHashTable->pFxchMan->nSizeOutputID ),
+ * pOutputID1 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pSCData1->iCube * pSCHashTable->pFxchMan->nSizeOutputID );
+ int i, Result = 0;
+
if ( !Vec_IntSize( vCube0 ) ||
!Vec_IntSize( vCube1 ) ||
Vec_IntEntry( vCube0, 0 ) != Vec_IntEntry( vCube1, 0 ) ||
pSCData0->Id != pSCData1->Id )
return 0;
+ for ( i = 0; i < pSCHashTable->pFxchMan->nSizeOutputID && Result == 0; i++ )
+ Result = ( pOutputID0[i] & pOutputID1[i] );
+
+ if ( Result == 0 )
+ return 0;
+
Vec_IntClear( &pSCHashTable->vSubCube0 );
Vec_IntClear( &pSCHashTable->vSubCube1 );
@@ -189,7 +148,6 @@ static inline int Fxch_SCHashTableEntryCompare( Fxch_SCHashTable_t* pSCHashTable
Vec_IntEntry( vCube0, pSCData0->iLit1 ) == Vec_IntEntry( vCube1, pSCData1->iLit1 ) ) )
return 0;
-
if ( pSCData0->iLit0 > 0 )
Vec_IntAppendSkip( &pSCHashTable->vSubCube0, vCube0, pSCData0->iLit0 );
else
@@ -200,7 +158,6 @@ static inline int Fxch_SCHashTableEntryCompare( Fxch_SCHashTable_t* pSCHashTable
else
Vec_IntAppend( &pSCHashTable->vSubCube1, vCube1 );
-
if ( pSCData0->iLit1 > 0)
Vec_IntDrop( &pSCHashTable->vSubCube0,
pSCData0->iLit0 < pSCData0->iLit1 ? pSCData0->iLit1 - 1 : pSCData0->iLit1 );
@@ -209,167 +166,169 @@ static inline int Fxch_SCHashTableEntryCompare( Fxch_SCHashTable_t* pSCHashTable
Vec_IntDrop( &pSCHashTable->vSubCube1,
pSCData1->iLit0 < pSCData1->iLit1 ? pSCData1->iLit1 - 1 : pSCData1->iLit1 );
- Vec_IntDrop( &pSCHashTable->vSubCube0, 0 );
- Vec_IntDrop( &pSCHashTable->vSubCube1, 0 );
-
return Vec_IntEqual( &pSCHashTable->vSubCube0, &pSCHashTable->vSubCube1 );
}
int Fxch_SCHashTableInsert( Fxch_SCHashTable_t* pSCHashTable,
Vec_Wec_t* vCubes,
- unsigned int SubCubeID,
- unsigned int iSubCube,
- unsigned int iCube,
- unsigned int iLit0,
- unsigned int iLit1,
+ uint32_t SubCubeID,
+ uint32_t iCube,
+ uint32_t iLit0,
+ uint32_t iLit1,
char fUpdate )
{
- unsigned int BinID;
- unsigned int iNewEntry;
- Fxch_SCHashTable_Entry_t* pBin,* pNewEntry;
-
- Fxch_SCHashTable_Entry_t* pEntry;
- unsigned int iEntry;
- char Pairs = 0,
- fStart = 1;
+ int iNewEntry;
+ int Pairs = 0;
+ uint32_t BinID;
+ Fxch_SCHashTable_Entry_t* pBin;
+ Fxch_SubCube_t* pNewEntry;
+ int iEntry;
MurmurHash3_x86_32( ( void* ) &SubCubeID, sizeof( int ), 0x9747b28c, &BinID);
-
- iNewEntry = ( unsigned int )( Vec_IntEntry( pSCHashTable->vCubeLinks, iCube ) ) + iSubCube;
pBin = Fxch_SCHashTableBin( pSCHashTable, BinID );
- pNewEntry = Fxch_SCHashTableEntry( pSCHashTable, iNewEntry );
-
- assert( pNewEntry->Used == 0 );
-
- pNewEntry->SCData.Id = SubCubeID;
- pNewEntry->SCData.iCube = iCube;
- pNewEntry->SCData.iLit0 = iLit0;
- pNewEntry->SCData.iLit1 = iLit1;
+
+ if ( pBin->vSCData == NULL )
+ {
+ pBin->vSCData = ABC_CALLOC( Fxch_SubCube_t, 16 );
+ pBin->Size = 0;
+ pBin->Cap = 16;
+ }
+ else if ( pBin->Size == pBin->Cap )
+ {
+ pBin->Cap = 2 * pBin->Size;
+ pBin->vSCData = ABC_REALLOC( Fxch_SubCube_t, pBin->vSCData, pBin->Cap );
+ }
- pNewEntry->Used = 1;
+ iNewEntry = pBin->Size++;
+ pBin->vSCData[iNewEntry].Id = SubCubeID;
+ pBin->vSCData[iNewEntry].iCube = iCube;
+ pBin->vSCData[iNewEntry].iLit0 = iLit0;
+ pBin->vSCData[iNewEntry].iLit1 = iLit1;
pSCHashTable->nEntries++;
- if ( pBin->iTable == 0 )
- {
- pBin->iTable = iNewEntry;
- pNewEntry->iNext = iNewEntry;
- pNewEntry->iPrev = iNewEntry;
+
+ if ( pBin->Size == 1 )
return 0;
- }
- for ( iEntry = pBin->iTable; iEntry != pBin->iTable || fStart; iEntry = pEntry->iNext, fStart = 0 )
+ pNewEntry = &( pBin->vSCData[iNewEntry] );
+ for ( iEntry = 0; iEntry < (int)pBin->Size - 1; iEntry++ )
{
+ Fxch_SubCube_t* pEntry = &( pBin->vSCData[iEntry] );
+ int* pOutputID0 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pEntry->iCube * pSCHashTable->pFxchMan->nSizeOutputID );
+ int* pOutputID1 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pNewEntry->iCube * pSCHashTable->pFxchMan->nSizeOutputID );
+ int Result = 0;
int Base;
- int iNewDiv;
+ int iNewDiv, i, z;
- pEntry = Fxch_SCHashTableBin( pSCHashTable, iEntry );
-
- if ( !Fxch_SCHashTableEntryCompare( pSCHashTable, vCubes, &( pEntry->SCData ), &( pNewEntry->SCData ) ) )
+ if ( !Fxch_SCHashTableEntryCompare( pSCHashTable, vCubes, pEntry, pNewEntry ) )
continue;
- if ( ( pEntry->SCData.iLit0 == 0 ) || ( pNewEntry->SCData.iLit0 == 0 ) )
+ if ( ( pEntry->iLit0 == 0 ) || ( pNewEntry->iLit0 == 0 ) )
{
- Vec_Int_t* vCube0 = Fxch_ManGetCube( pSCHashTable->pFxchMan, pEntry->SCData.iCube ),
- * vCube1 = Fxch_ManGetCube( pSCHashTable->pFxchMan, pEntry->SCData.iCube );
+ Vec_Int_t* vCube0 = Fxch_ManGetCube( pSCHashTable->pFxchMan, pEntry->iCube ),
+ * vCube1 = Fxch_ManGetCube( pSCHashTable->pFxchMan, pNewEntry->iCube );
if ( Vec_IntSize( vCube0 ) > Vec_IntSize( vCube1 ) )
- Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pEntry->SCData.iCube );
+ {
+ Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pEntry->iCube );
+ Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pNewEntry->iCube );
+ }
else
- Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pNewEntry->SCData.iCube );
+ {
+ Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pNewEntry->iCube );
+ Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pEntry->iCube );
+ }
continue;
}
- if ( pEntry->SCData.iCube < pNewEntry->SCData.iCube )
- Base = Fxch_DivCreate( pSCHashTable->pFxchMan, &( pEntry->SCData ), &( pNewEntry->SCData ) );
- else
- Base = Fxch_DivCreate( pSCHashTable->pFxchMan, &( pNewEntry->SCData ), &( pEntry->SCData ) );
+ Base = Fxch_DivCreate( pSCHashTable->pFxchMan, pEntry, pNewEntry );
if ( Base < 0 )
continue;
- iNewDiv = Fxch_DivAdd( pSCHashTable->pFxchMan, fUpdate, 0, Base );
+ for ( i = 0; i < pSCHashTable->pFxchMan->nSizeOutputID; i++ )
+ Result += Fxch_CountOnes( pOutputID0[i] & pOutputID1[i] );
- Vec_WecPush( pSCHashTable->pFxchMan->vDivCubePairs, iNewDiv, pEntry->SCData.iCube );
- Vec_WecPush( pSCHashTable->pFxchMan->vDivCubePairs, iNewDiv, pNewEntry->SCData.iCube );
+ for ( z = 0; z < Result; z++ )
+ iNewDiv = Fxch_DivAdd( pSCHashTable->pFxchMan, fUpdate, 0, Base );
+
+ Vec_WecPush( pSCHashTable->pFxchMan->vDivCubePairs, iNewDiv, pEntry->iCube );
+ Vec_WecPush( pSCHashTable->pFxchMan->vDivCubePairs, iNewDiv, pNewEntry->iCube );
Pairs++;
}
- assert( iEntry == (unsigned int)( pBin->iTable ) );
-
- pEntry = Fxch_SCHashTableBin( pSCHashTable, iEntry );
- Fxch_SCHashTableInsertLink( pSCHashTable, pEntry->iPrev, iNewEntry );
return Pairs;
}
int Fxch_SCHashTableRemove( Fxch_SCHashTable_t* pSCHashTable,
Vec_Wec_t* vCubes,
- unsigned int SubCubeID,
- unsigned int iSubCube,
- unsigned int iCube,
- unsigned int iLit0,
- unsigned int iLit1,
+ uint32_t SubCubeID,
+ uint32_t iCube,
+ uint32_t iLit0,
+ uint32_t iLit1,
char fUpdate )
{
- unsigned int BinID;
- unsigned int iEntry;
- Fxch_SCHashTable_Entry_t* pBin,* pEntry;
- Fxch_SCHashTable_Entry_t* pNextEntry;
- int iNextEntry,
- Pairs = 0,
- fStart = 1;
+ int iEntry;
+ int Pairs = 0;
+ uint32_t BinID;
+ Fxch_SCHashTable_Entry_t* pBin;
+ Fxch_SubCube_t* pEntry;
+ int idx;
MurmurHash3_x86_32( ( void* ) &SubCubeID, sizeof( int ), 0x9747b28c, &BinID);
- iEntry = ( unsigned int )( Vec_IntEntry( pSCHashTable->vCubeLinks, iCube ) ) + iSubCube;
pBin = Fxch_SCHashTableBin( pSCHashTable, BinID );
- pEntry = Fxch_SCHashTableEntry( pSCHashTable, iEntry );
-
- assert( pEntry->Used == 1 );
- assert( pEntry->SCData.iCube == iCube );
- if ( pEntry->iNext == iEntry )
+ if ( pBin->Size == 1 )
{
- assert( pEntry->iPrev == iEntry );
- pBin->iTable = 0;
- pEntry->iNext = 0;
- pEntry->iPrev = 0;
- pEntry->Used = 0;
+ pBin->Size = 0;
return 0;
}
- for ( iNextEntry = (int)pEntry->iNext; iNextEntry != (int)iEntry; iNextEntry = pNextEntry->iNext, fStart = 0 )
+ for ( iEntry = 0; iEntry < (int)pBin->Size; iEntry++ )
+ if ( pBin->vSCData[iEntry].iCube == iCube )
+ break;
+
+ assert( ( iEntry != pBin->Size ) && ( pBin->Size != 0 ) );
+
+ pEntry = &( pBin->vSCData[iEntry] );
+ for ( idx = 0; idx < (int)pBin->Size; idx++ )
+ if ( idx != iEntry )
{
int Base,
iDiv;
- int i,
+ int i, z,
iCube0,
iCube1;
+ Fxch_SubCube_t* pNextEntry = &( pBin->vSCData[idx] );
Vec_Int_t* vDivCubePairs;
+ int* pOutputID0 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pEntry->iCube * pSCHashTable->pFxchMan->nSizeOutputID );
+ int* pOutputID1 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pNextEntry->iCube * pSCHashTable->pFxchMan->nSizeOutputID );
+ int Result = 0;
- pNextEntry = Fxch_SCHashTableBin( pSCHashTable, iNextEntry );
-
- if ( !Fxch_SCHashTableEntryCompare( pSCHashTable, vCubes, &( pEntry->SCData ), &( pNextEntry->SCData ) )
- || pEntry->SCData.iLit0 == 0
- || pNextEntry->SCData.iLit0 == 0 )
+ if ( !Fxch_SCHashTableEntryCompare( pSCHashTable, vCubes, pEntry, pNextEntry )
+ || pEntry->iLit0 == 0
+ || pNextEntry->iLit0 == 0 )
continue;
- if ( pNextEntry->SCData.iCube < pEntry->SCData.iCube )
- Base = Fxch_DivCreate( pSCHashTable->pFxchMan, &( pNextEntry->SCData ), &( pEntry->SCData ) );
- else
- Base = Fxch_DivCreate( pSCHashTable->pFxchMan, &( pEntry->SCData ), &( pNextEntry->SCData ) );
+ Base = Fxch_DivCreate( pSCHashTable->pFxchMan, pNextEntry, pEntry );
if ( Base < 0 )
continue;
- iDiv = Fxch_DivRemove( pSCHashTable->pFxchMan, fUpdate, 0, Base );
+ for ( i = 0; i < pSCHashTable->pFxchMan->nSizeOutputID; i++ )
+ Result += Fxch_CountOnes( pOutputID0[i] & pOutputID1[i] );
+
+ for ( z = 0; z < Result; z++ )
+ iDiv = Fxch_DivRemove( pSCHashTable->pFxchMan, fUpdate, 0, Base );
vDivCubePairs = Vec_WecEntry( pSCHashTable->pFxchMan->vDivCubePairs, iDiv );
Vec_IntForEachEntryDouble( vDivCubePairs, iCube0, iCube1, i )
- if ( ( iCube0 == (int)pNextEntry->SCData.iCube && iCube1 == (int)pEntry->SCData.iCube ) ||
- ( iCube0 == (int)pEntry->SCData.iCube && iCube1 == (int)pNextEntry->SCData.iCube ) )
+ if ( ( iCube0 == (int)pNextEntry->iCube && iCube1 == (int)pEntry->iCube ) ||
+ ( iCube0 == (int)pEntry->iCube && iCube1 == (int)pNextEntry->iCube ) )
{
Vec_IntDrop( vDivCubePairs, i+1 );
Vec_IntDrop( vDivCubePairs, i );
@@ -379,12 +338,10 @@ int Fxch_SCHashTableRemove( Fxch_SCHashTable_t* pSCHashTable,
Pairs++;
}
+
+ memmove(pBin->vSCData + iEntry, pBin->vSCData + iEntry + 1, (pBin->Size - iEntry - 1) * sizeof(*pBin->vSCData));
+ pBin->Size -= 1;
- if ( pBin->iTable == iEntry )
- pBin->iTable = ( pEntry->iNext != iEntry ) ? pEntry->iNext : 0;
-
- pEntry->Used = 0;
- Fxch_SCHashTableRemoveLink( pSCHashTable, pEntry->iPrev, iEntry );
return Pairs;
}
@@ -392,7 +349,6 @@ unsigned int Fxch_SCHashTableMemory( Fxch_SCHashTable_t* pHashTable )
{
unsigned int Memory = sizeof ( Fxch_SCHashTable_t );
- Memory += Vec_IntMemory( pHashTable->vCubeLinks );
Memory += sizeof( Fxch_SubCube_t ) * ( pHashTable->SizeMask + 1 );
return Memory;
diff --git a/src/proof/acec/acec.h b/src/proof/acec/acec.h
index f39041c8..c61b4485 100644
--- a/src/proof/acec/acec.h
+++ b/src/proof/acec/acec.h
@@ -53,7 +53,7 @@ ABC_NAMESPACE_HEADER_START
/*=== acecCore.c ========================================================*/
extern int Gia_PolynCec( Gia_Man_t * pGia0, Gia_Man_t * pGia1, Cec_ParCec_t * pPars );
/*=== acecFadds.c ========================================================*/
-extern Vec_Int_t * Gia_ManDetectFullAdders( Gia_Man_t * p, int fVerbose );
+extern Vec_Int_t * Gia_ManDetectFullAdders( Gia_Man_t * p, int fVerbose, Vec_Int_t ** vCutsXor2 );
extern Vec_Int_t * Gia_ManDetectHalfAdders( Gia_Man_t * p, int fVerbose );
/*=== acecOrder.c ========================================================*/
extern Vec_Int_t * Gia_PolynReorder( Gia_Man_t * pGia, int fVerbose, int fVeryVerbose );
diff --git a/src/proof/acec/acecCover.c b/src/proof/acec/acecCover.c
new file mode 100644
index 00000000..e0d16419
--- /dev/null
+++ b/src/proof/acec/acecCover.c
@@ -0,0 +1,263 @@
+/**CFile****************************************************************
+
+ FileName [acecCover.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: acecCover.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "acecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Gia_AcecMark_rec( Gia_Man_t * p, int iObj, int fFirst )
+{
+ Gia_Obj_t * pObj = Gia_ManObj( p, iObj );
+ if ( pObj->fMark0 && !fFirst )
+ return;
+ assert( Gia_ObjIsAnd(pObj) );
+ pObj->fMark1 = 1;
+ Gia_AcecMark_rec( p, Gia_ObjFaninId0(pObj, iObj), 0 );
+ Gia_AcecMark_rec( p, Gia_ObjFaninId1(pObj, iObj), 0 );
+}
+void Gia_AcecMarkFadd( Gia_Man_t * p, int * pSigs )
+{
+// if ( Gia_ManObj(p, pSigs[3])->fMark1 || Gia_ManObj(p, pSigs[4])->fMark1 )
+// return;
+ Gia_ManObj( p, pSigs[0] )->fMark0 = 1;
+ Gia_ManObj( p, pSigs[1] )->fMark0 = 1;
+ Gia_ManObj( p, pSigs[2] )->fMark0 = 1;
+// assert( !Gia_ManObj(p, pSigs[3])->fMark1 );
+// assert( !Gia_ManObj(p, pSigs[4])->fMark1 );
+ Gia_AcecMark_rec( p, pSigs[3], 1 );
+ Gia_AcecMark_rec( p, pSigs[4], 1 );
+}
+void Gia_AcecMarkHadd( Gia_Man_t * p, int * pSigs )
+{
+ Gia_Obj_t * pObj = Gia_ManObj( p, pSigs[0] );
+ int iFan0 = Gia_ObjFaninId0( pObj, pSigs[0] );
+ int iFan1 = Gia_ObjFaninId1( pObj, pSigs[0] );
+ Gia_ManObj( p, iFan0 )->fMark0 = 1;
+ Gia_ManObj( p, iFan1 )->fMark0 = 1;
+ Gia_AcecMark_rec( p, pSigs[0], 1 );
+ Gia_AcecMark_rec( p, pSigs[1], 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collect XORs reachable from the last output.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Gia_AcecCollectXors_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Bit_t * vMap, Vec_Int_t * vXors )
+{
+ if ( !Gia_ObjIsXor(pObj) )//|| Vec_BitEntry(vMap, Gia_ObjId(p, pObj)) )
+ return;
+ Vec_IntPush( vXors, Gia_ObjId(p, pObj) );
+ Gia_AcecCollectXors_rec( p, Gia_ObjFanin0(pObj), vMap, vXors );
+ Gia_AcecCollectXors_rec( p, Gia_ObjFanin1(pObj), vMap, vXors );
+}
+Vec_Int_t * Gia_AcecCollectXors( Gia_Man_t * p, Vec_Bit_t * vMap )
+{
+ Vec_Int_t * vXors = Vec_IntAlloc( 100 );
+ Gia_Obj_t * pObj = Gia_ObjFanin0( Gia_ManCo(p, Gia_ManCoNum(p)-1) );
+ Gia_AcecCollectXors_rec( p, pObj, vMap, vXors );
+ return vXors;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Gia_AcecExplore( Gia_Man_t * p, int fVerbose )
+{
+ Vec_Int_t * vNodes = Vec_IntAlloc( 100 );
+ Vec_Int_t * vFadds, * vHadds, * vXors;
+ Vec_Bit_t * vMap = Vec_BitStart( Gia_ManObjNum(p) );
+ Gia_Obj_t * pObj;
+ int i, nSupp, nCone, nHadds = 0;
+ assert( p->pMuxes != NULL );
+ vFadds = Gia_ManDetectFullAdders( p, fVerbose, NULL );
+ vHadds = Gia_ManDetectHalfAdders( p, fVerbose );
+
+ pObj = Gia_ManObj( p, 352 );
+ printf( "Xor = %d.\n", Gia_ObjIsXor(pObj) );
+ printf( "Fanin0 = %d. Fanin1 = %d.\n", Gia_ObjFaninId0(pObj, 352), Gia_ObjFaninId1(pObj, 352) );
+ printf( "Fan00 = %d. Fan01 = %d. Fan10 = %d. Fan11 = %d.\n",
+ Gia_ObjFaninId0(Gia_ObjFanin0(pObj), Gia_ObjFaninId0(pObj, 352)),
+ Gia_ObjFaninId1(Gia_ObjFanin0(pObj), Gia_ObjFaninId0(pObj, 352)),
+ Gia_ObjFaninId0(Gia_ObjFanin1(pObj), Gia_ObjFaninId1(pObj, 352)),
+ Gia_ObjFaninId1(Gia_ObjFanin1(pObj), Gia_ObjFaninId1(pObj, 352)) );
+
+ // create a map of all HADD/FADD outputs
+ for ( i = 0; i < Vec_IntSize(vHadds)/2; i++ )
+ {
+ int * pSigs = Vec_IntEntryP(vHadds, 2*i);
+ Vec_BitWriteEntry( vMap, pSigs[0], 1 );
+ Vec_BitWriteEntry( vMap, pSigs[1], 1 );
+ }
+ for ( i = 0; i < Vec_IntSize(vFadds)/5; i++ )
+ {
+ int * pSigs = Vec_IntEntryP(vFadds, 5*i);
+ Vec_BitWriteEntry( vMap, pSigs[3], 1 );
+ Vec_BitWriteEntry( vMap, pSigs[4], 1 );
+ }
+
+ Gia_ManCleanMark01( p );
+
+ // mark outputs
+ Gia_ManForEachCo( p, pObj, i )
+ Gia_ObjFanin0(pObj)->fMark0 = 1;
+
+ // collect XORs
+ vXors = Gia_AcecCollectXors( p, vMap );
+ Vec_BitFree( vMap );
+
+ printf( "Collected XORs: " );
+ Vec_IntPrint( vXors );
+
+ // mark their fanins
+ Gia_ManForEachObjVec( vXors, p, pObj, i )
+ {
+ pObj->fMark1 = 1;
+ Gia_ObjFanin0(pObj)->fMark0 = 1;
+ Gia_ObjFanin1(pObj)->fMark0 = 1;
+ }
+
+ // mark FADDs
+ for ( i = 0; i < Vec_IntSize(vFadds)/5; i++ )
+ Gia_AcecMarkFadd( p, Vec_IntEntryP(vFadds, 5*i) );
+
+ // iterate through HADDs and find those that fit in
+ while ( 1 )
+ {
+ int fChange = 0;
+ for ( i = 0; i < Vec_IntSize(vHadds)/2; i++ )
+ {
+ int * pSigs = Vec_IntEntryP(vHadds, 2*i);
+ if ( !Gia_ManObj(p, pSigs[0])->fMark0 || !Gia_ManObj(p, pSigs[1])->fMark0 )
+ continue;
+ if ( Gia_ManObj(p, pSigs[0])->fMark1 || Gia_ManObj(p, pSigs[1])->fMark1 )
+ continue;
+ Gia_AcecMarkHadd( p, pSigs );
+ fChange = 1;
+ nHadds++;
+ }
+ if ( !fChange )
+ break;
+ }
+ // print inputs to the adder network
+ Gia_ManForEachAnd( p, pObj, i )
+ if ( pObj->fMark0 && !pObj->fMark1 )
+ {
+ nSupp = Gia_ManSuppSize( p, &i, 1 );
+ nCone = Gia_ManConeSize( p, &i, 1 );
+ printf( "Node %5d : Supp = %5d. Cone = %5d.\n", i, nSupp, nCone );
+ Vec_IntPush( vNodes, i );
+ }
+ printf( "Fadds = %d. Hadds = %d. Root nodes found = %d.\n", Vec_IntSize(vFadds)/5, nHadds, Vec_IntSize(vNodes) );
+
+ Gia_ManCleanMark01( p );
+
+ Gia_ManForEachObjVec( vNodes, p, pObj, i )
+ pObj->fMark0 = 1;
+
+ Vec_IntFree( vFadds );
+ Vec_IntFree( vHadds );
+ Vec_IntFree( vNodes );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Gia_AcecCover( Gia_Man_t * p )
+{
+ int fVerbose = 1;
+ int i, k, Entry;
+ Gia_Obj_t * pObj;
+ Vec_Int_t * vCutsXor2 = NULL;
+ Vec_Int_t * vFadds = Gia_ManDetectFullAdders( p, fVerbose, &vCutsXor2 );
+
+ // mark FADDs
+ Gia_ManCleanMark01( p );
+ for ( i = 0; i < Vec_IntSize(vFadds)/5; i++ )
+ Gia_AcecMarkFadd( p, Vec_IntEntryP(vFadds, 5*i) );
+
+ k = 0;
+ Vec_IntForEachEntry( vCutsXor2, Entry, i )
+ {
+ if ( i % 3 != 2 )
+ continue;
+ pObj = Gia_ManObj( p, Entry );
+ if ( pObj->fMark1 )
+ continue;
+ printf( "%d ", Entry );
+ }
+ printf( "\n" );
+
+ Gia_ManCleanMark01( p );
+
+ Vec_IntFree( vFadds );
+ Vec_IntFree( vCutsXor2 );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/acec/acecFadds.c b/src/proof/acec/acecFadds.c
index 6b954398..7f6dcd53 100644
--- a/src/proof/acec/acecFadds.c
+++ b/src/proof/acec/acecFadds.c
@@ -59,6 +59,7 @@ Vec_Int_t * Gia_ManDetectHalfAdders( Gia_Man_t * p, int fVerbose )
{
if ( !Gia_ObjIsXor(pObj) )
continue;
+ Count = 0;
iFan0 = Gia_ObjFaninId0(pObj, i);
iFan1 = Gia_ObjFaninId1(pObj, i);
if ( (iLit = Gia_ManHashLookupInt(p, Abc_Var2Lit(iFan0, 0), Abc_Var2Lit(iFan1, 0))) )
@@ -69,6 +70,7 @@ Vec_Int_t * Gia_ManDetectHalfAdders( Gia_Man_t * p, int fVerbose )
Vec_IntPushTwo( vHadds, i, Abc_Lit2Var(iLit) ), Count++;
if ( (iLit = Gia_ManHashLookupInt(p, Abc_Var2Lit(iFan0, 1), Abc_Var2Lit(iFan1, 0))) )
Vec_IntPushTwo( vHadds, i, Abc_Lit2Var(iLit) ), Count++;
+ Counts[Count]++;
}
}
else
@@ -116,7 +118,10 @@ Vec_Int_t * Gia_ManDetectHalfAdders( Gia_Man_t * p, int fVerbose )
printf( "\n" );
Vec_IntForEachEntryDouble( vHadds, iXor, iAnd, i )
- printf( "%3d : %5d %5d\n", i, iXor, iAnd );
+ {
+ pObj = Gia_ManObj( p, iXor );
+ printf( "%3d : %5d %5d -> %5d %5d\n", i, Gia_ObjFaninId0(pObj, iXor), Gia_ObjFaninId1(pObj, iXor), iXor, iAnd );
+ }
}
return vHadds;
}
@@ -255,6 +260,8 @@ int Dtc_ObjComputeTruth( Gia_Man_t * p, int iObj, int * pCut, int * pTruth )
Dtc_ObjCleanTruth_rec( Gia_ManObj(p, iObj) );
if ( pTruth )
*pTruth = Truth;
+ if ( Truth == 0x66 || Truth == 0x99 )
+ return 3;
if ( Truth == 0x96 || Truth == 0x69 )
return 1;
if ( Truth == 0xE8 || Truth == 0xD4 || Truth == 0xB2 || Truth == 0x71 ||
@@ -262,11 +269,13 @@ int Dtc_ObjComputeTruth( Gia_Man_t * p, int iObj, int * pCut, int * pTruth )
return 2;
return 0;
}
-void Dtc_ManCutMerge( Gia_Man_t * p, int iObj, int * pList0, int * pList1, Vec_Int_t * vCuts, Vec_Int_t * vCutsXor, Vec_Int_t * vCutsMaj )
+void Dtc_ManCutMerge( Gia_Man_t * p, int iObj, int * pList0, int * pList1, Vec_Int_t * vCuts, Vec_Int_t * vCutsXor2, Vec_Int_t * vCutsXor, Vec_Int_t * vCutsMaj )
{
int fVerbose = 0;
Vec_Int_t * vTemp;
int i, k, c, Type, * pCut0, * pCut1, pCut[4];
+ if ( fVerbose )
+ printf( "Object %d = :\n", iObj );
Vec_IntFill( vCuts, 2, 1 );
Vec_IntPush( vCuts, iObj );
Dtc_ForEachCut( pList0, pCut0, i )
@@ -277,8 +286,28 @@ void Dtc_ManCutMerge( Gia_Man_t * p, int iObj, int * pList0, int * pList1, Vec_I
if ( Dtc_ManCutCheckEqual(vCuts, pCut) )
continue;
Vec_IntAddToEntry( vCuts, 0, 1 );
+ if ( fVerbose )
+ printf( "%d : ", pCut[0] );
for ( c = 0; c <= pCut[0]; c++ )
+ {
Vec_IntPush( vCuts, pCut[c] );
+ if ( fVerbose && c )
+ printf( "%d ", pCut[c] );
+ }
+ if ( fVerbose )
+ printf( "\n" );
+ if ( pCut[0] == 2 )
+ {
+ int Value = Dtc_ObjComputeTruth( p, iObj, pCut, NULL );
+ assert( Value == 3 || Value == 0 );
+ if ( Value == 3 )
+ {
+ Vec_IntPush( vCutsXor2, pCut[1] );
+ Vec_IntPush( vCutsXor2, pCut[2] );
+ Vec_IntPush( vCutsXor2, iObj );
+ }
+ continue;
+ }
if ( pCut[0] != 3 )
continue;
Type = Dtc_ObjComputeTruth( p, iObj, pCut, NULL );
@@ -298,11 +327,12 @@ void Dtc_ManCutMerge( Gia_Man_t * p, int iObj, int * pList0, int * pList1, Vec_I
Vec_IntPush( vTemp, iObj );
}
}
-void Dtc_ManComputeCuts( Gia_Man_t * p, Vec_Int_t ** pvCutsXor, Vec_Int_t ** pvCutsMaj, int fVerbose )
+void Dtc_ManComputeCuts( Gia_Man_t * p, Vec_Int_t ** pvCutsXor2, Vec_Int_t ** pvCutsXor, Vec_Int_t ** pvCutsMaj, int fVerbose )
{
Gia_Obj_t * pObj;
int * pList0, * pList1, i, nCuts = 0;
Vec_Int_t * vTemp = Vec_IntAlloc( 1000 );
+ Vec_Int_t * vCutsXor2 = Vec_IntAlloc( Gia_ManAndNum(p) );
Vec_Int_t * vCutsXor = Vec_IntAlloc( Gia_ManAndNum(p) );
Vec_Int_t * vCutsMaj = Vec_IntAlloc( Gia_ManAndNum(p) );
Vec_Int_t * vCuts = Vec_IntAlloc( 30 * Gia_ManAndNum(p) );
@@ -319,7 +349,7 @@ void Dtc_ManComputeCuts( Gia_Man_t * p, Vec_Int_t ** pvCutsXor, Vec_Int_t ** pvC
{
pList0 = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, Gia_ObjFaninId0(pObj, i)) );
pList1 = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, Gia_ObjFaninId1(pObj, i)) );
- Dtc_ManCutMerge( p, i, pList0, pList1, vTemp, vCutsXor, vCutsMaj );
+ Dtc_ManCutMerge( p, i, pList0, pList1, vTemp, vCutsXor2, vCutsXor, vCutsMaj );
Vec_IntWriteEntry( vCuts, i, Vec_IntSize(vCuts) );
Vec_IntAppend( vCuts, vTemp );
nCuts += Vec_IntEntry( vTemp, 0 );
@@ -329,6 +359,10 @@ void Dtc_ManComputeCuts( Gia_Man_t * p, Vec_Int_t ** pvCutsXor, Vec_Int_t ** pvC
Gia_ManAndNum(p), nCuts, 1.0*nCuts/Gia_ManAndNum(p), 1.0*Vec_IntSize(vCuts)/Gia_ManAndNum(p) );
Vec_IntFree( vTemp );
Vec_IntFree( vCuts );
+ if ( pvCutsXor2 )
+ *pvCutsXor2 = vCutsXor2;
+ else
+ Vec_IntFree( vCutsXor2 );
*pvCutsXor = vCutsXor;
*pvCutsMaj = vCutsMaj;
}
@@ -375,6 +409,12 @@ void Dtc_ManPrintFadds( Vec_Int_t * vFadds )
printf( "%6d ", Vec_IntEntry(vFadds, 5*i+3) );
printf( "%6d ", Vec_IntEntry(vFadds, 5*i+4) );
printf( "\n" );
+
+ if ( i == 100 )
+ {
+ printf( "Skipping other FADDs.\n" );
+ break;
+ }
}
}
int Dtc_ManCompare( int * pCut0, int * pCut1 )
@@ -394,10 +434,10 @@ int Dtc_ManCompare2( int * pCut0, int * pCut1 )
return 0;
}
// returns array of 5-tuples containing inputs/sum/cout of each full adder
-Vec_Int_t * Gia_ManDetectFullAdders( Gia_Man_t * p, int fVerbose )
+Vec_Int_t * Gia_ManDetectFullAdders( Gia_Man_t * p, int fVerbose, Vec_Int_t ** pvCutsXor2 )
{
Vec_Int_t * vCutsXor, * vCutsMaj, * vFadds;
- Dtc_ManComputeCuts( p, &vCutsXor, &vCutsMaj, fVerbose );
+ Dtc_ManComputeCuts( p, pvCutsXor2, &vCutsXor, &vCutsMaj, fVerbose );
qsort( Vec_IntArray(vCutsXor), Vec_IntSize(vCutsXor)/4, 16, (int (*)(const void *, const void *))Dtc_ManCompare );
qsort( Vec_IntArray(vCutsMaj), Vec_IntSize(vCutsMaj)/4, 16, (int (*)(const void *, const void *))Dtc_ManCompare );
vFadds = Dtc_ManFindCommonCuts( p, vCutsXor, vCutsMaj );
@@ -762,7 +802,7 @@ Gia_Man_t * Gia_ManDupWithNaturalBoxes( Gia_Man_t * p, int nFaddMin, int fVerbos
assert( Gia_ManBoxNum(p) == 0 );
// detect FADDs
- vFadds = Gia_ManDetectFullAdders( p, fVerbose );
+ vFadds = Gia_ManDetectFullAdders( p, fVerbose, NULL );
assert( Vec_IntSize(vFadds) % 5 == 0 );
// map MAJ into its FADD
vMap = Gia_ManCreateMap( p, vFadds );
diff --git a/src/proof/acec/acecOrder.c b/src/proof/acec/acecOrder.c
index 9b2242d0..93ef7f10 100644
--- a/src/proof/acec/acecOrder.c
+++ b/src/proof/acec/acecOrder.c
@@ -198,7 +198,7 @@ Vec_Int_t * Gia_PolynFindOrder( Gia_Man_t * pGia, Vec_Int_t * vFadds, Vec_Int_t
***********************************************************************/
Vec_Int_t * Gia_PolynReorder( Gia_Man_t * pGia, int fVerbose, int fVeryVerbose )
{
- Vec_Int_t * vFadds = Gia_ManDetectFullAdders( pGia, fVeryVerbose );
+ Vec_Int_t * vFadds = Gia_ManDetectFullAdders( pGia, fVeryVerbose, NULL );
Vec_Int_t * vHadds = Gia_ManDetectHalfAdders( pGia, fVeryVerbose );
Vec_Int_t * vRecord = Gia_PolynFindOrder( pGia, vFadds, vHadds, fVerbose, fVeryVerbose );
Vec_Int_t * vOrder = Vec_IntAlloc( Gia_ManAndNum(pGia) );
diff --git a/src/proof/acec/acecPolyn.c b/src/proof/acec/acecPolyn.c
index be601405..042e0c59 100644
--- a/src/proof/acec/acecPolyn.c
+++ b/src/proof/acec/acecPolyn.c
@@ -64,26 +64,6 @@ struct Pln_Man_t_
/**Function*************************************************************
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Vec_Int_t * Pln_ManSimpleOrder( Gia_Man_t * p )
-{
- Vec_Int_t * vOrder; int Id;
- vOrder = Vec_IntStart( Gia_ManObjNum(p) );
- Gia_ManForEachAndId( p, Id )
- Vec_IntWriteEntry( vOrder, Id, Id );
- return vOrder;
-}
-
-/**Function*************************************************************
-
Synopsis [Computation manager.]
Description []
@@ -108,7 +88,7 @@ Pln_Man_t * Pln_ManAlloc( Gia_Man_t * pGia, Vec_Int_t * vOrder )
p->vTempM[1] = Vec_IntAlloc( 100 );
p->vTempM[2] = Vec_IntAlloc( 100 );
p->vTempM[3] = Vec_IntAlloc( 100 );
- p->vOrder = vOrder ? vOrder : Vec_IntStartNatural( Gia_ManObjNum(pGia) );
+ p->vOrder = vOrder ? Vec_IntDup(vOrder) : Vec_IntStartNatural( Gia_ManObjNum(pGia) );
assert( Vec_IntSize(p->vOrder) == Gia_ManObjNum(pGia) );
Vec_QueSetPriority( p->vQue, Vec_FltArrayP(p->vCounts) );
// add 0-constant and 1-monomial
@@ -131,36 +111,52 @@ void Pln_ManStop( Pln_Man_t * p )
Vec_IntFree( p->vTempM[1] );
Vec_IntFree( p->vTempM[2] );
Vec_IntFree( p->vTempM[3] );
- //Vec_IntFree( p->vOrder );
+ Vec_IntFree( p->vOrder );
ABC_FREE( p );
}
+int Pln_ManCompare3( int * pData0, int * pData1 )
+{
+ if ( pData0[0] < pData1[0] ) return -1;
+ if ( pData0[0] > pData1[0] ) return 1;
+ if ( pData0[1] < pData1[1] ) return -1;
+ if ( pData0[1] > pData1[1] ) return 1;
+ return 0;
+}
void Pln_ManPrintFinal( Pln_Man_t * p, int fVerbose, int fVeryVerbose )
{
Vec_Int_t * vArray;
- int k, Entry, iMono, iConst, Count = 0;
+ int i, k, Entry, iMono, iConst;
+ // collect triples
+ Vec_Int_t * vPairs = Vec_IntAlloc( 100 );
Vec_IntForEachEntry( p->vCoefs, iConst, iMono )
{
if ( iConst == 0 )
continue;
-
- Count++;
-
- if ( !fVerbose )
- continue;
-
- if ( Count > 25 )
+ vArray = Hsh_VecReadEntry( p->pHashC, iConst );
+ Vec_IntPush( vPairs, Vec_IntEntry(vArray, 0) );
+ vArray = Hsh_VecReadEntry( p->pHashM, iMono );
+ Vec_IntPush( vPairs, Vec_IntSize(vArray) ? Vec_IntEntry(vArray, 0) : 0 );
+ Vec_IntPushTwo( vPairs, iConst, iMono );
+ }
+ // sort triples
+ qsort( Vec_IntArray(vPairs), Vec_IntSize(vPairs)/4, 16, (int (*)(const void *, const void *))Pln_ManCompare3 );
+ // print
+ if ( fVerbose )
+ Vec_IntForEachEntryDouble( vPairs, iConst, iMono, i )
+ {
+ if ( i % 4 == 0 )
continue;
-
+ printf( "%-6d : ", i/4 );
vArray = Hsh_VecReadEntry( p->pHashC, iConst );
Vec_IntForEachEntry( vArray, Entry, k )
printf( "%s%d", Entry < 0 ? "-" : "+", (1 << (Abc_AbsInt(Entry)-1)) );
-
vArray = Hsh_VecReadEntry( p->pHashM, iMono );
Vec_IntForEachEntry( vArray, Entry, k )
printf( " * %d", Entry );
printf( "\n" );
}
- printf( "HashC = %d. HashM = %d. Total = %d. Used = %d.\n", Hsh_VecSize(p->pHashC), Hsh_VecSize(p->pHashM), p->nBuilds, Count );
+ printf( "HashC = %d. HashM = %d. Total = %d. Used = %d. ", Hsh_VecSize(p->pHashC), Hsh_VecSize(p->pHashM), p->nBuilds, Vec_IntSize(vPairs)/4 );
+ Vec_IntFree( vPairs );
}
/**Function*************************************************************
@@ -400,7 +396,7 @@ void Gia_PolynBuild( Gia_Man_t * pGia, Vec_Int_t * vOrder, int fSigned, int fVer
else
Vec_BitSetEntry( vPres, LevCur, 1 );
- if ( fVerbose )
+ if ( fVeryVerbose )
printf( "Line%5d Iter%10d : Obj =%6d. Order =%6d. HashC =%6d. HashM =%10d. Total =%10d. Used =%10d.\n",
Line++, Iter, LevCur, Vec_IntEntry(p->vOrder, LevCur), Hsh_VecSize(p->pHashC), Hsh_VecSize(p->pHashM), p->nBuilds, p->nUsed );
}
@@ -409,14 +405,37 @@ void Gia_PolynBuild( Gia_Man_t * pGia, Vec_Int_t * vOrder, int fSigned, int fVer
Gia_PolynBuildOne( p, iMono );
//clk2 += Abc_Clock() - temp;
}
- Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
//Abc_PrintTime( 1, "Time2", clk2 );
Pln_ManPrintFinal( p, fVerbose, fVeryVerbose );
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
Pln_ManStop( p );
Vec_BitFree( vPres );
}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Gia_PolynBuild2( Gia_Man_t * pGia, int fSigned, int fVerbose, int fVeryVerbose )
+{
+ 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 );
+
+ Hsh_VecManStop( pHashC );
+ Hsh_VecManStop( pHashM );
+}
+
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/proof/acec/module.make b/src/proof/acec/module.make
index c70b0a7d..900d3f5f 100644
--- a/src/proof/acec/module.make
+++ b/src/proof/acec/module.make
@@ -1,4 +1,5 @@
SRC += src/proof/acec/acecCore.c \
+ src/proof/acec/acecCover.c \
src/proof/acec/acecFadds.c \
src/proof/acec/acecOrder.c \
src/proof/acec/acecPolyn.c \
diff --git a/src/proof/cec/cec.h b/src/proof/cec/cec.h
index a0b92b52..e8b243d3 100644
--- a/src/proof/cec/cec.h
+++ b/src/proof/cec/cec.h
@@ -108,6 +108,7 @@ struct Cec_ParFra_t_
int fColorDiff; // miter with separate outputs
int fSatSweeping; // enable SAT sweeping
int fRunCSat; // enable another solver
+ int fUseOrigIds; // enable recording of original IDs
int fVeryVerbose; // verbose stats
int fVerbose; // verbose stats
int iOutFail; // the failed output
diff --git a/src/proof/cec/cecCore.c b/src/proof/cec/cecCore.c
index c9e9f67a..ed5c4ab7 100644
--- a/src/proof/cec/cecCore.c
+++ b/src/proof/cec/cecCore.c
@@ -236,7 +236,7 @@ Gia_Man_t * Cec_ManSatSolving( Gia_Man_t * pAig, Cec_ParSat_t * pPars )
Gia_Man_t * pNew;
Cec_ManPat_t * pPat;
pPat = Cec_ManPatStart();
- Cec_ManSatSolve( pPat, pAig, pPars );
+ Cec_ManSatSolve( pPat, pAig, pPars, NULL, NULL, NULL );
// pNew = Gia_ManDupDfsSkip( pAig );
pNew = Gia_ManDup( pAig );
Cec_ManPatStop( pPat );
@@ -351,6 +351,12 @@ Gia_Man_t * Cec_ManSatSweeping( Gia_Man_t * pAig, Cec_ParFra_t * pPars, int fSil
pIni = Gia_ManDup(pAig);
pIni->pReprs = pAig->pReprs; pAig->pReprs = NULL;
pIni->pNexts = pAig->pNexts; pAig->pNexts = NULL;
+ if ( pPars->fUseOrigIds )
+ {
+ Gia_ManOrigIdsInit( pIni );
+ Vec_IntFreeP( &pAig->vIdsEquiv );
+ pAig->vIdsEquiv = Vec_IntAlloc( 1000 );
+ }
// prepare the managers
// SAT sweeping
@@ -429,7 +435,7 @@ clk = Abc_Clock();
if ( pPars->fRunCSat )
Cec_ManSatSolveCSat( pPat, pSrm, pParsSat );
else
- Cec_ManSatSolve( pPat, pSrm, pParsSat );
+ Cec_ManSatSolve( pPat, pSrm, pParsSat, p->pAig->vIdsOrig, p->vXorNodes, pAig->vIdsEquiv );
p->timeSat += Abc_Clock() - clk;
if ( Cec_ManFraClassesUpdate( p, pSim, pPat, pSrm ) )
{
diff --git a/src/proof/cec/cecInt.h b/src/proof/cec/cecInt.h
index ef1dd983..d93e5e86 100644
--- a/src/proof/cec/cecInt.h
+++ b/src/proof/cec/cecInt.h
@@ -201,7 +201,7 @@ extern int Cec_ManCountNonConstOutputs( Gia_Man_t * pAig );
extern int Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig );
/*=== cecSolve.c ============================================================*/
extern int Cec_ObjSatVarValue( Cec_ManSat_t * p, Gia_Obj_t * pObj );
-extern void Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars );
+extern void Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Int_t * vIdsOrig, Vec_Int_t * vMiterPairs, Vec_Int_t * vEquivPairs );
extern void Cec_ManSatSolveCSat( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars );
extern Vec_Str_t * Cec_ManSatSolveSeq( Vec_Ptr_t * vPatts, Gia_Man_t * pAig, Cec_ParSat_t * pPars, int nRegs, int * pnPats );
extern Vec_Int_t * Cec_ManSatSolveMiter( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Str_t ** pvStatus );
diff --git a/src/proof/cec/cecSolve.c b/src/proof/cec/cecSolve.c
index e3db0b93..f75914e4 100644
--- a/src/proof/cec/cecSolve.c
+++ b/src/proof/cec/cecSolve.c
@@ -673,7 +673,7 @@ p->timeSatUndec += Abc_Clock() - clk;
SeeAlso []
***********************************************************************/
-void Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars )
+void Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Int_t * vIdsOrig, Vec_Int_t * vMiterPairs, Vec_Int_t * vEquivPairs )
{
Bar_Progress_t * pProgress = NULL;
Cec_ManSat_t * p;
@@ -706,6 +706,16 @@ clk2 = Abc_Clock();
status = Cec_ManSatCheckNode( p, Gia_ObjChild0(pObj) );
pObj->fMark0 = (status == 0);
pObj->fMark1 = (status == 1);
+ if ( status == 1 && vIdsOrig )
+ {
+ int iObj1 = Vec_IntEntry(vMiterPairs, 2*i);
+ int iObj2 = Vec_IntEntry(vMiterPairs, 2*i+1);
+ int OrigId1 = Vec_IntEntry(vIdsOrig, iObj1);
+ int OrigId2 = Vec_IntEntry(vIdsOrig, iObj2);
+ assert( OrigId1 >= 0 && OrigId2 >= 0 );
+ Vec_IntPushTwo( vEquivPairs, OrigId1, OrigId2 );
+ }
+
/*
if ( status == -1 )
{
diff --git a/src/proof/ssw/sswConstr.c b/src/proof/ssw/sswConstr.c
index a9ed17fc..a3a7e66f 100644
--- a/src/proof/ssw/sswConstr.c
+++ b/src/proof/ssw/sswConstr.c
@@ -533,8 +533,10 @@ clk = Abc_Clock();
continue;
}
Ssw_NodesAreConstrained( p, pObjNew, Aig_ManConst0(p->pFrames) );
- }
-
+ }
+ // sweep flops
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 1 );
// sweep internal nodes
Aig_ManForEachNode( p->pAig, pObj, i )
{
diff --git a/src/proof/ssw/sswSweep.c b/src/proof/ssw/sswSweep.c
index 6db673cc..77cb24de 100644
--- a/src/proof/ssw/sswSweep.c
+++ b/src/proof/ssw/sswSweep.c
@@ -287,6 +287,9 @@ clk = Abc_Clock();
Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
Saig_ManForEachPi( p->pAig, pObj, i )
Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreateCi(p->pFrames) );
+ // sweep flops
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 1, NULL );
// sweep internal nodes
Aig_ManForEachNode( p->pAig, pObj, i )
{
diff --git a/src/sat/bsat/satSolver.c b/src/sat/bsat/satSolver.c
index 9d885701..88a05093 100644
--- a/src/sat/bsat/satSolver.c
+++ b/src/sat/bsat/satSolver.c
@@ -1019,7 +1019,7 @@ sat_solver* sat_solver_new(void)
sat_solver* s = (sat_solver*)ABC_CALLOC( char, sizeof(sat_solver));
// Vec_SetAlloc_(&s->Mem, 15);
- Sat_MemAlloc_(&s->Mem, 15);
+ Sat_MemAlloc_(&s->Mem, 17);
s->hLearnts = -1;
s->hBinary = Sat_MemAppend( &s->Mem, NULL, 2, 0, 0 );
s->binary = clause_read( s, s->hBinary );