diff options
Diffstat (limited to 'src')
56 files changed, 4369 insertions, 622 deletions
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 ); |