diff options
239 files changed, 34757 insertions, 2631 deletions
@@ -27,7 +27,7 @@ MODULES := \ src/opt/cut src/opt/fxu src/opt/fxch src/opt/rwr src/opt/mfs src/opt/sim \ src/opt/ret src/opt/fret src/opt/res src/opt/lpk src/opt/nwk src/opt/rwt \ src/opt/cgt src/opt/csw src/opt/dar src/opt/dau src/opt/dsc src/opt/sfm src/opt/sbd \ - src/sat/bsat src/sat/xsat src/sat/satoko src/sat/csat src/sat/msat src/sat/psat src/sat/cnf src/sat/bmc src/sat/glucose \ + src/sat/bsat src/sat/xsat src/sat/satoko src/sat/csat src/sat/msat src/sat/psat src/sat/cnf src/sat/bmc src/sat/glucose src/sat/glucose2 \ src/bool/bdc src/bool/deco src/bool/dec src/bool/kit src/bool/lucky \ src/bool/rsb src/bool/rpo \ src/proof/pdr src/proof/abs src/proof/live src/proof/ssc src/proof/int \ @@ -2366,6 +2366,122 @@ SOURCE=.\src\sat\glucose\Vec.h SOURCE=.\src\sat\glucose\XAlloc.h # End Source File # End Group +# Begin Group "glucose2" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\glucose2\AbcGlucose2.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\AbcGlucose2.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\AbcGlucoseCmd2.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Alg.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Alloc.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\BoundedQueue.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\CGlucose.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\CGlucoseCore.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Constants.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Dimacs.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Glucose2.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Heap.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\IntTypes.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Map.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Options.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Options2.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\ParseUtils.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\pstdint.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Queue.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\SimpSolver.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\SimpSolver2.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Solver.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\SolverTypes.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Sort.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\System.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\System2.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Vec.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\XAlloc.h +# End Source File +# End Group # End Group # Begin Group "opt" @@ -4787,6 +4903,10 @@ SOURCE=.\src\aig\gia\giaCSat2.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaCSat3.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaCSatOld.c # End Source File # Begin Source File @@ -4799,6 +4919,10 @@ SOURCE=.\src\aig\gia\giaCut.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaDecs.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaDeep.c # End Source File # Begin Source File @@ -4943,6 +5067,14 @@ SOURCE=.\src\aig\gia\giaMini.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaMinLut.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaMinLut2.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaMuxes.c # End Source File # Begin Source File @@ -4963,6 +5095,10 @@ SOURCE=.\src\aig\gia\giaPat.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaPat2.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaPf.c # End Source File # Begin Source File @@ -4971,10 +5107,26 @@ SOURCE=.\src\aig\gia\giaQbf.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaReshape1.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaReshape2.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaResub.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaResub2.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaResub3.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaRetime.c # End Source File # Begin Source File @@ -5039,14 +5191,6 @@ SOURCE=.\src\aig\gia\giaSim2.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaSim4.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\gia\giaSim5.c -# End Source File -# Begin Source File - SOURCE=.\src\aig\gia\giaSimBase.c # End Source File # Begin Source File @@ -5067,6 +5211,10 @@ SOURCE=.\src\aig\gia\giaStg.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaStoch.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaStr.c # End Source File # Begin Source File @@ -5079,6 +5227,10 @@ SOURCE=.\src\aig\gia\giaSupp.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaSupps.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaSweep.c # End Source File # Begin Source File @@ -5411,14 +5563,26 @@ SOURCE=.\src\proof\cec\cecSatG.c # End Source File # Begin Source File +SOURCE=.\src\proof\cec\cecSatG2.c +# End Source File +# Begin Source File + SOURCE=.\src\proof\cec\cecSeq.c # End Source File # Begin Source File +SOURCE=.\src\proof\cec\cecSim.c +# End Source File +# Begin Source File + SOURCE=.\src\proof\cec\cecSolve.c # End Source File # Begin Source File +SOURCE=.\src\proof\cec\cecSolveG.c +# End Source File +# Begin Source File + SOURCE=.\src\proof\cec\cecSplit.c # End Source File # Begin Source File diff --git a/src/aig/gia/gia.c b/src/aig/gia/gia.c index 7947a60e..ed6e276a 100644 --- a/src/aig/gia/gia.c +++ b/src/aig/gia/gia.c @@ -19,6 +19,7 @@ ***********************************************************************/ #include "gia.h" +#include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START @@ -297,6 +298,101 @@ void Gia_ManStructExperiment( Gia_Man_t * p ) Vec_PtrFree( vGias ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_EnumFirstUnused( int * pUsed, int nVars ) +{ + int i; + for ( i = 0; i < nVars; i++ ) + if ( pUsed[i] == 0 ) + return i; + return -1; +} +void Gia_EnumPerms_rec( int * pUsed, int nVars, int * pPerm, int nPerm, int * pCount, FILE * pFile, int nLogVars ) +{ + int i, k, New; + if ( nPerm == nVars ) + { + if ( pFile ) + { + for ( i = 0; i < nLogVars; i++ ) + fprintf( pFile, "%c", '0' + ((*pCount) >> (nLogVars-1-i) & 1) ); + fprintf( pFile, " " ); + for ( i = 0; i < nVars; i++ ) + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, "%c", '0' + (pPerm[i] == k) ); + fprintf( pFile, "\n" ); + } + else + { + if ( *pCount < 20 ) + { + printf( "%5d : ", (*pCount) ); + for ( i = 0; i < nVars; i += 2 ) + printf( "%d %d ", pPerm[i], pPerm[i+1] ); + printf( "\n" ); + } + } + (*pCount)++; + return; + } + New = Gia_EnumFirstUnused( pUsed, nVars ); + assert( New >= 0 ); + pPerm[nPerm] = New; + assert( pUsed[New] == 0 ); + pUsed[New] = 1; + // try remaining ones + for ( i = 0; i < nVars; i++ ) + { + if ( pUsed[i] == 1 ) + continue; + pPerm[nPerm+1] = i; + assert( pUsed[i] == 0 ); + pUsed[i] = 1; + Gia_EnumPerms_rec( pUsed, nVars, pPerm, nPerm+2, pCount, pFile, nLogVars ); + assert( pUsed[i] == 1 ); + pUsed[i] = 0; + } + assert( pUsed[New] == 1 ); + pUsed[New] = 0; +} +void Gia_EnumPerms( int nVars ) +{ + int nLogVars = 0, Count = 0; + int * pUsed = ABC_CALLOC( int, nVars ); + int * pPerm = ABC_CALLOC( int, nVars ); + FILE * pFile = fopen( "pairset.pla", "wb" ); + assert( nVars % 2 == 0 ); + + printf( "Printing sets of pairs for %d objects:\n", nVars ); + Gia_EnumPerms_rec( pUsed, nVars, pPerm, 0, &Count, NULL, -1 ); + if ( Count > 20 ) + printf( "...\n" ); + printf( "Finished enumerating %d sets of pairs.\n", Count ); + + nLogVars = Abc_Base2Log( Count ); + printf( "Need %d variables to encode %d sets.\n", nLogVars, Count ); + Count = 0; + fprintf( pFile, ".i %d\n", nLogVars ); + fprintf( pFile, ".o %d\n", nVars*nVars ); + Gia_EnumPerms_rec( pUsed, nVars, pPerm, 0, &Count, pFile, nLogVars ); + fprintf( pFile, ".e\n" ); + fclose( pFile ); + printf( "Finished dumping file \"%s\".\n", "pairset.pla" ); + + ABC_FREE( pUsed ); + ABC_FREE( pPerm ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index ae9835ee..5548def6 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -171,6 +171,7 @@ struct Gia_Man_t_ Vec_Int_t * vCoReqs; // CO required times Vec_Int_t * vCoArrs; // CO arrival times Vec_Int_t * vCoAttrs; // CO attributes + Vec_Int_t * vWeights; // object attributes int And2Delay; // delay of the AND gate float DefInArrs; // default PI arrival times float DefOutReqs; // default PO required times @@ -179,6 +180,7 @@ struct Gia_Man_t_ int nTravIdsAlloc; // the number of trav IDs allocated Vec_Ptr_t * vNamesIn; // the input names Vec_Ptr_t * vNamesOut; // the output names + Vec_Ptr_t * vNamesNode; // the node names Vec_Int_t * vUserPiIds; // numbers assigned to PIs by the user Vec_Int_t * vUserPoIds; // numbers assigned to POs by the user Vec_Int_t * vUserFfIds; // numbers assigned to FFs by the user @@ -214,6 +216,8 @@ struct Gia_Man_t_ Vec_Wrd_t * vSimsPo; Vec_Int_t * vClassOld; Vec_Int_t * vClassNew; + Vec_Int_t * vPats; + Vec_Bit_t * vPolars; // incremental simulation int fIncrSim; int iNextPi; @@ -235,6 +239,7 @@ struct Gia_Man_t_ Vec_Wrd_t * vSuppWords; // support information Vec_Int_t vCopiesTwo; // intermediate copies Vec_Int_t vSuppVars; // used variables + Vec_Int_t vVarMap; // used variables Gia_Dat_t * pUData; }; @@ -339,6 +344,7 @@ struct Jf_Par_t_ int fCutMin; int fFuncDsd; int fGenCnf; + int fGenLit; int fCnfObjIds; int fAddOrCla; int fCnfMapping; @@ -477,6 +483,11 @@ static inline int Gia_ObjValue( Gia_Obj_t * pObj ) { static inline void Gia_ObjSetValue( Gia_Obj_t * pObj, int i ) { pObj->Value = i; } static inline int Gia_ObjPhase( Gia_Obj_t * pObj ) { return pObj->fPhase; } static inline int Gia_ObjPhaseReal( Gia_Obj_t * pObj ) { return Gia_Regular(pObj)->fPhase ^ Gia_IsComplement(pObj); } +static inline int Gia_ObjPhaseDiff( Gia_Man_t * p, int i, int k ) { return Gia_ManObj(p, i)->fPhase ^ Gia_ManObj(p, k)->fPhase; } +static inline char * Gia_ObjCiName( Gia_Man_t * p, int i ) { return p->vNamesIn ? (char*)Vec_PtrEntry(p->vNamesIn, i) : NULL; } +static inline char * Gia_ObjCoName( Gia_Man_t * p, int i ) { return p->vNamesOut ? (char*)Vec_PtrEntry(p->vNamesOut, i) : NULL; } +static inline char * Gia_ObjName( Gia_Man_t * p, int i ) { return p->vNamesNode ? (char*)Vec_PtrEntry(p->vNamesNode, i) : NULL; } +static inline char * Gia_ObjNameObj( Gia_Man_t * p, Gia_Obj_t * pObj ) { return p->vNamesNode ? (char*)Vec_PtrEntry(p->vNamesNode, Gia_ObjId(p, pObj)) : NULL; } static inline int Gia_ObjIsTerm( Gia_Obj_t * pObj ) { return pObj->fTerm; } static inline int Gia_ObjIsAndOrConst0( Gia_Obj_t * pObj ) { return!pObj->fTerm; } @@ -538,6 +549,7 @@ static inline void Gia_ObjFlipFaninC0( Gia_Obj_t * pObj ) { static inline int Gia_ObjFaninNum( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsMux(p, pObj) ) return 3; if ( Gia_ObjIsAnd(pObj) ) return 2; if ( Gia_ObjIsCo(pObj) ) return 1; return 0; } static inline int Gia_ObjWhatFanin( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanin ) { if ( Gia_ObjFanin0(pObj) == pFanin ) return 0; if ( Gia_ObjFanin1(pObj) == pFanin ) return 1; if ( Gia_ObjFanin2(p, pObj) == pFanin ) return 2; assert(0); return -1; } +static inline int Gia_ManCoDriverId( Gia_Man_t * p, int iCoIndex ) { return Gia_ObjFaninId0p(p, Gia_ManCo(p, iCoIndex)); } static inline int Gia_ManPoIsConst( Gia_Man_t * p, int iPoIndex ) { return Gia_ObjFaninId0p(p, Gia_ManPo(p, iPoIndex)) == 0; } static inline int Gia_ManPoIsConst0( Gia_Man_t * p, int iPoIndex ) { return Gia_ManIsConst0Lit( Gia_ObjFaninLit0p(p, Gia_ManPo(p, iPoIndex)) ); } static inline int Gia_ManPoIsConst1( Gia_Man_t * p, int iPoIndex ) { return Gia_ManIsConst1Lit( Gia_ObjFaninLit0p(p, Gia_ManPo(p, iPoIndex)) ); } @@ -570,6 +582,7 @@ static inline int Gia_ObjPhaseRealLit( Gia_Man_t * p, int iLit ) { static inline int Gia_ObjLevelId( Gia_Man_t * p, int Id ) { return Vec_IntGetEntry(p->vLevels, Id); } static inline int Gia_ObjLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjLevelId( p, Gia_ObjId(p,pObj) ); } +static inline void Gia_ObjUpdateLevelId( Gia_Man_t * p, int Id, int l ) { Vec_IntSetEntry(p->vLevels, Id, Abc_MaxInt(Vec_IntEntry(p->vLevels, Id), l)); } static inline void Gia_ObjSetLevelId( Gia_Man_t * p, int Id, int l ) { Vec_IntSetEntry(p->vLevels, Id, l); } static inline void Gia_ObjSetLevel( Gia_Man_t * p, Gia_Obj_t * pObj, int l ) { Gia_ObjSetLevelId( p, Gia_ObjId(p,pObj), l ); } static inline void Gia_ObjSetCoLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsCo(pObj) ); Gia_ObjSetLevel( p, pObj, Gia_ObjLevel(p,Gia_ObjFanin0(pObj)) ); } @@ -610,10 +623,14 @@ static inline void Gia_ObjSetTravIdCurrent( Gia_Man_t * p, Gia_Obj_t * p static inline void Gia_ObjSetTravIdPrevious( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjId(p, pObj) < p->nTravIdsAlloc ); p->pTravIds[Gia_ObjId(p, pObj)] = p->nTravIds - 1; } static inline int Gia_ObjIsTravIdCurrent( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjId(p, pObj) < p->nTravIdsAlloc ); return (p->pTravIds[Gia_ObjId(p, pObj)] == p->nTravIds); } static inline int Gia_ObjIsTravIdPrevious( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjId(p, pObj) < p->nTravIdsAlloc ); return (p->pTravIds[Gia_ObjId(p, pObj)] == p->nTravIds - 1); } +static inline int Gia_ObjUpdateTravIdCurrent( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return 1; Gia_ObjSetTravIdCurrent(p, pObj); return 0; } +static inline int Gia_ObjUpdateTravIdPrevious( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsTravIdPrevious(p, pObj) ) return 1; Gia_ObjSetTravIdPrevious(p, pObj); return 0; } static inline void Gia_ObjSetTravIdCurrentId( Gia_Man_t * p, int Id ) { assert( Id < p->nTravIdsAlloc ); p->pTravIds[Id] = p->nTravIds; } static inline void Gia_ObjSetTravIdPreviousId( Gia_Man_t * p, int Id ) { assert( Id < p->nTravIdsAlloc ); p->pTravIds[Id] = p->nTravIds - 1; } static inline int Gia_ObjIsTravIdCurrentId( Gia_Man_t * p, int Id ) { assert( Id < p->nTravIdsAlloc ); return (p->pTravIds[Id] == p->nTravIds); } static inline int Gia_ObjIsTravIdPreviousId( Gia_Man_t * p, int Id ) { assert( Id < p->nTravIdsAlloc ); return (p->pTravIds[Id] == p->nTravIds - 1); } +static inline int Gia_ObjUpdateTravIdCurrentId( Gia_Man_t * p, int Id ) { if ( Gia_ObjIsTravIdCurrentId(p, Id) ) return 1; Gia_ObjSetTravIdCurrentId(p, Id); return 0; } +static inline int Gia_ObjUpdateTravIdPreviousId( Gia_Man_t * p, int Id ) { if ( Gia_ObjIsTravIdPreviousId(p, Id) ) return 1; Gia_ObjSetTravIdPreviousId(p, Id); return 0; } static inline void Gia_ManTimeClean( Gia_Man_t * p ) { int i; assert( p->vTiming != NULL ); Vec_FltFill(p->vTiming, 3*Gia_ManObjNum(p), 0); for ( i = 0; i < Gia_ManObjNum(p); i++ ) Vec_FltWriteEntry( p->vTiming, 3*i+1, (float)(ABC_INFINITY) ); } static inline void Gia_ManTimeStart( Gia_Man_t * p ) { assert( p->vTiming == NULL ); p->vTiming = Vec_FltAlloc(0); Gia_ManTimeClean( p ); } @@ -1067,9 +1084,11 @@ static inline void Gia_ClassUndoPair( Gia_Man_t * p, int i ) { a #define Gia_ManForEachClassReverse( p, i ) \ for ( i = Gia_ManObjNum(p) - 1; i > 0; i-- ) if ( !Gia_ObjIsHead(p, i) ) {} else #define Gia_ClassForEachObj( p, i, iObj ) \ - for ( assert(Gia_ObjIsHead(p, i)), iObj = i; iObj > 0; iObj = Gia_ObjNext(p, iObj) ) + for ( assert(Gia_ObjIsHead(p, i) && i), iObj = i; iObj > 0; iObj = Gia_ObjNext(p, iObj) ) #define Gia_ClassForEachObj1( p, i, iObj ) \ for ( assert(Gia_ObjIsHead(p, i)), iObj = Gia_ObjNext(p, i); iObj > 0; iObj = Gia_ObjNext(p, iObj) ) +#define Gia_ClassForEachObjStart( p, i, iObj, Start ) \ + for ( assert(Gia_ObjIsHead(p, i)), iObj = Gia_ObjNext(p, Start); iObj > 0; iObj = Gia_ObjNext(p, iObj) ) static inline int Gia_ObjFoffsetId( Gia_Man_t * p, int Id ) { return Vec_IntEntry( p->vFanout, Id ); } @@ -1149,7 +1168,13 @@ static inline int Gia_ObjCellId( Gia_Man_t * p, int iLit ) { re for ( i = 1; (i < p->nObjs) && ((pObj) = Gia_ManObj(p, i)); i++ ) #define Gia_ManForEachObjVec( vVec, p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) -#define Gia_ManForEachObjVecReverse( vVec, p, pObj, i ) \ +#define Gia_ManForEachObjVecStart( vVec, p, pObj, i, Start ) \ + for ( i = Start; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) +#define Gia_ManForEachObjVecStop( vVec, p, pObj, i, Stop ) \ + for ( i = 0; (i < Stop) && ((pObj) = Gia_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) +#define Gia_ManForEachObjVecStartStop( vVec, p, pObj, i, Start, Stop ) \ + for ( i = Start; (i < Stop) && ((pObj) = Gia_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) +#define Gia_ManForEachObjVecReverse( vVec, p, pObj, i ) \ for ( i = Vec_IntSize(vVec) - 1; (i >= 0) && ((pObj) = Gia_ManObj(p, Vec_IntEntry(vVec,i))); i-- ) #define Gia_ManForEachObjVecLit( vVec, p, pObj, fCompl, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManObj(p, Abc_Lit2Var(Vec_IntEntry(vVec,i)))) && (((fCompl) = Abc_LitIsCompl(Vec_IntEntry(vVec,i))),1); i++ ) @@ -1245,7 +1270,7 @@ extern Cbs_Man_t * Cbs_ManAlloc( Gia_Man_t * pGia ); extern void Cbs_ManStop( Cbs_Man_t * p ); extern int Cbs_ManSolve( Cbs_Man_t * p, Gia_Obj_t * pObj ); extern int Cbs_ManSolve2( Cbs_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 ); -extern Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ); +extern Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int f0Proved, int fVerbose ); extern void Cbs_ManSetConflictNum( Cbs_Man_t * p, int Num ); extern Vec_Int_t * Cbs_ReadModel( Cbs_Man_t * p ); /*=== giaCTas.c ============================================================*/ @@ -1255,6 +1280,11 @@ extern void Gia_ManPrintFanio( Gia_Man_t * pGia, int nNodes ); extern Gia_Man_t * Gia_ManDupCof( Gia_Man_t * p, int iVar ); extern Gia_Man_t * Gia_ManDupCofAllInt( Gia_Man_t * p, Vec_Int_t * vSigs, int fVerbose ); extern Gia_Man_t * Gia_ManDupCofAll( Gia_Man_t * p, int nFanLim, int fVerbose ); +/*=== giaDecs.c ============================================================*/ +extern int Gia_ResubVarNum( Vec_Int_t * vResub ); +extern word Gia_ResubToTruth6( Vec_Int_t * vResub ); +extern int Gia_ManEvalSolutionOne( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vSet, int nWords, int fVerbose ); +extern Vec_Int_t * Gia_ManDeriveSolutionOne( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vSet, int nWords, int Type ); /*=== giaDfs.c ============================================================*/ extern void Gia_ManCollectCis( Gia_Man_t * p, int * pNodes, int nNodes, Vec_Int_t * vSupp ); extern void Gia_ManCollectAnds_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vNodes ); @@ -1264,6 +1294,7 @@ extern Vec_Int_t * Gia_ManCollectNodesCis( Gia_Man_t * p, int * pNodes, extern int Gia_ManSuppSize( Gia_Man_t * p, int * pNodes, int nNodes ); extern int Gia_ManConeSize( Gia_Man_t * p, int * pNodes, int nNodes ); extern Vec_Vec_t * Gia_ManLevelize( Gia_Man_t * p ); +extern Vec_Wec_t * Gia_ManLevelizeR( Gia_Man_t * p ); extern Vec_Int_t * Gia_ManOrderReverse( Gia_Man_t * p ); extern void Gia_ManCollectTfi( Gia_Man_t * p, Vec_Int_t * vRoots, Vec_Int_t * vNodes ); extern void Gia_ManCollectTfo( Gia_Man_t * p, Vec_Int_t * vRoots, Vec_Int_t * vNodes ); @@ -1272,7 +1303,7 @@ extern void Gia_ManDupRemapLiterals( Vec_Int_t * vLits, Gia_Man_t extern void Gia_ManDupRemapEquiv( Gia_Man_t * pNew, Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupOrderDfs( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupOrderDfsChoices( Gia_Man_t * p ); -extern Gia_Man_t * Gia_ManDupOrderDfsReverse( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupOrderDfsReverse( Gia_Man_t * p, int fRevFans, int fRevOuts ); extern Gia_Man_t * Gia_ManDupOutputGroup( Gia_Man_t * p, int iOutStart, int iOutStop ); extern Gia_Man_t * Gia_ManDupOutputVec( Gia_Man_t * p, Vec_Int_t * vOutPres ); extern Gia_Man_t * Gia_ManDupSelectedOutputs( Gia_Man_t * p, Vec_Int_t * vOutsLeft ); @@ -1298,6 +1329,7 @@ extern Gia_Man_t * Gia_ManDupMarked( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupTimes( Gia_Man_t * p, int nTimes ); extern Gia_Man_t * Gia_ManDupDfs( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupDfsOnePo( Gia_Man_t * p, int iPo ); +extern Gia_Man_t * Gia_ManDupDfsRehash( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupCofactorVar( Gia_Man_t * p, int iVar, int Value ); extern Gia_Man_t * Gia_ManDupCofactorObj( Gia_Man_t * p, int iObj, int Value ); extern Gia_Man_t * Gia_ManDupMux( int iVar, Gia_Man_t * pCof1, Gia_Man_t * pCof0 ); @@ -1397,6 +1429,7 @@ extern void Gia_ManFanoutStart( Gia_Man_t * p ); extern void Gia_ManFanoutStop( Gia_Man_t * p ); extern void Gia_ManStaticFanoutStart( Gia_Man_t * p ); extern void Gia_ManStaticFanoutStop( Gia_Man_t * p ); +extern void Gia_ManStaticMappingFanoutStart( Gia_Man_t * p ); /*=== giaForce.c =========================================================*/ extern void For_ManExperiment( Gia_Man_t * pGia, int nIters, int fClustered, int fVerbose ); /*=== giaFrames.c =========================================================*/ @@ -1480,7 +1513,7 @@ extern void Gia_ManPrintStatsMiter( Gia_Man_t * p, int fVerbose ) extern void Gia_ManSetRegNum( Gia_Man_t * p, int nRegs ); extern void Gia_ManReportImprovement( Gia_Man_t * p, Gia_Man_t * pNew ); extern void Gia_ManPrintNpnClasses( Gia_Man_t * p ); -extern void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs ); +extern void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs ); /*=== giaMem.c ===========================================================*/ extern Gia_MmFixed_t * Gia_MmFixedStart( int nEntrySize, int nEntriesMax ); extern void Gia_MmFixedStop( Gia_MmFixed_t * p, int fVerbose ); @@ -1504,7 +1537,7 @@ extern void Mf_ManSetDefaultPars( Jf_Par_t * pPars ); extern Gia_Man_t * Mf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ); extern void * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fMapping, int fVerbose ); /*=== giaMini.c ===========================================================*/ -extern Gia_Man_t * Gia_ManReadMiniAig( char * pFileName ); +extern Gia_Man_t * Gia_ManReadMiniAig( char * pFileName, int fGiaSimple ); extern void Gia_ManWriteMiniAig( Gia_Man_t * pGia, char * pFileName ); extern Gia_Man_t * Gia_ManReadMiniLut( char * pFileName ); extern void Gia_ManWriteMiniLut( Gia_Man_t * pGia, char * pFileName ); @@ -1557,6 +1590,15 @@ extern void Gia_ManIncrSimStart( Gia_Man_t * p, int nWords, int n extern void Gia_ManIncrSimSet( Gia_Man_t * p, Vec_Int_t * vObjLits ); extern int Gia_ManIncrSimCheckOver( Gia_Man_t * p, int iLit0, int iLit1 ); extern int Gia_ManIncrSimCheckEqual( Gia_Man_t * p, int iLit0, int iLit1 ); +/*=== giaSimBase.c ============================================================*/ +extern Vec_Wrd_t * Gia_ManSimPatSim( Gia_Man_t * p ); +extern Vec_Wrd_t * Gia_ManSimPatSimOut( Gia_Man_t * pGia, Vec_Wrd_t * vSimsPi, int fOuts ); +extern void Gia_ManSim2ArrayOne( Vec_Wrd_t * vSimsPi, Vec_Int_t * vRes ); +extern Vec_Wec_t * Gia_ManSim2Array( Vec_Ptr_t * vSims ); +extern Vec_Wrd_t * Gia_ManArray2SimOne( Vec_Int_t * vRes ); +extern Vec_Ptr_t * Gia_ManArray2Sim( Vec_Wec_t * vRes ); +extern void Gia_ManPtrWrdDumpBin( char * pFileName, Vec_Ptr_t * p, int fVerbose ); +extern Vec_Ptr_t * Gia_ManPtrWrdReadBin( char * pFileName, int fVerbose ); /*=== giaSpeedup.c ============================================================*/ extern float Gia_ManDelayTraceLut( Gia_Man_t * p ); extern float Gia_ManDelayTraceLutPrint( Gia_Man_t * p, int fVerbose ); @@ -1668,6 +1710,7 @@ extern void Gia_ManSetPhase1( Gia_Man_t * p ); extern void Gia_ManCleanPhase( Gia_Man_t * p ); extern int Gia_ManCheckCoPhase( Gia_Man_t * p ); extern int Gia_ManLevelNum( Gia_Man_t * p ); +extern int Gia_ManLevelRNum( Gia_Man_t * p ); extern Vec_Int_t * Gia_ManGetCiLevels( Gia_Man_t * p ); extern int Gia_ManSetLevels( Gia_Man_t * p, Vec_Int_t * vCiLevels ); extern Vec_Int_t * Gia_ManReverseLevel( Gia_Man_t * p ); @@ -1682,7 +1725,9 @@ extern int Gia_ObjRecognizeExor( Gia_Obj_t * pObj, Gia_Obj_t ** extern Gia_Obj_t * Gia_ObjRecognizeMux( Gia_Obj_t * pNode, Gia_Obj_t ** ppNodeT, Gia_Obj_t ** ppNodeE ); extern int Gia_ObjRecognizeMuxLits( Gia_Man_t * p, Gia_Obj_t * pNode, int * iLitT, int * iLitE ); extern int Gia_NodeMffcSize( Gia_Man_t * p, Gia_Obj_t * pNode ); +extern int Gia_NodeMffcSizeMark( Gia_Man_t * p, Gia_Obj_t * pNode ); extern int Gia_NodeMffcSizeSupp( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSupp ); +extern int Gia_NodeMffcMapping( Gia_Man_t * p ); extern int Gia_ManHasDangling( Gia_Man_t * p ); extern int Gia_ManMarkDangling( Gia_Man_t * p ); extern Vec_Int_t * Gia_ManGetDangling( Gia_Man_t * p ); @@ -1704,6 +1749,7 @@ extern int Gia_ManCheckSuppOverlap( Gia_Man_t * p, int iNode1, i extern int Gia_ManCountPisWithFanout( Gia_Man_t * p ); extern int Gia_ManCountPosWithNonZeroDrivers( Gia_Man_t * p ); extern void Gia_ManUpdateCopy( Vec_Int_t * vCopy, Gia_Man_t * p ); +extern Vec_Int_t * Gia_ManComputeDistance( Gia_Man_t * p, int iObj, Vec_Int_t * vObjs, int fVerbose ); /*=== giaCTas.c ===========================================================*/ typedef struct Tas_Man_t_ Tas_Man_t; diff --git a/src/aig/gia/giaAig.c b/src/aig/gia/giaAig.c index dfd4a467..91a9c600 100644 --- a/src/aig/gia/giaAig.c +++ b/src/aig/gia/giaAig.c @@ -102,6 +102,41 @@ Gia_Man_t * Gia_ManFromAig( Aig_Man_t * p ) /**Function************************************************************* + Synopsis [Checks integrity of choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCheckChoices_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( !pObj || !Gia_ObjIsAnd(pObj) || pObj->fPhase ) + return; + pObj->fPhase = 1; + Gia_ManCheckChoices_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManCheckChoices_rec( p, Gia_ObjFanin1(pObj) ); + Gia_ManCheckChoices_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)) ); +} +void Gia_ManCheckChoices( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, fFound = 0; + Gia_ManCleanPhase( p ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManCheckChoices_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachAnd( p, pObj, i ) + if ( !pObj->fPhase ) + printf( "Object %d is dangling.\n", i ), fFound = 1; + if ( !fFound ) + printf( "There are no dangling objects.\n" ); + Gia_ManCleanPhase( p ); +} + +/**Function************************************************************* + Synopsis [Duplicates AIG in the DFS order.] Description [] @@ -155,6 +190,7 @@ Gia_Man_t * Gia_ManFromAigChoices( Aig_Man_t * p ) Gia_ManAppendCo( pNew, Gia_ObjChild0Copy(pObj) ); Gia_ManSetRegNum( pNew, Aig_ManRegNum(p) ); //assert( Gia_ManObjNum(pNew) == Aig_ManObjNum(p) ); + //Gia_ManCheckChoices( pNew ); return pNew; } diff --git a/src/aig/gia/giaAiger.c b/src/aig/gia/giaAiger.c index c9ad28db..aafe311b 100644 --- a/src/aig/gia/giaAiger.c +++ b/src/aig/gia/giaAiger.c @@ -176,6 +176,7 @@ Vec_Str_t * Gia_AigerWriteLiterals( Vec_Int_t * vLits ) Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSimple, int fSkipStrash, int fCheck ) { Gia_Man_t * pNew, * pTemp; + Vec_Ptr_t * vNamesIn = NULL, * vNamesOut = NULL, * vNamesRegIn = NULL, * vNamesRegOut = NULL, * vNamesNode = NULL; Vec_Int_t * vLits = NULL, * vPoTypes = NULL; Vec_Int_t * vNodes, * vDrivers, * vInits = NULL; int iObj, iNode0, iNode1, fHieOnly = 0; @@ -377,6 +378,101 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi pCur = pSymbols; if ( pCur < (unsigned char *)pContents + nFileSize && *pCur != 'c' ) { + int fReadNames = 1; + if ( fReadNames ) + { + int fError = 0; + while ( !fError && pCur < (unsigned char *)pContents + nFileSize && *pCur != 'c' ) + { + int iTerm; + char * pType = (char *)pCur; + char * pName = NULL; + // check terminal type + if ( *pCur != 'i' && *pCur != 'o' && *pCur != 'l' && *pCur != 'n' ) + { + fError = 1; + break; + } + // get terminal number + iTerm = atoi( (char *)++pCur ); while ( *pCur++ != ' ' ); + // skip spaces + while ( *pCur == ' ' ) + pCur++; + // skip till the end of line + for ( pName = (char *)pCur; *pCur && *pCur != '\n'; pCur++ ); + if ( *pCur == '\n' ) + *pCur = 0; + // save the name + if ( *pType == 'i' ) + { + if ( vNamesIn == NULL ) + vNamesIn = Vec_PtrAlloc( nInputs + nLatches ); + if ( Vec_PtrSize(vNamesIn) != iTerm ) + { + fError = 1; + break; + } + Vec_PtrPush( vNamesIn, Abc_UtilStrsav(pName) ); + } + else if ( *pType == 'o' ) + { + if ( vNamesOut == NULL ) + vNamesOut = Vec_PtrAlloc( nOutputs + nLatches ); + if ( Vec_PtrSize(vNamesOut) != iTerm ) + { + fError = 1; + break; + } + Vec_PtrPush( vNamesOut, Abc_UtilStrsav(pName) ); + } + else if ( *pType == 'l' ) + { + char Buffer[1000]; + assert( strlen(pName) < 995 ); + sprintf( Buffer, "%s_in", pName ); + if ( vNamesRegIn == NULL ) + vNamesRegIn = Vec_PtrAlloc( nLatches ); + if ( vNamesRegOut == NULL ) + vNamesRegOut = Vec_PtrAlloc( nLatches ); + if ( Vec_PtrSize(vNamesRegIn) != iTerm ) + { + fError = 1; + break; + } + Vec_PtrPush( vNamesRegIn, Abc_UtilStrsav(Buffer) ); + Vec_PtrPush( vNamesRegOut, Abc_UtilStrsav(pName) ); + } + else if ( *pType == 'n' ) + { + if ( Vec_IntSize(&pNew->vHTable) != 0 ) + { + printf( "Structural hashing should be disabled to read internal nodes names.\n" ); + fError = 1; + break; + } + if ( vNamesNode == NULL ) + vNamesNode = Vec_PtrStart( Gia_ManObjNum(pNew) ); + Vec_PtrWriteEntry( vNamesNode, iTerm, Abc_UtilStrsav(pName) ); + } + else + { + fError = 1; + break; + } + pCur++; + } + if ( fError ) + { + printf( "Error occurred when reading signal names. Signal names ignored.\n" ); + if ( vNamesIn ) Vec_PtrFreeFree( vNamesIn ), vNamesIn = NULL; + if ( vNamesOut ) Vec_PtrFreeFree( vNamesOut ), vNamesOut = NULL; + if ( vNamesRegIn ) Vec_PtrFreeFree( vNamesRegIn ), vNamesRegIn = NULL; + if ( vNamesRegOut ) Vec_PtrFreeFree( vNamesRegOut ), vNamesRegOut = NULL; + if ( vNamesNode ) Vec_PtrFreeFree( vNamesNode ), vNamesNode = NULL; + } + } + else + { int fBreakUsed = 0; unsigned char * pCurOld = pCur; pNew->vUserPiIds = Vec_IntStartFull( nInputs ); @@ -505,6 +601,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi } Vec_IntFree( vPoNames ); } + } } @@ -636,6 +733,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi pCur++; if ( (*pCur >= 'a' && *pCur <= 'z') || (*pCur >= 'A' && *pCur <= 'Z') || (*pCur >= '0' && *pCur <= '9') ) { + ABC_FREE( pNew->pName ); pNew->pName = Abc_UtilStrsav( (char *)pCur ); pCur += strlen(pNew->pName) + 1; } else @@ -866,6 +964,39 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi Abc_Print( 0, "Structural hashing enabled while reading AIGER invalidated the mapping. Consider using \"&r -s\".\n" ); Vec_IntFreeP( &pNew->vMapping ); } + if ( vNamesIn && Gia_ManPiNum(pNew) != Vec_PtrSize(vNamesIn) ) + Abc_Print( 0, "The number of inputs does not match the number of input names.\n" ); + else if ( vNamesOut && Gia_ManPoNum(pNew) != Vec_PtrSize(vNamesOut) ) + Abc_Print( 0, "The number of output does not match the number of output names.\n" ); + else if ( vNamesRegOut && Gia_ManRegNum(pNew) != Vec_PtrSize(vNamesRegOut) ) + Abc_Print( 0, "The number of inputs does not match the number of flop names.\n" ); + else if ( vNamesIn && vNamesOut ) + { + pNew->vNamesIn = vNamesIn; vNamesIn = NULL; + pNew->vNamesOut = vNamesOut; vNamesOut = NULL; + if ( vNamesRegOut ) + { + Vec_PtrAppend( pNew->vNamesIn, vNamesRegOut ); + Vec_PtrClear( vNamesRegOut ); + Vec_PtrFree( vNamesRegOut ); + vNamesRegOut = NULL; + } + if ( vNamesRegIn ) + { + Vec_PtrAppend( pNew->vNamesOut, vNamesRegIn ); + Vec_PtrClear( vNamesRegIn ); + Vec_PtrFree( vNamesRegIn ); + vNamesRegIn = NULL; + } + } + if ( vNamesNode && Gia_ManObjNum(pNew) != Vec_PtrSize(vNamesNode) ) + Abc_Print( 0, "The size of the node name array does not match the number of objects. Names are not entered.\n" ); + else if ( vNamesNode ) + pNew->vNamesNode = vNamesNode, vNamesNode = NULL; + if ( vNamesIn ) Vec_PtrFreeFree( vNamesIn ); + if ( vNamesOut ) Vec_PtrFreeFree( vNamesOut ); + if ( vNamesRegIn ) Vec_PtrFreeFree( vNamesRegIn ); + if ( vNamesRegOut ) Vec_PtrFreeFree( vNamesRegOut ); return pNew; } @@ -1197,6 +1328,14 @@ void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int Gia_ManForEachPo( p, pObj, i ) fprintf( pFile, "o%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesOut, i) ); } + if ( p->vNamesNode && Vec_PtrSize(p->vNamesNode) != Gia_ManObjNum(p) ) + Abc_Print( 0, "The size of the node name array does not match the number of objects. Names are not written.\n" ); + else if ( p->vNamesNode ) + { + Gia_ManForEachAnd( p, pObj, i ) + if ( Vec_PtrEntry(p->vNamesNode, i) ) + fprintf( pFile, "n%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesNode, i) ); + } // write the comment if ( fWriteNewLine ) @@ -1477,6 +1616,148 @@ void Gia_AigerWriteSimple( Gia_Man_t * pInit, char * pFileName ) fclose( pFile ); } + + +/**Function************************************************************* + + Synopsis [Simple AIGER reader/writer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Aiger_ReadUnsigned( FILE * pFile ) +{ + unsigned x = 0, i = 0; + unsigned char ch; + while ((ch = fgetc(pFile)) & 0x80) + x |= (ch & 0x7f) << (7 * i++); + return x | (ch << (7 * i)); +} +static inline void Aiger_WriteUnsigned( FILE * pFile, unsigned x ) +{ + unsigned char ch; + while (x & ~0x7f) + { + ch = (x & 0x7f) | 0x80; + fputc( ch, pFile ); + x >>= 7; + } + ch = x; + fputc( ch, pFile ); +} +int * Aiger_Read( char * pFileName, int * pnObjs, int * pnIns, int * pnLats, int * pnOuts, int * pnAnds ) +{ + int i, Temp, Value = 0, nTotal, nObjs, nIns, nLats, nOuts, nAnds, * pObjs; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Aiger_Read(): Cannot open the output file \"%s\".\n", pFileName ); + return NULL; + } + if ( fgetc(pFile) != 'a' || fgetc(pFile) != 'i' || fgetc(pFile) != 'g' ) + { + fprintf( stdout, "Aiger_Read(): Can only read binary AIGER.\n" ); + fclose( pFile ); + return NULL; + } + if ( fscanf(pFile, "%d %d %d %d %d", &nTotal, &nIns, &nLats, &nOuts, &nAnds) != 5 ) + { + fprintf( stdout, "Aiger_Read(): Cannot read the header line.\n" ); + fclose( pFile ); + return NULL; + } + if ( nTotal != nIns + nLats + nAnds ) + { + fprintf( stdout, "The number of objects does not match.\n" ); + fclose( pFile ); + return NULL; + } + nObjs = 1 + nIns + 2*nLats + nOuts + nAnds; + pObjs = ABC_CALLOC( int, nObjs * 2 ); + // read flop input literals + for ( i = 0; i < nLats; i++ ) + { + while ( fgetc(pFile) != '\n' ); + Value += fscanf( pFile, "%d", &Temp ); + pObjs[2*(nObjs-nLats+i)+0] = Temp; + pObjs[2*(nObjs-nLats+i)+1] = Temp; + } + // read output literals + for ( i = 0; i < nOuts; i++ ) + { + while ( fgetc(pFile) != '\n' ); + Value += fscanf( pFile, "%d", &Temp ); + pObjs[2*(nObjs-nOuts-nLats+i)+0] = Temp; + pObjs[2*(nObjs-nOuts-nLats+i)+1] = Temp; + } + assert( Value == nLats + nOuts ); + // read the binary part + while ( fgetc(pFile) != '\n' ); + for ( i = 0; i < nAnds; i++ ) + { + int uLit = 2*(1 + nIns + nLats + i); + int uLit1 = uLit - Aiger_ReadUnsigned( pFile ); + int uLit0 = uLit1 - Aiger_ReadUnsigned( pFile ); + pObjs[2*(1+nIns+nLats+i)+0] = uLit0; + pObjs[2*(1+nIns+nLats+i)+1] = uLit1; + } + fclose( pFile ); + if ( pnObjs ) *pnObjs = nObjs; + if ( pnIns ) *pnIns = nIns; + if ( pnLats ) *pnLats = nLats; + if ( pnOuts ) *pnOuts = nOuts; + if ( pnAnds ) *pnAnds = nAnds; + return pObjs; +} +void Aiger_Write( char * pFileName, int * pObjs, int nObjs, int nIns, int nLats, int nOuts, int nAnds ) +{ + FILE * pFile = fopen( pFileName, "wb" ); int i; + if ( pFile == NULL ) + { + fprintf( stdout, "Aiger_Write(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + fprintf( pFile, "aig %d %d %d %d %d\n", nIns + nLats + nAnds, nIns, nLats, nOuts, nAnds ); + for ( i = 0; i < nLats; i++ ) + fprintf( pFile, "%d\n", pObjs[2*(nObjs-nLats+i)+0] ); + for ( i = 0; i < nOuts; i++ ) + fprintf( pFile, "%d\n", pObjs[2*(nObjs-nOuts-nLats+i)+0] ); + for ( i = 0; i < nAnds; i++ ) + { + int uLit = 2*(1 + nIns + nLats + i); + int uLit0 = pObjs[2*(1+nIns+nLats+i)+0]; + int uLit1 = pObjs[2*(1+nIns+nLats+i)+1]; + Aiger_WriteUnsigned( pFile, uLit - uLit1 ); + Aiger_WriteUnsigned( pFile, uLit1 - uLit0 ); + } + fprintf( pFile, "c\n" ); + fclose( pFile ); +} +void Aiger_Test( char * pFileNameIn, char * pFileNameOut ) +{ + int nObjs, nIns, nLats, nOuts, nAnds, * pObjs = Aiger_Read( pFileNameIn, &nObjs, &nIns, &nLats, &nOuts, &nAnds ); + if ( pObjs == NULL ) + return; + printf( "Read input file \"%s\".\n", pFileNameIn ); + Aiger_Write( pFileNameOut, pObjs, nObjs, nIns, nLats, nOuts, nAnds ); + printf( "Written output file \"%s\".\n", pFileNameOut ); + ABC_FREE( pObjs ); +} + +/* +int main( int argc, char ** argv ) +{ + if ( argc != 3 ) + return 0; + Aiger_Test( argv[1], argv[2] ); + return 1; +} +*/ + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaCSat.c b/src/aig/gia/giaCSat.c index 503961d4..67b62655 100644 --- a/src/aig/gia/giaCSat.c +++ b/src/aig/gia/giaCSat.c @@ -1034,7 +1034,7 @@ void Cbs_ManSatPrintStats( Cbs_Man_t * p ) SeeAlso [] ***********************************************************************/ -Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ) +Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int f0Proved, int fVerbose ) { extern void Gia_ManCollectTest( Gia_Man_t * pAig ); extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ); @@ -1105,6 +1105,8 @@ Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvSt } if ( status == 1 ) { + if ( f0Proved ) + Gia_ManPatchCoDriver( pAig, i, 0 ); p->nSatUnsat++; p->nConfUnsat += p->Pars.nBTThis; p->timeSatUnsat += Abc_Clock() - clk; diff --git a/src/aig/gia/giaCSat3.c b/src/aig/gia/giaCSat3.c new file mode 100644 index 00000000..c34c84ca --- /dev/null +++ b/src/aig/gia/giaCSat3.c @@ -0,0 +1,1365 @@ +/**CFile**************************************************************** + + FileName [giaCSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [A simple circuit-based solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaCSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Cbs3_Par_t_ Cbs3_Par_t; +struct Cbs3_Par_t_ +{ + // conflict limits + int nBTLimit; // limit on the number of conflicts + int nJustLimit; // limit on the size of justification queue + int nRestLimit; // limit on the number of restarts + // current parameters + int nBTThis; // number of conflicts + int nJustThis; // max size of the frontier + int nBTTotal; // total number of conflicts + int nJustTotal; // total size of the frontier + // other + int fVerbose; +}; + +typedef struct Cbs3_Que_t_ Cbs3_Que_t; +struct Cbs3_Que_t_ +{ + int iHead; // beginning of the queue + int iTail; // end of the queue + int nSize; // allocated size + int * pData; // nodes stored in the queue +}; + +typedef struct Cbs3_Man_t_ Cbs3_Man_t; +struct Cbs3_Man_t_ +{ + Cbs3_Par_t Pars; // parameters + Gia_Man_t * pAig; // AIG manager + Cbs3_Que_t pProp; // propagation queue + Cbs3_Que_t pJust; // justification queue + Cbs3_Que_t pClauses; // clause queue + Vec_Int_t * vModel; // satisfying assignment + Vec_Int_t * vTemp; // temporary storage + // circuit structure + int nVars; + int nVarsAlloc; + int var_inc; + Vec_Int_t vMap; + Vec_Int_t vRef; + Vec_Int_t vFans; + Vec_Wec_t vImps; + // internal data + Vec_Str_t vAssign; + Vec_Str_t vMark; + Vec_Int_t vLevReason; + Vec_Int_t vActs; + Vec_Int_t vWatches; + Vec_Int_t vWatchUpds; + // SAT calls statistics + int nSatUnsat; // the number of proofs + int nSatSat; // the number of failure + int nSatUndec; // the number of timeouts + int nSatTotal; // the number of calls + // conflicts + int nConfUnsat; // conflicts in unsat problems + int nConfSat; // conflicts in sat problems + int nConfUndec; // conflicts in undec problems + // runtime stats + abctime timeJFront; + abctime timeSatLoad; // SAT solver loading time + abctime timeSatUnsat; // unsat + abctime timeSatSat; // sat + abctime timeSatUndec; // undecided + abctime timeTotal; // total runtime + // other statistics + int nPropCalls[3]; + int nFails[2]; + int nClauseConf; + int nDecs; +}; + +static inline int Cbs3_VarUnused( Cbs3_Man_t * p, int iVar ) { return Vec_IntEntry(&p->vLevReason, 3*iVar) == -1; } +static inline void Cbs3_VarSetUnused( Cbs3_Man_t * p, int iVar ) { Vec_IntWriteEntry(&p->vLevReason, 3*iVar, -1); } + +static inline int Cbs3_VarMark0( Cbs3_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vMark, iVar); } +static inline void Cbs3_VarSetMark0( Cbs3_Man_t * p, int iVar, int Value ) { Vec_StrWriteEntry(&p->vMark, iVar, (char)Value); } + +static inline int Cbs3_VarIsAssigned( Cbs3_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vAssign, iVar) < 2; } +static inline void Cbs3_VarUnassign( Cbs3_Man_t * p, int iVar ) { assert( Cbs3_VarIsAssigned(p, iVar)); Vec_StrWriteEntry(&p->vAssign, iVar, (char)(2+Vec_StrEntry(&p->vAssign, iVar))); Cbs3_VarSetUnused(p, iVar); } + +static inline int Cbs3_VarValue( Cbs3_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vAssign, iVar); } +static inline void Cbs3_VarSetValue( Cbs3_Man_t * p, int iVar, int v ) { assert( !Cbs3_VarIsAssigned(p, iVar)); Vec_StrWriteEntry(&p->vAssign, iVar, (char)v); } + +static inline int Cbs3_VarLit0( Cbs3_Man_t * p, int iVar ) { return Vec_IntEntry( &p->vFans, Abc_Var2Lit(iVar, 0) ); } +static inline int Cbs3_VarLit1( Cbs3_Man_t * p, int iVar ) { return Vec_IntEntry( &p->vFans, Abc_Var2Lit(iVar, 1) ); } +static inline int Cbs3_VarIsPi( Cbs3_Man_t * p, int iVar ) { return Vec_IntEntry( &p->vFans, Abc_Var2Lit(iVar, 0) ) == 0; } +static inline int Cbs3_VarIsJust( Cbs3_Man_t * p, int iVar ) { int * pLits = Vec_IntEntryP(&p->vFans, Abc_Var2Lit(iVar, 0)); return pLits[0] > 0 && Cbs3_VarValue(p, Abc_Lit2Var(pLits[0])) >= 2 && Cbs3_VarValue(p, Abc_Lit2Var(pLits[1])) >= 2; } + +static inline int Cbs3_VarDecLevel( Cbs3_Man_t * p, int iVar ) { assert( !Cbs3_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar); } +static inline int Cbs3_VarReason0( Cbs3_Man_t * p, int iVar ) { assert( !Cbs3_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar+1); } +static inline int Cbs3_VarReason1( Cbs3_Man_t * p, int iVar ) { assert( !Cbs3_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar+2); } +static inline int * Cbs3_VarReasonP( Cbs3_Man_t * p, int iVar ) { assert( !Cbs3_VarUnused(p, iVar) ); return Vec_IntEntryP(&p->vLevReason, 3*iVar+1); } +static inline int Cbs3_ClauseDecLevel( Cbs3_Man_t * p, int hClause ) { return Cbs3_VarDecLevel( p, p->pClauses.pData[hClause] ); } + +static inline int Cbs3_ClauseSize( Cbs3_Man_t * p, int hClause ) { return p->pClauses.pData[hClause]; } +static inline int * Cbs3_ClauseLits( Cbs3_Man_t * p, int hClause ) { return p->pClauses.pData+hClause+1; } +static inline int Cbs3_ClauseLit( Cbs3_Man_t * p, int hClause, int i ) { return p->pClauses.pData[hClause+1+i]; } +static inline int * Cbs3_ClauseNext1p( Cbs3_Man_t * p, int hClause ) { return p->pClauses.pData+hClause+Cbs3_ClauseSize(p, hClause)+2; } + +static inline void Cbs3_ClauseSetSize( Cbs3_Man_t * p, int hClause, int x ) { p->pClauses.pData[hClause] = x; } +static inline void Cbs3_ClauseSetLit( Cbs3_Man_t * p, int hClause, int i, int x ) { p->pClauses.pData[hClause+i+1] = x; } +static inline void Cbs3_ClauseSetNext( Cbs3_Man_t * p, int hClause, int n, int x ){ p->pClauses.pData[hClause+Cbs3_ClauseSize(p, hClause)+1+n] = x; } + + +#define Cbs3_QueForEachEntry( Que, iObj, i ) \ + for ( i = (Que).iHead; (i < (Que).iTail) && ((iObj) = (Que).pData[i]); i++ ) + +#define Cbs3_ClauseForEachEntry( p, hClause, iObj, i ) \ + for ( i = 1; i <= Cbs3_ClauseSize(p, hClause) && (iObj = (p)->pClauses.pData[hClause+i]); i++ ) +#define Cbs3_ClauseForEachEntry1( p, hClause, iObj, i ) \ + for ( i = 2; i <= Cbs3_ClauseSize(p, hClause) && (iObj = (p)->pClauses.pData[hClause+i]); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sets default values of the parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs3_SetDefaultParams( Cbs3_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Cbs3_Par_t) ); + pPars->nBTLimit = 1000; // limit on the number of conflicts + pPars->nJustLimit = 500; // limit on the size of justification queue + pPars->nRestLimit = 10; // limit on the number of restarts + pPars->fVerbose = 1; // print detailed statistics +} +void Cbs3_ManSetConflictNum( Cbs3_Man_t * p, int Num ) +{ + p->Pars.nBTLimit = Num; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cbs3_Man_t * Cbs3_ManAlloc( Gia_Man_t * pGia ) +{ + Cbs3_Man_t * p; + p = ABC_CALLOC( Cbs3_Man_t, 1 ); + p->pProp.nSize = p->pJust.nSize = p->pClauses.nSize = 10000; + p->pProp.pData = ABC_ALLOC( int, p->pProp.nSize ); + p->pJust.pData = ABC_ALLOC( int, p->pJust.nSize ); + p->pClauses.pData = ABC_ALLOC( int, p->pClauses.nSize ); + p->pClauses.iHead = p->pClauses.iTail = 1; + p->vModel = Vec_IntAlloc( 1000 ); + p->vTemp = Vec_IntAlloc( 1000 ); + p->pAig = pGia; + Cbs3_SetDefaultParams( &p->Pars ); + // circuit structure + Vec_IntPush( &p->vMap, -1 ); + Vec_IntPush( &p->vRef, -1 ); + Vec_IntPushTwo( &p->vFans, -1, -1 ); + Vec_WecPushLevel( &p->vImps ); + Vec_WecPushLevel( &p->vImps ); + p->nVars = 1; + // internal data + p->nVarsAlloc = 1000; + Vec_StrFill( &p->vAssign, p->nVarsAlloc, 2 ); + Vec_StrFill( &p->vMark, p->nVarsAlloc, 0 ); + Vec_IntFill( &p->vLevReason, 3*p->nVarsAlloc, -1 ); + Vec_IntFill( &p->vActs, p->nVarsAlloc, 0 ); + Vec_IntFill( &p->vWatches, 2*p->nVarsAlloc, 0 ); + Vec_IntGrow( &p->vWatchUpds, 1000 ); + return p; +} +static inline void Cbs3_ManReset( Cbs3_Man_t * p ) +{ + assert( p->nVars == Vec_IntSize(&p->vMap) ); + Vec_IntShrink( &p->vMap, 1 ); + Vec_IntShrink( &p->vRef, 1 ); + Vec_IntShrink( &p->vFans, 2 ); + Vec_WecShrink( &p->vImps, 2 ); + p->nVars = 1; +} +static inline void Cbs3_ManGrow( Cbs3_Man_t * p ) +{ + if ( p->nVarsAlloc < p->nVars ) + { + p->nVarsAlloc = 2*p->nVars; + Vec_StrFill( &p->vAssign, p->nVarsAlloc, 2 ); + Vec_StrFill( &p->vMark, p->nVarsAlloc, 0 ); + Vec_IntFill( &p->vLevReason, 3*p->nVarsAlloc, -1 ); + Vec_IntFill( &p->vActs, p->nVarsAlloc, 0 ); + Vec_IntFill( &p->vWatches, 2*p->nVarsAlloc, 0 ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs3_ManStop( Cbs3_Man_t * p ) +{ + // circuit structure + Vec_IntErase( &p->vMap ); + Vec_IntErase( &p->vRef ); + Vec_IntErase( &p->vFans ); + Vec_WecErase( &p->vImps ); + // internal data + Vec_StrErase( &p->vAssign ); + Vec_StrErase( &p->vMark ); + Vec_IntErase( &p->vLevReason ); + Vec_IntErase( &p->vActs ); + Vec_IntErase( &p->vWatches ); + Vec_IntErase( &p->vWatchUpds ); + Vec_IntFree( p->vModel ); + Vec_IntFree( p->vTemp ); + ABC_FREE( p->pClauses.pData ); + ABC_FREE( p->pProp.pData ); + ABC_FREE( p->pJust.pData ); + ABC_FREE( p ); +} +int Cbs3_ManMemory( Cbs3_Man_t * p ) +{ + int nMem = sizeof(Cbs3_Man_t); + nMem += (int)Vec_IntMemory( &p->vMap ); + nMem += (int)Vec_IntMemory( &p->vRef ); + nMem += (int)Vec_IntMemory( &p->vFans ); + nMem += (int)Vec_WecMemory( &p->vImps ); + nMem += (int)Vec_StrMemory( &p->vAssign ); + nMem += (int)Vec_StrMemory( &p->vMark ); + nMem += (int)Vec_IntMemory( &p->vActs ); + nMem += (int)Vec_IntMemory( &p->vWatches ); + nMem += (int)Vec_IntMemory( &p->vWatchUpds ); + nMem += (int)Vec_IntMemory( p->vModel ); + nMem += (int)Vec_IntMemory( p->vTemp ); + nMem += 4*p->pClauses.nSize; + nMem += 4*p->pProp.nSize; + nMem += 4*p->pJust.nSize; + return nMem; +} + +/**Function************************************************************* + + Synopsis [Returns satisfying assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cbs3_ReadModel( Cbs3_Man_t * p ) +{ + return p->vModel; +} + + +/**Function************************************************************* + + Synopsis [Activity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +//#define USE_ACTIVITY + +#ifdef USE_ACTIVITY +static inline void Cbs3_ActReset( Cbs3_Man_t * p ) +{ + int i, * pAct = Vec_IntArray(&p->vActs); + for ( i = 0; i < p->nVars; i++ ) + pAct[i] = (1 << 10); + p->var_inc = (1 << 5); +} +static inline void Cbs3_ActRescale( Cbs3_Man_t * p ) +{ + int i, * pAct = Vec_IntArray(&p->vActs); + for ( i = 0; i < p->nVars; i++ ) + pAct[i] >>= 19; + p->var_inc >>= 19; + p->var_inc = Abc_MaxInt( (unsigned)p->var_inc, (1<<5) ); +} +static inline void Cbs3_ActBumpVar( Cbs3_Man_t * p, int iVar ) +{ + int * pAct = Vec_IntArray(&p->vActs); + pAct[iVar] += p->var_inc; + if ((unsigned)pAct[iVar] & 0x80000000) + Cbs3_ActRescale(p); +} +static inline void Cbs3_ActDecay( Cbs3_Man_t * p ) +{ + p->var_inc += (p->var_inc >> 4); +} +#else +static inline void Cbs3_ActReset( Cbs3_Man_t * p ) {} +static inline void Cbs3_ActRescale( Cbs3_Man_t * p ) {} +static inline void Cbs3_ActBumpVar( Cbs3_Man_t * p, int iVar ) {} +static inline void Cbs3_ActDecay( Cbs3_Man_t * p ) {} +#endif + + +/**Function************************************************************* + + Synopsis [Returns 1 if the solver is out of limits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManCheckLimits( Cbs3_Man_t * p ) +{ + p->nFails[0] += p->Pars.nJustThis > p->Pars.nJustLimit; + p->nFails[1] += p->Pars.nBTThis > p->Pars.nBTLimit; + return p->Pars.nJustThis > p->Pars.nJustLimit || p->Pars.nBTThis > p->Pars.nBTLimit; +} + +/**Function************************************************************* + + Synopsis [Saves the satisfying assignment as an array of literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_ManSaveModel( Cbs3_Man_t * p, Vec_Int_t * vCex ) +{ + int i, iLit; + Vec_IntClear( vCex ); + p->pProp.iHead = 0; + Cbs3_QueForEachEntry( p->pProp, iLit, i ) + if ( Cbs3_VarIsPi(p, Abc_Lit2Var(iLit)) ) + Vec_IntPush( vCex, Abc_Lit2LitV(Vec_IntArray(&p->vMap), iLit)-2 ); +} +static inline void Cbs3_ManSaveModelAll( Cbs3_Man_t * p, Vec_Int_t * vCex ) +{ + int i, iLit; + Vec_IntClear( vCex ); + p->pProp.iHead = 0; + Cbs3_QueForEachEntry( p->pProp, iLit, i ) + { + int iVar = Abc_Lit2Var(iLit); + Vec_IntPush( vCex, Abc_Var2Lit(iVar, !Cbs3_VarValue(p, iVar)) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_QueIsEmpty( Cbs3_Que_t * p ) +{ + return p->iHead == p->iTail; +} +static inline int Cbs3_QueSize( Cbs3_Que_t * p ) +{ + return p->iTail - p->iHead; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_QuePush( Cbs3_Que_t * p, int iObj ) +{ + if ( p->iTail == p->nSize ) + { + p->nSize *= 2; + p->pData = ABC_REALLOC( int, p->pData, p->nSize ); + } + p->pData[p->iTail++] = iObj; +} +static inline void Cbs3_QueGrow( Cbs3_Que_t * p, int Plus ) +{ + if ( p->iTail + Plus > p->nSize ) + { + p->nSize *= 2; + p->pData = ABC_REALLOC( int, p->pData, p->nSize ); + } + assert( p->iTail + Plus <= p->nSize ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the object in the queue.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_QueHasNode( Cbs3_Que_t * p, int iObj ) +{ + int i, iTemp; + Cbs3_QueForEachEntry( *p, iTemp, i ) + if ( iTemp == iObj ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_QueStore( Cbs3_Que_t * p, int * piHeadOld, int * piTailOld ) +{ + int i; + *piHeadOld = p->iHead; + *piTailOld = p->iTail; + for ( i = *piHeadOld; i < *piTailOld; i++ ) + Cbs3_QuePush( p, p->pData[i] ); + p->iHead = *piTailOld; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_QueRestore( Cbs3_Que_t * p, int iHeadOld, int iTailOld ) +{ + p->iHead = iHeadOld; + p->iTail = iTailOld; +} + +/**Function************************************************************* + + Synopsis [Find variable with the highest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManDecide( Cbs3_Man_t * p ) +{ + int i, iObj, iObjMax = 0; +#ifdef USE_ACTIVITY + Cbs3_QueForEachEntry( p->pJust, iObj, i ) + if ( iObjMax == 0 || + Vec_IntEntry(&p->vActs, iObjMax) < Vec_IntEntry(&p->vActs, iObj) || + (Vec_IntEntry(&p->vActs, iObjMax) == Vec_IntEntry(&p->vActs, iObj) && Vec_IntEntry(&p->vMap, iObjMax) < Vec_IntEntry(&p->vMap, iObj)) ) + iObjMax = iObj; +#else + Cbs3_QueForEachEntry( p->pJust, iObj, i ) +// if ( iObjMax == 0 || iObjMax < iObj ) + if ( iObjMax == 0 || Vec_IntEntry(&p->vMap, iObjMax) < Vec_IntEntry(&p->vMap, iObj) ) + iObjMax = iObj; +#endif + return iObjMax; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_ManCancelUntil( Cbs3_Man_t * p, int iBound ) +{ + int i, iLit; + assert( iBound <= p->pProp.iTail ); + p->pProp.iHead = iBound; + Cbs3_QueForEachEntry( p->pProp, iLit, i ) + Cbs3_VarUnassign( p, Abc_Lit2Var(iLit) ); + p->pProp.iTail = iBound; +} + +/**Function************************************************************* + + Synopsis [Assigns the variables a value.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_ManAssign( Cbs3_Man_t * p, int iLit, int Level, int iRes0, int iRes1 ) +{ + int iObj = Abc_Lit2Var(iLit); + assert( Cbs3_VarUnused(p, iObj) ); + assert( !Cbs3_VarIsAssigned(p, iObj) ); + Cbs3_VarSetValue( p, iObj, !Abc_LitIsCompl(iLit) ); + Cbs3_QuePush( &p->pProp, iLit ); + Vec_IntWriteEntry( &p->vLevReason, 3*iObj, Level ); + Vec_IntWriteEntry( &p->vLevReason, 3*iObj+1, iRes0 ); + Vec_IntWriteEntry( &p->vLevReason, 3*iObj+2, iRes1 ); +} + + + + +/**Function************************************************************* + + Synopsis [Prints conflict clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_ManPrintClause( Cbs3_Man_t * p, int Level, int hClause ) +{ + int i, iLit; + assert( Cbs3_QueIsEmpty( &p->pClauses ) ); + printf( "Level %2d : ", Level ); + Cbs3_ClauseForEachEntry( p, hClause, iLit, i ) + printf( "%c%d ", Abc_LitIsCompl(iLit) ? '-':'+', Abc_Lit2Var(iLit) ); +// printf( "%d=%d(%d) ", iObj, Cbs3_VarValue(p, Abc_Lit2Var(iLit)), Cbs3_VarDecLevel(p, Abc_Lit2Var(iLit)) ); + printf( "\n" ); +} +static inline void Cbs3_ManPrintCube( Cbs3_Man_t * p, int Level, int hClause ) +{ + int i, iObj; + assert( Cbs3_QueIsEmpty( &p->pClauses ) ); + printf( "Level %2d : ", Level ); + Cbs3_ClauseForEachEntry( p, hClause, iObj, i ) + printf( "%c%d ", Cbs3_VarValue(p, iObj)? '+':'-', iObj ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Finalized the clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_ManCleanWatch( Cbs3_Man_t * p ) +{ + int i, iLit; + Vec_IntForEachEntry( &p->vWatchUpds, iLit, i ) + Vec_IntWriteEntry( &p->vWatches, iLit, 0 ); + Vec_IntClear( &p->vWatchUpds ); + //Vec_IntForEachEntry( &p->vWatches, iLit, i ) + // assert( iLit == 0 ); +} +static inline void Cbs3_ManWatchClause( Cbs3_Man_t * p, int hClause, int Lit ) +{ + int * pLits = Cbs3_ClauseLits( p, hClause ); + int * pPlace = Vec_IntEntryP( &p->vWatches, Abc_LitNot(Lit) ); + if ( *pPlace == 0 ) + Vec_IntPush( &p->vWatchUpds, Abc_LitNot(Lit) ); +/* + if ( pClause->pLits[0] == Lit ) + pClause->pNext0 = p->pWatches[lit_neg(Lit)]; + else + { + assert( pClause->pLits[1] == Lit ); + pClause->pNext1 = p->pWatches[lit_neg(Lit)]; + } + p->pWatches[lit_neg(Lit)] = pClause; +*/ + assert( Lit == pLits[0] || Lit == pLits[1] ); + Cbs3_ClauseSetNext( p, hClause, Lit == pLits[1], *pPlace ); + *pPlace = hClause; +} +static inline int Cbs3_QueFinish( Cbs3_Man_t * p, int Level ) +{ + Cbs3_Que_t * pQue = &(p->pClauses); + int i, iObj, hClauseC, hClause = pQue->iHead, Size = pQue->iTail - pQue->iHead - 1; + assert( pQue->iHead+1 < pQue->iTail ); + Cbs3_ClauseSetSize( p, pQue->iHead, Size ); + hClauseC = pQue->iHead = pQue->iTail; + //printf( "Adding cube: " ); Cbs3_ManPrintCube(p, Level, hClause); + if ( Size == 1 ) + return hClause; + // create watched clause + pQue->iHead = hClause; + Cbs3_QueForEachEntry( p->pClauses, iObj, i ) + { + if ( i == hClauseC ) + break; + else if ( i == hClause ) // nlits + Cbs3_QuePush( pQue, iObj ); + else // literals + Cbs3_QuePush( pQue, Abc_Var2Lit(iObj, Cbs3_VarValue(p, iObj)) ); // complement + } + Cbs3_QuePush( pQue, 0 ); // next0 + Cbs3_QuePush( pQue, 0 ); // next1 + pQue->iHead = pQue->iTail; + Cbs3_ManWatchClause( p, hClauseC, Cbs3_ClauseLit(p, hClauseC, 0) ); + Cbs3_ManWatchClause( p, hClauseC, Cbs3_ClauseLit(p, hClauseC, 1) ); + //printf( "Adding clause %d: ", hClauseC ); Cbs3_ManPrintClause(p, Level, hClauseC); + Cbs3_ActDecay( p ); + return hClause; +} + +/**Function************************************************************* + + Synopsis [Returns conflict clause.] + + Description [Performs conflict analysis.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManDeriveReason( Cbs3_Man_t * p, int Level ) +{ + Cbs3_Que_t * pQue = &(p->pClauses); + int i, k, iObj, iLitLevel, * pReason; + assert( pQue->pData[pQue->iHead] == 0 ); + assert( pQue->pData[pQue->iHead+1] == 0 ); + assert( pQue->iHead + 2 < pQue->iTail ); + //for ( i = pQue->iHead + 2; i < pQue->iTail; i++ ) + // assert( !Cbs3_VarMark0(p, pQue->pData[i]) ); + // compact literals + Vec_IntClear( p->vTemp ); + for ( i = k = pQue->iHead + 2; i < pQue->iTail; i++ ) + { + iObj = pQue->pData[i]; + if ( Cbs3_VarMark0(p, iObj) ) // unassigned - seen again + continue; + //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 ) + // Vec_IntPush( &p->vActStore, iObj ); + //Vec_IntAddToEntry( &p->vActivity, iObj, 1 ); + // assigned - seen first time + Cbs3_VarSetMark0(p, iObj, 1); + Cbs3_ActBumpVar(p, iObj); + Vec_IntPush( p->vTemp, iObj ); + // check decision level + iLitLevel = Cbs3_VarDecLevel( p, iObj ); + if ( iLitLevel < Level ) + { + pQue->pData[k++] = iObj; + continue; + } + assert( iLitLevel == Level ); + pReason = Cbs3_VarReasonP( p, iObj ); + if ( pReason[0] == 0 && pReason[1] == 0 ) // no reason + { + assert( pQue->pData[pQue->iHead+1] == 0 ); + pQue->pData[pQue->iHead+1] = iObj; + } + else if ( pReason[0] != 0 ) // circuit reason + { + Cbs3_QuePush( pQue, pReason[0] ); + if ( pReason[1] ) + Cbs3_QuePush( pQue, pReason[1] ); + } + else // clause reason + { + int i, * pLits, nLits = Cbs3_ClauseSize( p, pReason[1] ); + assert( pReason[1] ); + Cbs3_QueGrow( pQue, nLits ); + pLits = Cbs3_ClauseLits( p, pReason[1] ); + assert( iObj == Abc_Lit2Var(pLits[0]) ); + for ( i = 1; i < nLits; i++ ) + Cbs3_QuePush( pQue, Abc_Lit2Var(pLits[i]) ); + } + } + assert( pQue->pData[pQue->iHead] == 0 ); + assert( pQue->pData[pQue->iHead+1] != 0 ); + pQue->iTail = k; + // clear the marks + Vec_IntForEachEntry( p->vTemp, iObj, i ) + Cbs3_VarSetMark0(p, iObj, 0); + return Cbs3_QueFinish( p, Level ); +} +static inline int Cbs3_ManAnalyze( Cbs3_Man_t * p, int Level, int iVar, int iFan0, int iFan1 ) +{ + Cbs3_Que_t * pQue = &(p->pClauses); + assert( Cbs3_VarIsAssigned(p, iVar) ); + assert( Cbs3_QueIsEmpty( pQue ) ); + Cbs3_QuePush( pQue, 0 ); + Cbs3_QuePush( pQue, 0 ); + if ( iFan0 ) // circuit conflict + { + assert( Cbs3_VarIsAssigned(p, iFan0) ); + assert( iFan1 == 0 || Cbs3_VarIsAssigned(p, iFan1) ); + Cbs3_QuePush( pQue, iVar ); + Cbs3_QuePush( pQue, iFan0 ); + if ( iFan1 ) + Cbs3_QuePush( pQue, iFan1 ); + } + else // clause conflict + { + int i, * pLits, nLits = Cbs3_ClauseSize( p, iFan1 ); + assert( iFan1 ); + Cbs3_QueGrow( pQue, nLits ); + pLits = Cbs3_ClauseLits( p, iFan1 ); + assert( iVar == Abc_Lit2Var(pLits[0]) ); + assert( Cbs3_VarValue(p, iVar) == Abc_LitIsCompl(pLits[0]) ); + for ( i = 0; i < nLits; i++ ) + Cbs3_QuePush( pQue, Abc_Lit2Var(pLits[i]) ); + } + return Cbs3_ManDeriveReason( p, Level ); +} + + +/**Function************************************************************* + + Synopsis [Propagate one assignment.] + + Description [Returns handle of the conflict clause, if conflict occurs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManPropagateClauses( Cbs3_Man_t * p, int Level, int Lit ) +{ + int i, Value, Cur, LitF = Abc_LitNot(Lit); + int * pPrev = Vec_IntEntryP( &p->vWatches, Lit ); + //for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev ) + for ( Cur = *pPrev; Cur; Cur = *pPrev ) + { + int nLits = Cbs3_ClauseSize( p, Cur ); + int * pLits = Cbs3_ClauseLits( p, Cur ); + p->nPropCalls[1]++; +//printf( " Watching literal %c%d on level %d.\n", Abc_LitIsCompl(Lit) ? '-':'+', Abc_Lit2Var(Lit), Level ); + // make sure the false literal is in the second literal of the clause + //if ( pCur->pLits[0] == LitF ) + if ( pLits[0] == LitF ) + { + //pCur->pLits[0] = pCur->pLits[1]; + pLits[0] = pLits[1]; + //pCur->pLits[1] = LitF; + pLits[1] = LitF; + //pTemp = pCur->pNext0; + //pCur->pNext0 = pCur->pNext1; + //pCur->pNext1 = pTemp; + ABC_SWAP( int, pLits[nLits], pLits[nLits+1] ); + } + //assert( pCur->pLits[1] == LitF ); + assert( pLits[1] == LitF ); + + // if the first literal is true, the clause is satisfied + //if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] ) + if ( Cbs3_VarValue(p, Abc_Lit2Var(pLits[0])) == !Abc_LitIsCompl(pLits[0]) ) + { + //ppPrev = &pCur->pNext1; + pPrev = Cbs3_ClauseNext1p(p, Cur); + continue; + } + + // look for a new literal to watch + for ( i = 2; i < nLits; i++ ) + { + // skip the case when the literal is false + //if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] ) + if ( Cbs3_VarValue(p, Abc_Lit2Var(pLits[i])) == Abc_LitIsCompl(pLits[i]) ) + continue; + // the literal is either true or unassigned - watch it + //pCur->pLits[1] = pCur->pLits[i]; + //pCur->pLits[i] = LitF; + pLits[1] = pLits[i]; + pLits[i] = LitF; + // remove this clause from the watch list of Lit + //*ppPrev = pCur->pNext1; + *pPrev = *Cbs3_ClauseNext1p(p, Cur); + // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1]) + //Intb_ManWatchClause( p, pCur, pCur->pLits[1] ); + Cbs3_ManWatchClause( p, Cur, Cbs3_ClauseLit(p, Cur, 1) ); + break; + } + if ( i < nLits ) // found new watch + continue; + + // clause is unit - enqueue new implication + //if ( Inta_ManEnqueue(p, pCur->pLits[0], pCur) ) + //{ + // ppPrev = &pCur->pNext1; + // continue; + //} + + // clause is unit - enqueue new implication + Value = Cbs3_VarValue(p, Abc_Lit2Var(pLits[0])); + if ( Value >= 2 ) // unassigned + { + Cbs3_ManAssign( p, pLits[0], Level, 0, Cur ); + pPrev = Cbs3_ClauseNext1p(p, Cur); + continue; + } + + // conflict detected - return the conflict clause + //return pCur; + if ( Value == Abc_LitIsCompl(pLits[0]) ) + { + p->nClauseConf++; + return Cbs3_ManAnalyze( p, Level, Abc_Lit2Var(pLits[0]), 0, Cur ); + } + } + return 0; +} + + +/**Function************************************************************* + + Synopsis [Performs resolution of two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManResolve( Cbs3_Man_t * p, int Level, int hClause0, int hClause1 ) +{ + Cbs3_Que_t * pQue = &(p->pClauses); + int i, iObj, LevelMax = -1, LevelCur; + assert( pQue->pData[hClause0+1] != 0 ); + assert( pQue->pData[hClause0+1] == pQue->pData[hClause1+1] ); + //Cbs3_ClauseForEachEntry1( p, hClause0, iObj, i ) + // assert( !Cbs3_VarMark0(p, iObj) ); + //Cbs3_ClauseForEachEntry1( p, hClause1, iObj, i ) + // assert( !Cbs3_VarMark0(p, iObj) ); + assert( Cbs3_QueIsEmpty( pQue ) ); + Cbs3_QuePush( pQue, 0 ); + Cbs3_QuePush( pQue, 0 ); +// for ( i = hClause0 + 1; (iObj = pQue->pData[i]); i++ ) + Cbs3_ClauseForEachEntry1( p, hClause0, iObj, i ) + { + if ( Cbs3_VarMark0(p, iObj) ) // unassigned - seen again + continue; + //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 ) + // Vec_IntPush( &p->vActStore, iObj ); + //Vec_IntAddToEntry( &p->vActivity, iObj, 1 ); + // assigned - seen first time + Cbs3_VarSetMark0(p, iObj, 1); + Cbs3_ActBumpVar(p, iObj); + Cbs3_QuePush( pQue, iObj ); + LevelCur = Cbs3_VarDecLevel( p, iObj ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } +// for ( i = hClause1 + 1; (iObj = pQue->pData[i]); i++ ) + Cbs3_ClauseForEachEntry1( p, hClause1, iObj, i ) + { + if ( Cbs3_VarMark0(p, iObj) ) // unassigned - seen again + continue; + //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 ) + // Vec_IntPush( &p->vActStore, iObj ); + //Vec_IntAddToEntry( &p->vActivity, iObj, 1 ); + // assigned - seen first time + Cbs3_VarSetMark0(p, iObj, 1); + Cbs3_ActBumpVar(p, iObj); + Cbs3_QuePush( pQue, iObj ); + LevelCur = Cbs3_VarDecLevel( p, iObj ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } + for ( i = pQue->iHead + 2; i < pQue->iTail; i++ ) + Cbs3_VarSetMark0(p, pQue->pData[i], 0); + return Cbs3_ManDeriveReason( p, LevelMax ); +} + +/**Function************************************************************* + + Synopsis [Propagates a variable.] + + Description [Returns clause handle if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs3_ManUpdateJFrontier( Cbs3_Man_t * p ) +{ + //abctime clk = Abc_Clock(); + int iVar, iLit, i, k = p->pJust.iTail; + Cbs3_QueGrow( &p->pJust, Cbs3_QueSize(&p->pJust) + Cbs3_QueSize(&p->pProp) ); + Cbs3_QueForEachEntry( p->pJust, iVar, i ) + if ( Cbs3_VarIsJust(p, iVar) ) + p->pJust.pData[k++] = iVar; + Cbs3_QueForEachEntry( p->pProp, iLit, i ) + if ( Cbs3_VarIsJust(p, Abc_Lit2Var(iLit)) ) + p->pJust.pData[k++] = Abc_Lit2Var(iLit); + p->pJust.iHead = p->pJust.iTail; + p->pJust.iTail = k; + //p->timeJFront += Abc_Clock() - clk; +} +int Cbs3_ManPropagateNew( Cbs3_Man_t * p, int Level ) +{ + int i, k, iLit, hClause, nLits, * pLits; + p->nPropCalls[0]++; + Cbs3_QueForEachEntry( p->pProp, iLit, i ) + { + if ( (hClause = Cbs3_ManPropagateClauses(p, Level, iLit)) ) + return hClause; + p->nPropCalls[2]++; + nLits = Vec_IntSize(Vec_WecEntry(&p->vImps, iLit)); + pLits = Vec_IntArray(Vec_WecEntry(&p->vImps, iLit)); + for ( k = 0; k < nLits; k += 2 ) + { + int Value0 = Cbs3_VarValue(p, Abc_Lit2Var(pLits[k])); + int Value1 = pLits[k+1] ? Cbs3_VarValue(p, Abc_Lit2Var(pLits[k+1])) : -1; + if ( Value1 == -1 || Value1 == Abc_LitIsCompl(pLits[k+1]) ) // pLits[k+1] is false + { + if ( Value0 >= 2 ) // pLits[k] is unassigned + Cbs3_ManAssign( p, pLits[k], Level, Abc_Lit2Var(iLit), Abc_Lit2Var(pLits[k+1]) ); + else if ( Value0 == Abc_LitIsCompl(pLits[k]) ) // pLits[k] is false + return Cbs3_ManAnalyze( p, Level, Abc_Lit2Var(iLit), Abc_Lit2Var(pLits[k]), Abc_Lit2Var(pLits[k+1]) ); + } + if ( Value1 != -1 && Value0 == Abc_LitIsCompl(pLits[k]) ) // pLits[k] is false + { + if ( Value1 >= 2 ) // pLits[k+1] is unassigned + Cbs3_ManAssign( p, pLits[k+1], Level, Abc_Lit2Var(iLit), Abc_Lit2Var(pLits[k]) ); + else if ( Value1 == Abc_LitIsCompl(pLits[k+1]) ) // pLits[k+1] is false + return Cbs3_ManAnalyze( p, Level, Abc_Lit2Var(iLit), Abc_Lit2Var(pLits[k]), Abc_Lit2Var(pLits[k+1]) ); + } + } + } + Cbs3_ManUpdateJFrontier( p ); + // finalize propagation queue + p->pProp.iHead = p->pProp.iTail; + return 0; +} + +/**Function************************************************************* + + Synopsis [Solve the problem recursively.] + + Description [Returns learnt clause if unsat, NULL if sat or undecided.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cbs3_ManSolve2_rec( Cbs3_Man_t * p, int Level ) +{ + Cbs3_Que_t * pQue = &(p->pClauses); + int iPropHead, iJustHead, iJustTail; + int hClause, hLearn0, hLearn1, iVar, iDecLit; + int nRef0, nRef1; + // propagate assignments + assert( !Cbs3_QueIsEmpty(&p->pProp) ); + //if ( (hClause = Cbs3_ManPropagate( p, Level )) ) + if ( (hClause = Cbs3_ManPropagateNew( p, Level )) ) + return hClause; + // check for satisfying assignment + assert( Cbs3_QueIsEmpty(&p->pProp) ); + if ( Cbs3_QueIsEmpty(&p->pJust) ) + return 0; + // quit using resource limits + p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); + if ( Cbs3_ManCheckLimits( p ) ) + return 0; + // remember the state before branching + iPropHead = p->pProp.iHead; + iJustHead = p->pJust.iHead; + iJustTail = p->pJust.iTail; + // find the decision variable + p->nDecs++; + iVar = Cbs3_ManDecide( p ); + assert( !Cbs3_VarIsPi(p, iVar) ); + assert( Cbs3_VarIsJust(p, iVar) ); + // chose decision variable using fanout count + nRef0 = Vec_IntEntry(&p->vRef, Abc_Lit2Var(Cbs3_VarLit0(p, iVar))); + nRef1 = Vec_IntEntry(&p->vRef, Abc_Lit2Var(Cbs3_VarLit1(p, iVar))); +// if ( nRef0 >= nRef1 || (nRef0 == nRef1) && (Abc_Random(0) & 1) ) + if ( nRef0 >= nRef1 ) + iDecLit = Abc_LitNot(Cbs3_VarLit0(p, iVar)); + else + iDecLit = Abc_LitNot(Cbs3_VarLit1(p, iVar)); + // decide on first fanin + Cbs3_ManAssign( p, iDecLit, Level+1, 0, 0 ); + if ( !(hLearn0 = Cbs3_ManSolve2_rec( p, Level+1 )) ) + return 0; + if ( pQue->pData[hLearn0+1] != Abc_Lit2Var(iDecLit) ) + return hLearn0; + Cbs3_ManCancelUntil( p, iPropHead ); + Cbs3_QueRestore( &p->pJust, iJustHead, iJustTail ); + // decide on second fanin + Cbs3_ManAssign( p, Abc_LitNot(iDecLit), Level+1, 0, 0 ); + if ( !(hLearn1 = Cbs3_ManSolve2_rec( p, Level+1 )) ) + return 0; + if ( pQue->pData[hLearn1+1] != Abc_Lit2Var(iDecLit) ) + return hLearn1; + hClause = Cbs3_ManResolve( p, Level, hLearn0, hLearn1 ); + p->Pars.nBTThis++; + return hClause; +} + +/**Function************************************************************* + + Synopsis [Looking for a satisfying assignment of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManSolveInt( Cbs3_Man_t * p, int iLit ) +{ + int RetValue = 0; + assert( !p->pProp.iHead && !p->pProp.iTail ); + assert( !p->pJust.iHead && !p->pJust.iTail ); + p->Pars.nBTThis = p->Pars.nJustThis = 0; + Cbs3_ManAssign( p, iLit, 0, 0, 0 ); + if ( !Cbs3_ManSolve2_rec(p, 0) && !Cbs3_ManCheckLimits(p) ) + Cbs3_ManSaveModel( p, p->vModel ); + else + RetValue = 1; + Cbs3_ManCancelUntil( p, 0 ); + p->pJust.iHead = p->pJust.iTail = 0; + p->Pars.nBTTotal += p->Pars.nBTThis; + p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); + if ( Cbs3_ManCheckLimits( p ) ) + RetValue = -1; + return RetValue; +} +int Cbs3_ManSolve( Cbs3_Man_t * p, int iLit, int nRestarts ) +{ + int i, RetValue = -1; + assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 ); + for ( i = 0; i < nRestarts; i++ ) + if ( (RetValue = Cbs3_ManSolveInt(p, iLit)) != -1 ) + break; + Cbs3_ManCleanWatch( p ); + p->pClauses.iHead = p->pClauses.iTail = 1; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Prints statistics of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs3_ManSatPrintStats( Cbs3_Man_t * p ) +{ + printf( "CO = %8d ", Gia_ManCoNum(p->pAig) ); + printf( "AND = %8d ", Gia_ManAndNum(p->pAig) ); + printf( "Conf = %6d ", p->Pars.nBTLimit ); + printf( "Restart = %2d ", p->Pars.nRestLimit ); + printf( "JustMax = %5d ", p->Pars.nJustLimit ); + printf( "\n" ); + printf( "Unsat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUnsat, p->nSatTotal? 100.0*p->nSatUnsat/p->nSatTotal :0.0, p->nSatUnsat? 1.0*p->nConfUnsat/p->nSatUnsat :0.0 ); + ABC_PRTP( "Time", p->timeSatUnsat, p->timeTotal ); + printf( "Sat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatSat, p->nSatTotal? 100.0*p->nSatSat/p->nSatTotal :0.0, p->nSatSat? 1.0*p->nConfSat/p->nSatSat : 0.0 ); + ABC_PRTP( "Time", p->timeSatSat, p->timeTotal ); + printf( "Undef calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUndec, p->nSatTotal? 100.0*p->nSatUndec/p->nSatTotal :0.0, p->nSatUndec? 1.0*p->nConfUndec/p->nSatUndec : 0.0 ); + ABC_PRTP( "Time", p->timeSatUndec, p->timeTotal ); + ABC_PRT( "Total time", p->timeTotal ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManAddVar( Cbs3_Man_t * p, int iGiaObj ) +{ + assert( Vec_IntSize(&p->vMap) == p->nVars ); + Vec_IntPush( &p->vMap, iGiaObj ); + Vec_IntPush( &p->vRef, Gia_ObjRefNumId(p->pAig, iGiaObj) ); + Vec_IntPushTwo( &p->vFans, 0, 0 ); + Vec_WecPushLevel(&p->vImps); + Vec_WecPushLevel(&p->vImps); + return Abc_Var2Lit( p->nVars++, 0 ); +} +static inline void Cbs3_ManAddConstr( Cbs3_Man_t * p, int x, int x0, int x1 ) +{ + Vec_WecPushTwo( &p->vImps, x , x0, 0 ); // ~x + x0 + Vec_WecPushTwo( &p->vImps, x , x1, 0 ); // ~x + x1 + Vec_WecPushTwo( &p->vImps, 1^x0, 1^x , 0 ); // ~x + x0 + Vec_WecPushTwo( &p->vImps, 1^x1, 1^x , 0 ); // ~x + x1 + Vec_WecPushTwo( &p->vImps, 1^x , 1^x0, 1^x1 ); // x + ~x0 + ~x1 + Vec_WecPushTwo( &p->vImps, x0, x , 1^x1 ); // x + ~x0 + ~x1 + Vec_WecPushTwo( &p->vImps, x1, x , 1^x0 ); // x + ~x0 + ~x1 +} +static inline void Cbs3_ManAddAnd( Cbs3_Man_t * p, int x, int x0, int x1 ) +{ + assert( x > 0 && x0 > 0 && x1 > 0 ); + Vec_IntWriteEntry( &p->vFans, x, x0 ); + Vec_IntWriteEntry( &p->vFans, x+1, x1 ); + Cbs3_ManAddConstr( p, x, x0, x1 ); +} +static inline int Cbs3_ManToSolver1_rec( Cbs3_Man_t * pSol, Gia_Man_t * p, int iObj, int Depth ) +{ + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); int Lit0, Lit1; + if ( Gia_ObjUpdateTravIdCurrentId(p, iObj) ) + return pObj->Value; + pObj->Value = Cbs3_ManAddVar( pSol, iObj ); + if ( Gia_ObjIsCi(pObj) || Depth == 0 ) + return pObj->Value; + assert( Gia_ObjIsAnd(pObj) ); + Lit0 = Cbs3_ManToSolver1_rec( pSol, p, Gia_ObjFaninId0(pObj, iObj), Depth - Gia_ObjFaninC0(pObj) ); + Lit1 = Cbs3_ManToSolver1_rec( pSol, p, Gia_ObjFaninId1(pObj, iObj), Depth - Gia_ObjFaninC1(pObj) ); + Cbs3_ManAddAnd( pSol, pObj->Value, Lit0 ^ Gia_ObjFaninC0(pObj), Lit1 ^ Gia_ObjFaninC1(pObj) ); + return pObj->Value; +} +static inline int Cbs3_ManToSolver1( Cbs3_Man_t * pSol, Gia_Man_t * p, Gia_Obj_t * pRoot, int nRestarts, int Depth ) +{ + //abctime clk = Abc_Clock(); + assert( Gia_ObjIsCo(pRoot) ); + Cbs3_ManReset( pSol ); + Gia_ManIncrementTravId( p ); + Cbs3_ManToSolver1_rec( pSol, p, Gia_ObjFaninId0p(p, pRoot), Depth ); + Cbs3_ManGrow( pSol ); + Cbs3_ActReset( pSol ); + //pSol->timeSatLoad += Abc_Clock() - clk; + return Cbs3_ManSolve( pSol, Gia_ObjFanin0Copy(pRoot), nRestarts ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_ManPrepare( Cbs3_Man_t * p ) +{ + int x, x0, x1; + Vec_WecInit( &p->vImps, Abc_Var2Lit(p->nVars, 0) ); + Vec_IntForEachEntryDoubleStart( &p->vFans, x0, x1, x, 2 ) + if ( x0 ) Cbs3_ManAddConstr( p, x, x0, x1 ); +} +static inline int Cbs3_ManAddNode( Cbs3_Man_t * p, int iGiaObj, int iLit0, int iLit1 ) +{ + assert( Vec_IntSize(&p->vMap) == p->nVars ); + Vec_IntPush( &p->vMap, iGiaObj ); + Vec_IntPush( &p->vRef, Gia_ObjRefNumId(p->pAig, iGiaObj) ); + Vec_IntPushTwo( &p->vFans, iLit0, iLit1 ); + return Abc_Var2Lit( p->nVars++, 0 ); +} +static inline int Cbs3_ManToSolver2_rec( Cbs3_Man_t * pSol, Gia_Man_t * p, int iObj, int Depth ) +{ + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); int Lit0, Lit1; + if ( Gia_ObjUpdateTravIdCurrentId(p, iObj) ) + return pObj->Value; + if ( Gia_ObjIsCi(pObj) || Depth == 0 ) + return pObj->Value = Cbs3_ManAddNode(pSol, iObj, 0, 0); + assert( Gia_ObjIsAnd(pObj) ); + Lit0 = Cbs3_ManToSolver2_rec( pSol, p, Gia_ObjFaninId0(pObj, iObj), Depth - Gia_ObjFaninC0(pObj) ); + Lit1 = Cbs3_ManToSolver2_rec( pSol, p, Gia_ObjFaninId1(pObj, iObj), Depth - Gia_ObjFaninC1(pObj) ); + return pObj->Value = Cbs3_ManAddNode(pSol, iObj, Lit0 ^ Gia_ObjFaninC0(pObj), Lit1 ^ Gia_ObjFaninC1(pObj)); +} +static inline int Cbs3_ManToSolver2( Cbs3_Man_t * pSol, Gia_Man_t * p, Gia_Obj_t * pRoot, int nRestarts, int Depth ) +{ + //abctime clk = Abc_Clock(); + assert( Gia_ObjIsCo(pRoot) ); + Cbs3_ManReset( pSol ); + Gia_ManIncrementTravId( p ); + Cbs3_ManToSolver2_rec( pSol, p, Gia_ObjFaninId0p(p, pRoot), Depth ); + Cbs3_ManGrow( pSol ); + Cbs3_ManPrepare( pSol ); + Cbs3_ActReset( pSol ); + //pSol->timeSatLoad += Abc_Clock() - clk; + return Cbs3_ManSolve( pSol, Gia_ObjFanin0Copy(pRoot), nRestarts ); +} + + +/**Function************************************************************* + + Synopsis [Procedure to test the new SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cbs3_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, int nRestarts, Vec_Str_t ** pvStatus, int fVerbose ) +{ + extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ); + Cbs3_Man_t * p; + Vec_Int_t * vCex, * vVisit, * vCexStore; + Vec_Str_t * vStatus; + Gia_Obj_t * pRoot; + int i, status; // 1 = unsat, 0 = sat, -1 = undec + abctime clk, clkTotal = Abc_Clock(); + //assert( Gia_ManRegNum(pAig) == 0 ); + Gia_ManCreateRefs( pAig ); + //Gia_ManLevelNum( pAig ); + // create logic network + p = Cbs3_ManAlloc( pAig ); + p->Pars.nBTLimit = nConfs; + p->Pars.nRestLimit = nRestarts; + // create resulting data-structures + vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); + vCexStore = Vec_IntAlloc( 10000 ); + vVisit = Vec_IntAlloc( 100 ); + vCex = Cbs3_ReadModel( p ); + // solve for each output + Gia_ManForEachCo( pAig, pRoot, i ) + { + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) ) + { + Vec_IntClear( vCex ); + Vec_StrPush( vStatus, (char)(!Gia_ObjFaninC0(pRoot)) ); + if ( Gia_ObjFaninC0(pRoot) ) // const1 + Cec_ManSatAddToStore( vCexStore, vCex, i ); // trivial counter-example + continue; + } + clk = Abc_Clock(); + status = Cbs3_ManToSolver2( p, pAig, pRoot, p->Pars.nRestLimit, 10000 ); + Vec_StrPush( vStatus, (char)status ); + if ( status == -1 ) + { + p->nSatUndec++; + p->nConfUndec += p->Pars.nBTThis; + Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout + p->timeSatUndec += Abc_Clock() - clk; + continue; + } + if ( status == 1 ) + { + p->nSatUnsat++; + p->nConfUnsat += p->Pars.nBTThis; + p->timeSatUnsat += Abc_Clock() - clk; + continue; + } + p->nSatSat++; + p->nConfSat += p->Pars.nBTThis; + //Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit ); + Cec_ManSatAddToStore( vCexStore, vCex, i ); + p->timeSatSat += Abc_Clock() - clk; + } + Vec_IntFree( vVisit ); + p->nSatTotal = Gia_ManPoNum(pAig); + p->timeTotal = Abc_Clock() - clkTotal; + if ( fVerbose ) + Cbs3_ManSatPrintStats( p ); + if ( fVerbose ) + { + printf( "Prop1 = %d. Prop2 = %d. Prop3 = %d. ClaConf = %d. FailJ = %d. FailC = %d. ", p->nPropCalls[0], p->nPropCalls[1], p->nPropCalls[2], p->nClauseConf, p->nFails[0], p->nFails[1] ); + printf( "Mem usage %.2f MB.\n", 1.0*Cbs3_ManMemory(p)/(1<<20) ); + //Abc_PrintTime( 1, "JFront", p->timeJFront ); + //Abc_PrintTime( 1, "Loading", p->timeSatLoad ); + //printf( "Decisions = %d.\n", p->nDecs ); + } + Cbs3_ManStop( p ); + *pvStatus = vStatus; + return vCexStore; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/gia/giaCut.c b/src/aig/gia/giaCut.c index f70f0fc0..7ee795b6 100644 --- a/src/aig/gia/giaCut.c +++ b/src/aig/gia/giaCut.c @@ -602,10 +602,10 @@ void Gia_StoRefObj( Gia_Sto_t * p, int iObj ) } void Gia_StoComputeCuts( Gia_Man_t * pGia ) { - int nCutSize = 6; - int nCutNum = 25; - int fCutMin = 1; - int fTruthMin = 1; + int nCutSize = 8; + int nCutNum = 6; + int fCutMin = 0; + int fTruthMin = 0; int fVerbose = 1; Gia_Sto_t * p = Gia_StoAlloc( pGia, nCutSize, nCutNum, fCutMin, fTruthMin, fVerbose ); Gia_Obj_t * pObj; int i, iObj; @@ -637,6 +637,147 @@ void Gia_StoComputeCuts( Gia_Man_t * pGia ) Gia_StoFree( p ); } + +/**Function************************************************************* + + Synopsis [Extract a given number of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_StoSelectOneCut( Vec_Wec_t * vCuts, int iObj, Vec_Int_t * vCut, int nCutSizeMin ) +{ + Vec_Int_t * vThis = Vec_WecEntry( vCuts, iObj ); + int i, v, * pCut, * pList = Vec_IntArray( vThis ); + if ( pList == NULL ) + return 0; + Vec_IntClear( vCut ); + Sdb_ForEachCut( pList, pCut, i ) + { + if ( pCut[0] < nCutSizeMin ) + continue; + for ( v = 0; v <= pCut[0]; v++ ) + Vec_IntPush( vCut, pCut[v] ); + return 1; + } + return 0; +} +Vec_Wec_t * Gia_ManSelectCuts( Vec_Wec_t * vCuts, int nCuts, int nCutSizeMin ) +{ + Vec_Wec_t * vCutsSel = Vec_WecStart( nCuts ); + int i; srand( time(NULL) ); + for ( i = 0; i < nCuts; i++ ) + while ( !Gia_StoSelectOneCut(vCuts, (rand() | (rand() << 15)) % Vec_WecSize(vCuts), Vec_WecEntry(vCutsSel, i), nCutSizeMin) ); + return vCutsSel; +} +Vec_Wec_t * Gia_ManExtractCuts( Gia_Man_t * pGia, int nCutSize0, int nCuts0, int fVerbose0 ) +{ + int nCutSize = nCutSize0; + int nCutNum = 6; + int fCutMin = 0; + int fTruthMin = 0; + int fVerbose = fVerbose0; + Vec_Wec_t * vCutsSel; + Gia_Sto_t * p = Gia_StoAlloc( pGia, nCutSize, nCutNum, fCutMin, fTruthMin, fVerbose ); + Gia_Obj_t * pObj; int i, iObj; + assert( nCutSize <= GIA_MAX_CUTSIZE ); + assert( nCutNum < GIA_MAX_CUTNUM ); + // prepare references + Gia_ManForEachObj( p->pGia, pObj, iObj ) + Gia_StoRefObj( p, iObj ); + // compute cuts + Gia_StoComputeCutsConst0( p, 0 ); + Gia_ManForEachCiId( p->pGia, iObj, i ) + Gia_StoComputeCutsCi( p, iObj ); + Gia_ManForEachAnd( p->pGia, pObj, iObj ) + Gia_StoComputeCutsNode( p, iObj ); + if ( p->fVerbose ) + { + printf( "Running cut computation with CutSize = %d CutNum = %d CutMin = %s TruthMin = %s\n", + p->nCutSize, p->nCutNum, p->fCutMin ? "yes":"no", p->fTruthMin ? "yes":"no" ); + printf( "CutPair = %.0f ", p->CutCount[0] ); + printf( "Merge = %.0f (%.2f %%) ", p->CutCount[1], 100.0*p->CutCount[1]/p->CutCount[0] ); + printf( "Eval = %.0f (%.2f %%) ", p->CutCount[2], 100.0*p->CutCount[2]/p->CutCount[0] ); + printf( "Cut = %.0f (%.2f %%) ", p->CutCount[3], 100.0*p->CutCount[3]/p->CutCount[0] ); + printf( "Cut/Node = %.2f ", p->CutCount[3] / Gia_ManAndNum(p->pGia) ); + printf( "\n" ); + printf( "The number of nodes with cut count over the limit (%d cuts) = %d nodes (out of %d). ", + p->nCutNum, p->nCutsOver, Gia_ManAndNum(pGia) ); + Abc_PrintTime( 0, "Time", Abc_Clock() - p->clkStart ); + } + vCutsSel = Gia_ManSelectCuts( p->vCuts, nCuts0, nCutSize0-1 ); + Gia_StoFree( p ); + return vCutsSel; +} +void Gia_ManCreateWins( Gia_Man_t * pGia, Vec_Wec_t * vCuts ) +{ + Gia_Obj_t * pObj; + Vec_Wec_t * vWins = Vec_WecStart( Gia_ManObjNum(pGia) ); + Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); + Vec_Int_t * vCut; int i, k, Obj, Cut; + Vec_WecForEachLevel( vCuts, vCut, i ) + Vec_IntForEachEntryStart( vCut, Obj, k, 1 ) + Vec_IntPush( Vec_WecEntry(vWins, Obj), i ); + Gia_ManForEachAnd( pGia, pObj, Obj ) + { + Vec_Int_t * vWin = Vec_WecEntry(vWins, Obj); + Vec_Int_t * vWin0 = Vec_WecEntry(vWins, Gia_ObjFaninId0(pObj, Obj)); + Vec_Int_t * vWin1 = Vec_WecEntry(vWins, Gia_ObjFaninId1(pObj, Obj)); + Vec_IntTwoFindCommon( vWin0, vWin1, vTemp ); + Vec_IntForEachEntry( vTemp, Cut, k ) + { + Vec_IntPushUniqueOrder( vWin, Cut ); + Vec_IntPush( Vec_WecEntry(vCuts, Cut), Obj ); + } + } + Vec_WecFree( vWins ); + Vec_IntFree( vTemp ); +} +void Gia_ManPrintWins( Vec_Wec_t * vCuts ) +{ + Vec_Int_t * vCut; int i, k, Obj; + Vec_WecForEachLevel( vCuts, vCut, i ) + { + int nInputs = Vec_IntEntry(vCut, 0); + printf( "Cut %5d : ", i ); + printf( "Supp = %d ", nInputs ); + printf( "Nodes = %d ", Vec_IntSize(vCut) - 1 - nInputs ); + Vec_IntForEachEntryStartStop( vCut, Obj, k, 1, nInputs+1 ) + printf( "%d ", Obj ); + printf( " " ); + Vec_IntForEachEntryStart( vCut, Obj, k, nInputs+1 ) + printf( "%d ", Obj ); + printf( "\n" ); + } +} +void Gia_ManPrintWinStats( Vec_Wec_t * vCuts ) +{ + Vec_Int_t * vCut; int i, nInputs = 0, nNodes = 0; + Vec_WecForEachLevel( vCuts, vCut, i ) + { + nInputs += Vec_IntEntry(vCut, 0); + nNodes += Vec_IntSize(vCut) - 1 - Vec_IntEntry(vCut, 0); + } + printf( "Computed %d windows with average support %.3f and average volume %.3f.\n", + Vec_WecSize(vCuts), 1.0*nInputs/Vec_WecSize(vCuts), 1.0*nNodes/Vec_WecSize(vCuts) ); +} +void Gia_ManExtractTest( Gia_Man_t * pGia ) +{ + extern Vec_Wec_t * Gia_ManExtractCuts2( Gia_Man_t * p, int nCutSize, int nCuts, int fVerbose ); + Vec_Wec_t * vCutsSel = Gia_ManExtractCuts2( pGia, 8, 10000, 1 ); + //Vec_Wec_t * vCutsSel = Gia_ManExtractCuts( pGia, 8, 10000, 1 ); + abctime clk = Abc_Clock(); + Gia_ManCreateWins( pGia, vCutsSel ); + //Gia_ManPrintWins( vCutsSel ); + Gia_ManPrintWinStats( vCutsSel ); + Vec_WecFree( vCutsSel ); + Abc_PrintTime( 0, "Creating windows", Abc_Clock() - clk ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaDecs.c b/src/aig/gia/giaDecs.c new file mode 100644 index 00000000..343891d5 --- /dev/null +++ b/src/aig/gia/giaDecs.c @@ -0,0 +1,350 @@ +/**CFile**************************************************************** + + FileName [giaDecs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Calling various decomposition engines.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaDecs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig/gia/gia.h" +#include "misc/util/utilTruth.h" +#include "misc/extra/extra.h" +#include "bool/bdc/bdc.h" +#include "bool/kit/kit.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); +extern Vec_Int_t * Gia_ManResubOne( Vec_Ptr_t * vDivs, int nWords, int nLimit, int nDivsMax, int iChoice, int fUseXor, int fDebug, int fVerbose, word * pFunc, int Depth ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ResubVarNum( Vec_Int_t * vResub ) +{ + if ( Vec_IntSize(vResub) == 1 ) + return Vec_IntEntryLast(vResub) >= 2; + return Vec_IntEntryLast(vResub)/2 - Vec_IntSize(vResub)/2 - 1; +} +word Gia_ResubToTruth6_rec( Vec_Int_t * vResub, int iNode, int nVars ) +{ + assert( iNode >= 0 && nVars <= 6 ); + if ( iNode < nVars ) + return s_Truths6[iNode]; + else + { + int iLit0 = Vec_IntEntry( vResub, Abc_Var2Lit(iNode-nVars, 0) ); + int iLit1 = Vec_IntEntry( vResub, Abc_Var2Lit(iNode-nVars, 1) ); + word Res0 = Gia_ResubToTruth6_rec( vResub, Abc_Lit2Var(iLit0)-2, nVars ); + word Res1 = Gia_ResubToTruth6_rec( vResub, Abc_Lit2Var(iLit1)-2, nVars ); + Res0 = Abc_LitIsCompl(iLit0) ? ~Res0 : Res0; + Res1 = Abc_LitIsCompl(iLit1) ? ~Res1 : Res1; + return iLit0 > iLit1 ? Res0 ^ Res1 : Res0 & Res1; + } +} +word Gia_ResubToTruth6( Vec_Int_t * vResub ) +{ + word Res; + int iRoot = Vec_IntEntryLast(vResub); + if ( iRoot < 2 ) + return iRoot ? ~(word)0 : 0; + assert( iRoot != 2 && iRoot != 3 ); + Res = Gia_ResubToTruth6_rec( vResub, Abc_Lit2Var(iRoot)-2, Gia_ResubVarNum(vResub) ); + return Abc_LitIsCompl(iRoot) ? ~Res : Res; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Gia_ManDeriveTruths( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vSet, int nWords ) +{ + int nTtWords = Abc_Truth6WordNum(Vec_IntSize(vSet)); + int nFuncs = Vec_WrdSize(vIsfs) / 2 / nWords; + Vec_Wrd_t * vRes = Vec_WrdStart( 2 * nFuncs * nTtWords ); + Vec_Wrd_t * vIn = Vec_WrdStart( 64*nWords ), * vOut; + int i, f, m, iObj; word Func; + assert( Vec_IntSize(vSet) <= 64 ); + Vec_IntForEachEntry( vSet, iObj, i ) + Abc_TtCopy( Vec_WrdEntryP(vIn, i*nWords), Vec_WrdEntryP(vSims, Vec_IntEntry(vCands, iObj)*nWords), nWords, 0 ); + vOut = Vec_WrdStart( Vec_WrdSize(vIn) ); + Extra_BitMatrixTransposeP( vIn, nWords, vOut, 1 ); + for ( f = 0; f < nFuncs; f++ ) + { + word * pIsf[2] = { Vec_WrdEntryP(vIsfs, (2*f+0)*nWords), + Vec_WrdEntryP(vIsfs, (2*f+1)*nWords) }; + word * pTruth[2] = { Vec_WrdEntryP(vRes, (2*f+0)*nTtWords), + Vec_WrdEntryP(vRes, (2*f+1)*nTtWords) }; + for ( m = 0; m < 64*nWords; m++ ) + { + int iMint = (int)Vec_WrdEntry(vOut, m); + int Value0 = Abc_TtGetBit( pIsf[0], m ); + int Value1 = Abc_TtGetBit( pIsf[1], m ); + if ( !Value0 && !Value1 ) + continue; + if ( Value0 && Value1 ) + printf( "Internal error: Onset and Offset overlap.\n" ); + assert( !Value0 || !Value1 ); + Abc_TtSetBit( pTruth[Value1], iMint ); + } + if ( Abc_TtCountOnesVecMask(pTruth[0], pTruth[1], nTtWords, 0) ) + printf( "Verification for function %d failed for %d minterm pairs.\n", f, + Abc_TtCountOnesVecMask(pTruth[0], pTruth[1], nTtWords, 0) ); + } + if ( Vec_IntSize(vSet) < 6 ) + Vec_WrdForEachEntry( vRes, Func, i ) + Vec_WrdWriteEntry( vRes, i, Abc_Tt6Stretch(Func, Vec_IntSize(vSet)) ); + Vec_WrdFree( vIn ); + Vec_WrdFree( vOut ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCountResub( Vec_Wrd_t * vTruths, int nVars, int fVerbose ) +{ + Vec_Int_t * vResub; int nNodes; + int nTtWords = Abc_Truth6WordNum(nVars); + int v, nFuncs = Vec_WrdSize(vTruths) / 2 / nTtWords; + Vec_Wrd_t * vElems = Vec_WrdStartTruthTables( nVars ); + Vec_Ptr_t * vDivs = Vec_PtrAlloc( 2 + nVars ); + assert( Vec_WrdSize(vElems) == nTtWords * nVars ); + assert( nFuncs == 1 ); + Vec_PtrPush( vDivs, Vec_WrdEntryP(vTruths, (2*0+0)*nTtWords) ); + Vec_PtrPush( vDivs, Vec_WrdEntryP(vTruths, (2*0+1)*nTtWords) ); + for ( v = 0; v < nVars; v++ ) + Vec_PtrPush( vDivs, Vec_WrdEntryP(vElems, v*nTtWords) ); + vResub = Gia_ManResubOne( vDivs, nTtWords, 30, 100, 0, 0, 0, fVerbose, NULL, 0 ); + Vec_PtrFree( vDivs ); + Vec_WrdFree( vElems ); + nNodes = Vec_IntSize(vResub) ? Vec_IntSize(vResub)/2 : 999; + Vec_IntFree( vResub ); + return nNodes; +} +Vec_Int_t * Gia_ManDeriveResub( Vec_Wrd_t * vTruths, int nVars ) +{ + Vec_Int_t * vResub; + int nTtWords = Abc_Truth6WordNum(nVars); + int v, nFuncs = Vec_WrdSize(vTruths) / 2 / nTtWords; + Vec_Wrd_t * vElems = Vec_WrdStartTruthTables( nVars ); + Vec_Ptr_t * vDivs = Vec_PtrAlloc( 2 + nVars ); + assert( Vec_WrdSize(vElems) == nTtWords * nVars ); + assert( nFuncs == 1 ); + Vec_PtrPush( vDivs, Vec_WrdEntryP(vTruths, (2*0+0)*nTtWords) ); + Vec_PtrPush( vDivs, Vec_WrdEntryP(vTruths, (2*0+1)*nTtWords) ); + for ( v = 0; v < nVars; v++ ) + Vec_PtrPush( vDivs, Vec_WrdEntryP(vElems, v*nTtWords) ); + vResub = Gia_ManResubOne( vDivs, nTtWords, 30, 100, 0, 0, 0, 0, NULL, 0 ); + Vec_PtrFree( vDivs ); + Vec_WrdFree( vElems ); + return vResub; +} + +int Gia_ManCountBidec( Vec_Wrd_t * vTruths, int nVars, int fVerbose ) +{ + int nNodes, nTtWords = Abc_Truth6WordNum(nVars); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + Abc_TtOr( pTruth[0], pTruth[0], pTruth[1], nTtWords ); + nNodes = Bdc_ManBidecNodeNum( pTruth[1], pTruth[0], nVars, fVerbose ); + Abc_TtSharp( pTruth[0], pTruth[0], pTruth[1], nTtWords ); + return nNodes; +} +Vec_Int_t * Gia_ManDeriveBidec( Vec_Wrd_t * vTruths, int nVars ) +{ + Vec_Int_t * vRes = NULL; + int nTtWords = Abc_Truth6WordNum(nVars); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + Abc_TtOr( pTruth[0], pTruth[0], pTruth[1], nTtWords ); + vRes = Bdc_ManBidecResub( pTruth[1], pTruth[0], nVars ); + Abc_TtSharp( pTruth[0], pTruth[0], pTruth[1], nTtWords ); + return vRes; +} + +int Gia_ManCountIsop( Vec_Wrd_t * vTruths, int nVars, int fVerbose ) +{ + int nTtWords = Abc_Truth6WordNum(nVars); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + int nNodes = Kit_IsopNodeNum( (unsigned *)pTruth[0], (unsigned *)pTruth[1], nVars, NULL ); + return nNodes; +} +Vec_Int_t * Gia_ManDeriveIsop( Vec_Wrd_t * vTruths, int nVars ) +{ + Vec_Int_t * vRes = NULL; + int nTtWords = Abc_Truth6WordNum(nVars); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + vRes = Kit_IsopResub( (unsigned *)pTruth[0], (unsigned *)pTruth[1], nVars, NULL ); + return vRes; +} + +int Gia_ManCountBdd( Vec_Wrd_t * vTruths, int nVars, int fVerbose ) +{ + extern Gia_Man_t * Gia_TryPermOptNew( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ); + int nTtWords = Abc_Truth6WordNum(nVars); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + Gia_Man_t * pGia; int nNodes; + + Abc_TtOr( pTruth[1], pTruth[1], pTruth[0], nTtWords ); + Abc_TtNot( pTruth[0], nTtWords ); + pGia = Gia_TryPermOptNew( pTruth[0], nVars, 1, nTtWords, 50, 0 ); + Abc_TtNot( pTruth[0], nTtWords ); + Abc_TtSharp( pTruth[1], pTruth[1], pTruth[0], nTtWords ); + + nNodes = Gia_ManAndNum(pGia); + Gia_ManStop( pGia ); + return nNodes; +} +Vec_Int_t * Gia_ManDeriveBdd( Vec_Wrd_t * vTruths, int nVars ) +{ + extern Vec_Int_t * Gia_ManToGates( Gia_Man_t * p ); + Vec_Int_t * vRes = NULL; + extern Gia_Man_t * Gia_TryPermOptNew( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ); + int nTtWords = Abc_Truth6WordNum(nVars); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + Gia_Man_t * pGia; + + Abc_TtOr( pTruth[1], pTruth[1], pTruth[0], nTtWords ); + Abc_TtNot( pTruth[0], nTtWords ); + pGia = Gia_TryPermOptNew( pTruth[0], nVars, 1, nTtWords, 50, 0 ); + Abc_TtNot( pTruth[0], nTtWords ); + Abc_TtSharp( pTruth[1], pTruth[1], pTruth[0], nTtWords ); + + vRes = Gia_ManToGates( pGia ); + Gia_ManStop( pGia ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManEvalSolutionOne( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vSet, int nWords, int fVerbose ) +{ + Vec_Wrd_t * vTruths = Gia_ManDeriveTruths( p, vSims, vIsfs, vCands, vSet, nWords ); + int nTtWords = Vec_WrdSize(vTruths)/2, nVars = Vec_IntSize(vSet); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + int nNodesResub = Gia_ManCountResub( vTruths, nVars, 0 ); + int nNodesBidec = nVars > 2 ? Gia_ManCountBidec( vTruths, nVars, 0 ) : 999; + int nNodesIsop = nVars > 2 ? Gia_ManCountIsop( vTruths, nVars, 0 ) : 999; + int nNodesBdd = nVars > 2 ? Gia_ManCountBdd( vTruths, nVars, 0 ) : 999; + int nNodesMin = Abc_MinInt( Abc_MinInt(nNodesResub, nNodesBidec), Abc_MinInt(nNodesIsop, nNodesBdd) ); + if ( fVerbose ) + { + printf( "Size = %2d ", nVars ); + printf( "Resub =%3d ", nNodesResub ); + printf( "Bidec =%3d ", nNodesBidec ); + printf( "Isop =%3d ", nNodesIsop ); + printf( "Bdd =%3d ", nNodesBdd ); + Abc_TtIsfPrint( pTruth[0], pTruth[1], nTtWords ); + if ( nVars <= 6 ) + { + printf( " " ); + Extra_PrintHex( stdout, (unsigned*)pTruth[0], nVars ); + printf( " " ); + Extra_PrintHex( stdout, (unsigned*)pTruth[1], nVars ); + } + printf( "\n" ); + } + Vec_WrdFree( vTruths ); + if ( nNodesMin > 500 ) + return -1; + if ( nNodesMin == nNodesResub ) + return (nNodesMin << 2) | 0; + if ( nNodesMin == nNodesBidec ) + return (nNodesMin << 2) | 1; + if ( nNodesMin == nNodesIsop ) + return (nNodesMin << 2) | 2; + if ( nNodesMin == nNodesBdd ) + return (nNodesMin << 2) | 3; + return -1; +} +Vec_Int_t * Gia_ManDeriveSolutionOne( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vSet, int nWords, int Type ) +{ + Vec_Int_t * vRes = NULL; + Vec_Wrd_t * vTruths = Gia_ManDeriveTruths( p, vSims, vIsfs, vCands, vSet, nWords ); + int nTtWords = Vec_WrdSize(vTruths)/2, nVars = Vec_IntSize(vSet); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + if ( Type == 0 ) + vRes = Gia_ManDeriveResub( vTruths, nVars ); + else if ( Type == 1 ) + vRes = Gia_ManDeriveBidec( vTruths, nVars ); + else if ( Type == 2 ) + vRes = Gia_ManDeriveIsop( vTruths, nVars ); + else if ( Type == 3 ) + vRes = Gia_ManDeriveBdd( vTruths, nVars ); + if ( vRes && Gia_ResubVarNum(vRes) <= 6 ) + { + word Func = Gia_ResubToTruth6( vRes ); + assert( !(Func & pTruth[0][0]) ); + assert( !(pTruth[1][0] & ~Func) ); + } + Vec_WrdFree( vTruths ); + return vRes; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/gia/giaDeep.c b/src/aig/gia/giaDeep.c index f8b2930e..815a546e 100644 --- a/src/aig/gia/giaDeep.c +++ b/src/aig/gia/giaDeep.c @@ -19,14 +19,14 @@ ***********************************************************************/ #include "gia.h" +#include "base/main/main.h" +#include "base/cmd/cmd.h" ABC_NAMESPACE_IMPL_START - //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -43,9 +43,121 @@ ABC_NAMESPACE_IMPL_START SeeAlso [] ***********************************************************************/ -Gia_Man_t * Gia_ManDeepSyn( Gia_Man_t * pGia, int TimeOut, int nAnds, int Seed, int fVerbose ) +Gia_Man_t * Gia_ManDeepSynOne( int nNoImpr, int TimeOut, int nAnds, int Seed, int fUseTwo, int fVerbose ) +{ + abctime nTimeToStop = TimeOut ? Abc_Clock() + TimeOut * CLOCKS_PER_SEC : 0; + abctime clkStart = Abc_Clock(); + int s, i, IterMax = 100000, nAndsMin = -1, iIterLast = -1; + Gia_Man_t * pTemp = Abc_FrameReadGia(Abc_FrameGetGlobalFrame()); + Gia_Man_t * pNew = Gia_ManDup( pTemp ); + Abc_Random(1); + for ( s = 0; s < 10+Seed; s++ ) + Abc_Random(0); + for ( i = 0; i < IterMax; i++ ) + { + unsigned Rand = Abc_Random(0); + int fDch = Rand & 1; + //int fCom = (Rand >> 1) & 3; + int fCom = (Rand >> 1) & 1; + int fFx = (Rand >> 2) & 1; + int KLut = fUseTwo ? 2 + (i % 5) : 3 + (i % 4); + int fChange = 0; + char Command[1000]; + char * pComp = NULL; + if ( fCom == 3 ) + pComp = "; &put; compress2rs; compress2rs; compress2rs; &get"; + else if ( fCom == 2 ) + pComp = "; &put; compress2rs; compress2rs; &get"; + else if ( fCom == 1 ) + pComp = "; &put; compress2rs; &get"; + else if ( fCom == 0 ) + pComp = "; &dc2"; + sprintf( Command, "&dch%s; &if -a -K %d; &mfs -e -W 20 -L 20%s%s", + fDch ? " -f" : "", KLut, fFx ? "; &fx; &st" : "", pComp ); + if ( Abc_FrameIsBatchMode() ) + { + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), Command) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", Command ); + return NULL; + } + } + else + { + Abc_FrameSetBatchMode( 1 ); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), Command) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", Command ); + return NULL; + } + Abc_FrameSetBatchMode( 0 ); + } + pTemp = Abc_FrameReadGia(Abc_FrameGetGlobalFrame()); + if ( Gia_ManAndNum(pNew) > Gia_ManAndNum(pTemp) ) + { + Gia_ManStop( pNew ); + pNew = Gia_ManDup( pTemp ); + fChange = 1; + iIterLast = i; + } + else if ( Gia_ManAndNum(pNew) + Gia_ManAndNum(pNew)/10 < Gia_ManAndNum(pTemp) ) + { + //printf( "Updating\n" ); + //Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), Gia_ManDup(pNew) ); + } + if ( fChange && fVerbose ) + { + printf( "Iter %6d : ", i ); + printf( "Time %8.2f sec : ", (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC ); + printf( "And = %6d ", Gia_ManAndNum(pNew) ); + printf( "Lev = %3d ", Gia_ManLevelNum(pNew) ); + if ( fChange ) + printf( "<== best : " ); + else if ( fVerbose ) + printf( " " ); + printf( "%s", Command ); + printf( "\n" ); + } + if ( nTimeToStop && Abc_Clock() > nTimeToStop ) + { + printf( "Runtime limit (%d sec) is reached after %d iterations.\n", TimeOut, i ); + break; + } + if ( i - iIterLast > nNoImpr ) + { + printf( "Completed %d iterations without improvement in %.2f seconds.\n", + nNoImpr, (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC ); + break; + } + } + if ( i == IterMax ) + printf( "Iteration limit (%d iters) is reached after %.2f seconds.\n", IterMax, (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC ); + else if ( nAnds && nAndsMin <= nAnds ) + printf( "Quality goal (%d nodes <= %d nodes) is achieved after %d iterations and %.2f seconds.\n", + nAndsMin, nAnds, i, (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC ); + return pNew; +} +Gia_Man_t * Gia_ManDeepSyn( Gia_Man_t * pGia, int nIters, int nNoImpr, int TimeOut, int nAnds, int Seed, int fUseTwo, int fVerbose ) { - return NULL; + Gia_Man_t * pInit = Gia_ManDup(pGia); + Gia_Man_t * pBest = Gia_ManDup(pGia); + Gia_Man_t * pThis; + int i; + for ( i = 0; i < nIters; i++ ) + { + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), Gia_ManDup(pInit) ); + pThis = Gia_ManDeepSynOne( nNoImpr, TimeOut, nAnds, Seed+i, fUseTwo, fVerbose ); + if ( Gia_ManAndNum(pBest) > Gia_ManAndNum(pThis) ) + { + Gia_ManStop( pBest ); + pBest = pThis; + } + else + Gia_ManStop( pThis ); + + } + Gia_ManStop( pInit ); + return pBest; } //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaDfs.c b/src/aig/gia/giaDfs.c index 5cfe3b44..7ed59b9a 100644 --- a/src/aig/gia/giaDfs.c +++ b/src/aig/gia/giaDfs.c @@ -418,6 +418,34 @@ Vec_Vec_t * Gia_ManLevelize( Gia_Man_t * p ) /**Function************************************************************* + Synopsis [Levelizes the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManLevelizeR( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + Vec_Wec_t * vLevels; + int nLevels, Level, i; + nLevels = Gia_ManLevelRNum( p ); + vLevels = Vec_WecStart( nLevels + 1 ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( i == 0 || (!Gia_ObjIsCo(pObj) && !Gia_ObjLevel(p, pObj)) ) + continue; + Level = Gia_ObjLevel( p, pObj ); + assert( Level <= nLevels ); + Vec_WecPush( vLevels, Level, i ); + } + return vLevels; +} +/**Function************************************************************* + Synopsis [Computes reverse topological order.] Description [Assumes that levels are already assigned. diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index 4f448c40..b3fcd295 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -466,7 +466,16 @@ Gia_Man_t * Gia_ManDupOrderDfsChoices( Gia_Man_t * p ) SeeAlso [] ***********************************************************************/ -Gia_Man_t * Gia_ManDupOrderDfsReverse( Gia_Man_t * p ) +int Gia_ManDupOrderDfs2_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return pObj->Value; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDupOrderDfs2_rec( pNew, p, Gia_ObjFanin1(pObj) ); + Gia_ManDupOrderDfs2_rec( pNew, p, Gia_ObjFanin0(pObj) ); + return pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManDupOrderDfsReverse( Gia_Man_t * p, int fRevFans, int fRevOuts ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; @@ -476,12 +485,28 @@ Gia_Man_t * Gia_ManDupOrderDfsReverse( Gia_Man_t * p ) pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManConst0(p)->Value = 0; - Gia_ManForEachCoReverse( p, pObj, i ) - Gia_ManDupOrderDfs_rec( pNew, p, pObj ); Gia_ManForEachCi( p, pObj, i ) - if ( !~pObj->Value ) - pObj->Value = Gia_ManAppendCi(pNew); - assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(p) ); + pObj->Value = Gia_ManAppendCi(pNew); + if ( fRevOuts ) + { + if ( fRevFans ) + Gia_ManForEachCoReverse( p, pObj, i ) + Gia_ManDupOrderDfs2_rec( pNew, p, Gia_ObjFanin0(pObj) ); + else + Gia_ManForEachCoReverse( p, pObj, i ) + Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); + } + else + { + if ( fRevFans ) + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupOrderDfs2_rec( pNew, p, Gia_ObjFanin0(pObj) ); + else + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); + } + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManDupRemapCis( pNew, p ); Gia_ManDupRemapCos( pNew, p ); Gia_ManDupRemapEquiv( pNew, p ); @@ -1327,7 +1352,7 @@ Gia_Man_t * Gia_ManDupMarked( Gia_Man_t * p ) { Gia_Obj_t * pRepr; pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pNew) ); - for ( i = 0; i < Gia_ManObjNum(p); i++ ) + for ( i = 0; i < Gia_ManObjNum(pNew); i++ ) Gia_ObjSetRepr( pNew, i, GIA_VOID ); Gia_ManForEachObj1( p, pObj, i ) { @@ -1585,6 +1610,52 @@ Gia_Man_t * Gia_ManDupDfsOnePo( Gia_Man_t * p, int iPo ) /**Function************************************************************* + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupDfsRehash_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDupDfsRehash_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManDupDfsRehash_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManDupDfsRehash( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupDfsRehash_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew->nConstrs = p->nConstrs; + if ( p->pCexSeq ) + pNew->pCexSeq = Abc_CexDup( p->pCexSeq, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + Synopsis [Cofactors w.r.t. a primary input variable.] Description [] @@ -2295,6 +2366,31 @@ Gia_Man_t * Gia_ManDupTrimmed2( Gia_Man_t * p ) assert( !Gia_ManHasDangling( pNew ) ); return pNew; } +Gia_Man_t * Gia_ManDupTrimmed3( Gia_Man_t * p ) +{ + Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(p) ); + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // mark duplicated POs + Gia_ManForEachPo( p, pObj, i ) + Vec_IntWriteEntry( vMap, Gia_ObjFaninId0p(p, pObj), i ); + Gia_ManForEachPo( p, pObj, i ) + if ( Vec_IntEntry(vMap, Gia_ObjFaninId0p(p, pObj)) == i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Vec_IntFree( vMap ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} /**Function************************************************************* @@ -2916,6 +3012,44 @@ Vec_Ptr_t * Gia_ManMiterNames( Vec_Ptr_t * p, int nOuts ) /**Function************************************************************* + Synopsis [Pair-wise miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManPairWiseMiter( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pObj2; + int i, k, iLit; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + Gia_ManForEachPo( p, pObj2, k ) + { + if ( i >= k ) + continue; + iLit = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin0Copy(pObj2) ); + Gia_ManAppendCo( pNew, iLit ); + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + Synopsis [Transforms the circuit into a regular miter.] Description [] @@ -3448,7 +3582,7 @@ Gia_Man_t * Gia_ManDupCones( Gia_Man_t * p, int * pPos, int nPos, int fTrimPis ) Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); Vec_PtrForEachEntry( Gia_Obj_t *, vRoots, pObj, i ) Gia_ManDupCones_rec( p, pObj, vLeaves, vNodes, vRoots ); - Vec_PtrSort( vLeaves, (int (*)(void))Gia_ObjCompareByCioId ); + Vec_PtrSort( vLeaves, (int (*)(const void *, const void *))Gia_ObjCompareByCioId ); // start the new manager // Gia_ManFillValue( p ); @@ -3460,6 +3594,8 @@ Gia_Man_t * Gia_ManDupCones( Gia_Man_t * p, int * pPos, int nPos, int fTrimPis ) // create PIs if ( fTrimPis ) { + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = ~0; Vec_PtrForEachEntry( Gia_Obj_t *, vLeaves, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); } @@ -3508,7 +3644,7 @@ Gia_Man_t * Gia_ManDupAndCones( Gia_Man_t * p, int * pAnds, int nAnds, int fTrim Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); Vec_PtrForEachEntry( Gia_Obj_t *, vRoots, pObj, i ) Gia_ManDupCones_rec( p, pObj, vLeaves, vNodes, vRoots ); - Vec_PtrSort( vLeaves, (int (*)(void))Gia_ObjCompareByCioId ); + Vec_PtrSort( vLeaves, (int (*)(const void *, const void *))Gia_ObjCompareByCioId ); // start the new manager // Gia_ManFillValue( p ); @@ -4245,7 +4381,7 @@ Gia_Man_t * Gia_ManDupDemiter( Gia_Man_t * p, int fVerbose ) vSuperPtr = Vec_PtrAlloc( Vec_IntSize(vSuper) ); Vec_IntForEachEntry( vSuper, iLit, i ) Vec_PtrPush( vSuperPtr, Gia_Lit2Obj(p, iLit) ); - Vec_PtrSort( vSuperPtr, (int (*)(void))Gia_ManSortByValue ); + Vec_PtrSort( vSuperPtr, (int (*)(const void *, const void *))Gia_ManSortByValue ); // create new manager pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); @@ -4899,6 +5035,38 @@ Gia_Man_t * Gia_ManDupReplaceCut( Gia_Man_t * p ) return pNew; } +/**Function************************************************************* + + Synopsis [Duplicate AIG by creating a cut between logic fed by PIs] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupAddPis( Gia_Man_t * p, int nMulti ) +{ + Gia_Man_t * pNew; int i, k; + Gia_Obj_t * pObj; + pNew = Gia_ManStart( Gia_ManObjNum(p) + Gia_ManCiNum(p) * nMulti ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + { + pObj->Value = Gia_ManAppendCi(pNew); + for ( k = 1; k < nMulti; k++ ) + Gia_ManAppendCi(pNew); + } + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + assert( Gia_ManCiNum(pNew) == nMulti * Gia_ManCiNum(p) ); + return pNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaEmbed.c b/src/aig/gia/giaEmbed.c index b646a311..28d28483 100644 --- a/src/aig/gia/giaEmbed.c +++ b/src/aig/gia/giaEmbed.c @@ -32,7 +32,7 @@ ABC_NAMESPACE_IMPL_START http://www.emis.de/journals/JGAA/accepted/2004/HarelKoren2004.8.2.pdf Iterative refinement is described in the paper: F. A. Aloul, I. L. Markov, and K. A. Sakallah. - "FORCE: A Fast and Easy-To-Implement Variable-Ordering Heuristic", Proc. GLSVLSI’03. + "FORCE: A Fast and Easy-To-Implement Variable-Ordering Heuristic", Proc. GLSVLSI 03. http://www.eecs.umich.edu/~imarkov/pubs/conf/glsvlsi03-force.pdf */ diff --git a/src/aig/gia/giaEquiv.c b/src/aig/gia/giaEquiv.c index 03b9b819..5c82b260 100644 --- a/src/aig/gia/giaEquiv.c +++ b/src/aig/gia/giaEquiv.c @@ -269,6 +269,7 @@ int * Gia_ManDeriveNexts( Gia_Man_t * p ) pTails[i] = i; for ( i = 0; i < Gia_ManObjNum(p); i++ ) { + //if ( p->pReprs[i].iRepr == GIA_VOID ) if ( !p->pReprs[i].iRepr || p->pReprs[i].iRepr == GIA_VOID ) continue; pNexts[ pTails[p->pReprs[i].iRepr] ] = i; @@ -480,8 +481,10 @@ void Gia_ManEquivPrintClasses( Gia_Man_t * p, int fVerbose, float Mem ) } CounterX -= Gia_ManCoNum(p); nLits = Gia_ManCiNum(p) + Gia_ManAndNum(p) - Counter - CounterX; - Abc_Print( 1, "cst =%8d cls =%7d lit =%8d unused =%8d proof =%6d mem =%5.2f MB\n", - Counter0, Counter, nLits, CounterX, Proved, (Mem == 0.0) ? 8.0*Gia_ManObjNum(p)/(1<<20) : Mem ); +// Abc_Print( 1, "cst =%8d cls =%7d lit =%8d unused =%8d proof =%6d mem =%5.2f MB\n", +// Counter0, Counter, nLits, CounterX, Proved, (Mem == 0.0) ? 8.0*Gia_ManObjNum(p)/(1<<20) : Mem ); + Abc_Print( 1, "cst =%8d cls =%7d lit =%8d unused =%8d proof =%6d\n", + Counter0, Counter, nLits, CounterX, Proved ); assert( Gia_ManEquivCheckLits( p, nLits ) ); if ( fVerbose ) { @@ -1985,7 +1988,7 @@ Gia_Man_t * Gia_ManEquivToChoices( Gia_Man_t * p, int nSnapshots ) pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); pNew->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p) ); for ( i = 0; i < Gia_ManObjNum(p); i++ ) - Gia_ObjSetRepr( pNew, i, GIA_VOID ); + pNew->pReprs[i].iRepr = GIA_VOID; Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) @@ -2587,6 +2590,294 @@ void Gia_ManFilterEquivsUsingLatches( Gia_Man_t * pGia, int fFlopsOnly, int fFlo Abc_Print( 1, "The number of literals: Before = %d. After = %d.\n", iLitsOld, iLitsNew ); } +/**Function************************************************************* + + Synopsis [Changing node order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManChangeOrder_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return pObj->Value; + if ( Gia_ObjIsCi(pObj) ) + return pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManChangeOrder_rec( pNew, p, Gia_ObjFanin0(pObj) ); + if ( Gia_ObjIsCo(pObj) ) + return pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManChangeOrder_rec( pNew, p, Gia_ObjFanin1(pObj) ); + return pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManChangeOrder( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i, k; + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachClass( p, i ) + Gia_ClassForEachObj( p, i, k ) + Gia_ManChangeOrder_rec( pNew, p, Gia_ManObj(p, k) ); + Gia_ManForEachConst( p, k ) + Gia_ManChangeOrder_rec( pNew, p, Gia_ManObj(p, k) ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManChangeOrder_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + assert( Gia_ManObjNum(pNew) == Gia_ManObjNum(p) ); + return pNew; +} +void Gia_ManTransferEquivs( Gia_Man_t * p, Gia_Man_t * pNew ) +{ + Vec_Int_t * vClass; + int i, k, iNode, iRepr; + assert( Gia_ManObjNum(p) == Gia_ManObjNum(pNew) ); + assert( p->pReprs != NULL ); + assert( p->pNexts != NULL ); + assert( pNew->pReprs == NULL ); + assert( pNew->pNexts == NULL ); + // start representatives + pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pNew) ); + for ( i = 0; i < Gia_ManObjNum(pNew); i++ ) + Gia_ObjSetRepr( pNew, i, GIA_VOID ); + // iterate over constant candidates + Gia_ManForEachConst( p, i ) + Gia_ObjSetRepr( pNew, Abc_Lit2Var(Gia_ManObj(p, i)->Value), 0 ); + // iterate over class candidates + vClass = Vec_IntAlloc( 100 ); + Gia_ManForEachClass( p, i ) + { + Vec_IntClear( vClass ); + Gia_ClassForEachObj( p, i, k ) + Vec_IntPushUnique( vClass, Abc_Lit2Var(Gia_ManObj(p, k)->Value) ); + assert( Vec_IntSize( vClass ) > 1 ); + Vec_IntSort( vClass, 0 ); + iRepr = Vec_IntEntry( vClass, 0 ); + Vec_IntForEachEntryStart( vClass, iNode, k, 1 ) + Gia_ObjSetRepr( pNew, iNode, iRepr ); + } + Vec_IntFree( vClass ); + pNew->pNexts = Gia_ManDeriveNexts( pNew ); +} +void Gia_ManTransferTest( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; int i; + Gia_Rpr_t * pReprs = p->pReprs; // representatives (for CIs and ANDs) + int * pNexts = p->pNexts; // next nodes in the equivalence classes + Gia_Man_t * pNew = Gia_ManChangeOrder(p); + //Gia_ManEquivPrintClasses( p, 1, 0 ); + assert( Gia_ManObjNum(p) == Gia_ManObjNum(pNew) ); + Gia_ManTransferEquivs( p, pNew ); + p->pReprs = NULL; + p->pNexts = NULL; + // make new point to old + Gia_ManForEachObj( p, pObj, i ) + { + assert( !Abc_LitIsCompl(pObj->Value) ); + Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value))->Value = Abc_Var2Lit(i, 0); + } + Gia_ManTransferEquivs( pNew, p ); + //Gia_ManEquivPrintClasses( p, 1, 0 ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + pReprs[i].fProved = 0; + //printf( "%5d : %5d %5d %5d %5d\n", i, *(int*)&p->pReprs[i], *(int*)&pReprs[i], (int)p->pNexts[i], (int)pNexts[i] ); + if ( memcmp(p->pReprs, pReprs, sizeof(int)*Gia_ManObjNum(p)) ) + printf( "Verification of reprs failed.\n" ); + else + printf( "Verification of reprs succeeded.\n" ); + if ( memcmp(p->pNexts, pNexts, sizeof(int)*Gia_ManObjNum(p)) ) + printf( "Verification of nexts failed.\n" ); + else + printf( "Verification of nexts succeeded.\n" ); + ABC_FREE( pNew->pReprs ); + ABC_FREE( pNew->pNexts ); + ABC_FREE( pReprs ); + ABC_FREE( pNexts ); + Gia_ManStop( pNew ); +} + + +/**Function************************************************************* + + Synopsis [Converting AIG after SAT sweeping into AIG with choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec4_ManMarkIndependentClasses_rec( Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj; + assert( iObj > 0 ); + if ( Gia_ObjIsTravIdPreviousId(p, iObj) ) // failed + return 0; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) // passed + return 1; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + return 1; + assert( Gia_ObjIsAnd(pObj) ); + if ( Cec4_ManMarkIndependentClasses_rec( p, Gia_ObjFaninId0(pObj, iObj) ) && + Cec4_ManMarkIndependentClasses_rec( p, Gia_ObjFaninId1(pObj, iObj) ) ) + return 1; + Gia_ObjSetTravIdPreviousId(p, iObj); + return 0; +} +int Cec4_ManMarkIndependentClasses( Gia_Man_t * p, Gia_Man_t * pNew ) +{ + int iObjNew, iRepr, iObj, Res, fHaveChoices = 0; + Gia_ManCleanMark01(p); + Gia_ManForEachClass( p, iRepr ) + { + Gia_ManIncrementTravId( pNew ); + Gia_ManIncrementTravId( pNew ); + iObjNew = Abc_Lit2Var( Gia_ManObj(p, iRepr)->Value ); + Res = Cec4_ManMarkIndependentClasses_rec( pNew, iObjNew ); + assert( Res == 1 ); + Gia_ObjSetTravIdPreviousId( pNew, iObjNew ); + p->pReprs[iRepr].fColorA = 1; + Gia_ClassForEachObj1( p, iRepr, iObj ) + { + assert( p->pReprs[iObj].iRepr == (unsigned)iRepr ); + iObjNew = Abc_Lit2Var( Gia_ManObj(p, iObj)->Value ); + if ( Cec4_ManMarkIndependentClasses_rec( pNew, iObjNew ) ) + { + p->pReprs[iObj].fColorA = 1; + fHaveChoices = 1; + } + Gia_ObjSetTravIdPreviousId( pNew, iObjNew ); + } + } + return fHaveChoices; +} +int Cec4_ManSatSolverAnd_rec( Gia_Man_t * pCho, Gia_Man_t * p, Gia_Man_t * pNew, int iObj ) +{ + return 0; +} +int Cec4_ManSatSolverChoices_rec( Gia_Man_t * pCho, Gia_Man_t * p, Gia_Man_t * pNew, int iObj ) +{ + if ( !Gia_ObjIsClass(p, iObj) ) + return Cec4_ManSatSolverAnd_rec( pCho, p, pNew, iObj ); + else + { + Vec_Int_t * vLits = Vec_IntAlloc( 100 ); + int i, iHead, iNext, iRepr = Gia_ObjIsHead(p, iObj) ? iObj : Gia_ObjRepr(p, iObj); + Gia_ClassForEachObj( p, iRepr, iObj ) + if ( p->pReprs[iObj].fColorA ) + Vec_IntPush( vLits, Cec4_ManSatSolverAnd_rec( pCho, p, pNew, iObj ) ); + Vec_IntSort( vLits, 1 ); + iHead = Abc_Lit2Var( Vec_IntEntry(vLits, 0) ); + if ( Vec_IntSize(vLits) > 1 ) + { + Vec_IntForEachEntryStart( vLits, iNext, i, 1 ) + { + pCho->pSibls[iHead] = Abc_Lit2Var(iNext); + iHead = Abc_Lit2Var(iNext); + } + } + return Abc_LitNotCond( Vec_IntEntry(vLits, 0), Gia_ManObj(p, iHead)->fPhase ); + } +} +Gia_Man_t * Cec4_ManSatSolverChoices( Gia_Man_t * p, Gia_Man_t * pNew ) +{ + Gia_Man_t * pCho; + Gia_Obj_t * pObj; + int i, DriverId; + // mark topologically dependent equivalent nodes + if ( !Cec4_ManMarkIndependentClasses( p, pNew ) ) + return Gia_ManDup( pNew ); + // rebuild AIG in a different order with choices + pCho = Gia_ManStart( Gia_ManObjNum(pNew) ); + pCho->pName = Abc_UtilStrsav( p->pName ); + pCho->pSpec = Abc_UtilStrsav( p->pSpec ); + pCho->pSibls = ABC_CALLOC( int, Gia_ManObjNum(pNew) ); + Gia_ManFillValue(pNew); + Gia_ManConst0(pNew)->Value = 0; + for ( i = 0; i < Gia_ManCiNum(pNew); i++ ) + Gia_ManCi(pNew, i)->Value = Gia_ManAppendCi( pCho ); + Gia_ManForEachCoDriverId( p, DriverId, i ) + Cec4_ManSatSolverChoices_rec( pCho, p, pNew, DriverId ); + Gia_ManForEachCo( pNew, pObj, i ) + pObj->Value = Gia_ManAppendCo( pCho, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pCho, Gia_ManRegNum(p) ); + return pCho; +} + +/**Function************************************************************* + + Synopsis [Converting AIG after SAT sweeping into AIG with choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCombSpecReduce( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pRepr; int i, iLit; + Vec_Int_t * vXors = Vec_IntAlloc( 100 ); + Gia_Man_t * pTemp, * pNew = Gia_ManStart( Gia_ManObjNum(p) ); + assert( p->pReprs && p->pNexts ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManLevelNum(p); + Gia_ManSetPhase(p); + 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 ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + pRepr = Gia_ObjReprObj( p, i ); + if ( pRepr && Abc_Lit2Var(pObj->Value) != Abc_Lit2Var(pRepr->Value) ) + { + //if ( Gia_ObjLevel(p, pRepr) > Gia_ObjLevel(p, pObj) + 50 ) + //printf( "%d %d ", Gia_ObjLevel(p, pRepr), Gia_ObjLevel(p, pObj) ); + iLit = Abc_LitNotCond( pRepr->Value, pObj->fPhase ^ pRepr->fPhase ); + Vec_IntPush( vXors, Gia_ManHashXor( pNew, pObj->Value, iLit ) ); + pObj->Value = iLit; + } + } + Gia_ManHashStop( pNew ); + if ( Vec_IntSize(vXors) == 0 ) + Vec_IntPush( vXors, 0 ); + Vec_IntForEachEntry( vXors, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + Vec_IntFree( vXors ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +void Gia_ManCombSpecReduceTest( Gia_Man_t * p, char * pFileName ) +{ + Gia_Man_t * pSrm = Gia_ManCombSpecReduce( p ); + if ( pFileName == NULL ) + pFileName = "test.aig"; + Gia_AigerWrite( pSrm, pFileName, 0, 0, 0 ); + Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", pFileName ); + Gia_ManStop( pSrm ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaFanout.c b/src/aig/gia/giaFanout.c index 44e79ba2..8b104e9b 100644 --- a/src/aig/gia/giaFanout.c +++ b/src/aig/gia/giaFanout.c @@ -283,6 +283,89 @@ void Gia_ManStaticFanoutStart( Gia_Man_t * p ) Vec_IntFree( vCounts ); } + +/**Function************************************************************* + + Synopsis [Compute the map of all edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManStartMappingFanoutMap( Gia_Man_t * p, Vec_Int_t * vFanoutNums ) +{ + Gia_Obj_t * pObj; + int i, iOffset = Gia_ManObjNum(p); + Vec_Int_t * vEdgeMap = Vec_IntAlloc( 2 * iOffset ); + Vec_IntFill( vEdgeMap, iOffset, 0 ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( Vec_IntEntry(vFanoutNums, i) == 0 ) + continue; + Vec_IntWriteEntry( vEdgeMap, i, iOffset ); + iOffset += Vec_IntEntry( vFanoutNums, i ); + Vec_IntFillExtra( vEdgeMap, iOffset, 0 ); + } + //printf( "Fanout map is %.2fx larger than AIG manager.\n", 1.0*Vec_IntSize(vEdgeMap)/Gia_ManObjNum(p) ); + return vEdgeMap; +} + +/**Function************************************************************* + + Synopsis [Allocates static fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManStaticMappingFanoutStart( Gia_Man_t * p ) +{ + Vec_Int_t * vCounts; + int * pRefsOld; + Gia_Obj_t * pObj, * pFanin; + int i, k, iFan, iFanout; + assert( p->vFanoutNums == NULL ); + assert( p->vFanout == NULL ); + // recompute reference counters + pRefsOld = p->pLutRefs; p->pLutRefs = NULL; + Gia_ManSetLutRefs(p); + p->vFanoutNums = Vec_IntAllocArray( p->pLutRefs, Gia_ManObjNum(p) ); + p->pLutRefs = pRefsOld; + // start the fanout maps + p->vFanout = Gia_ManStartMappingFanoutMap( p, p->vFanoutNums ); + // incrementally add fanouts + vCounts = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManForEachLut( p, i ) + { + pObj = Gia_ManObj( p, i ); + Gia_LutForEachFanin( p, i, iFan, k ) + { + pFanin = Gia_ManObj( p, iFan ); + iFanout = Vec_IntEntry( vCounts, iFan ); + Gia_ObjSetFanout( p, pFanin, iFanout, pObj ); + Vec_IntAddToEntry( vCounts, iFan, 1 ); + } + } + Gia_ManForEachCo( p, pObj, i ) + { + iFan = Gia_ObjFaninId0p(p, pObj); + pFanin = Gia_ManObj( p, iFan ); + iFanout = Vec_IntEntry( vCounts, iFan ); + Gia_ObjSetFanout( p, pFanin, iFanout, pObj ); + Vec_IntAddToEntry( vCounts, iFan, 1 ); + } + // double-check the current number of fanouts added + Gia_ManForEachObj( p, pObj, i ) + assert( Vec_IntEntry(vCounts, i) == Gia_ObjFanoutNum(p, pObj) ); + Vec_IntFree( vCounts ); +} + /**Function************************************************************* Synopsis [Deallocates static fanout.] diff --git a/src/aig/gia/giaFx.c b/src/aig/gia/giaFx.c index c6eae6c7..032ae5fc 100644 --- a/src/aig/gia/giaFx.c +++ b/src/aig/gia/giaFx.c @@ -460,7 +460,11 @@ Gia_Man_t * Gia_ManPerformFx( Gia_Man_t * p, int nNewNodesMax, int LitCountMax, Vec_Wec_t * vCubes; Vec_Str_t * vCompl; if ( Gia_ManAndNum(p) == 0 ) - return Gia_ManDup(p); + { + pNew = Gia_ManDup(p); + Gia_ManTransferTiming( pNew, p ); + return pNew; + } // abctime clk; assert( Gia_ManHasMapping(p) ); // collect information diff --git a/src/aig/gia/giaGen.c b/src/aig/gia/giaGen.c index 94d561cc..cb56ef64 100644 --- a/src/aig/gia/giaGen.c +++ b/src/aig/gia/giaGen.c @@ -20,6 +20,7 @@ #include "gia.h" #include "misc/util/utilTruth.h" +#include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START @@ -35,6 +36,64 @@ ABC_NAMESPACE_IMPL_START /**Function************************************************************* + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_DeriveAig( Vec_Wrd_t * vSims, Vec_Str_t * vSimsOut ) +{ + int nInputs = 32*32*24; + int nWords = nInputs/64; + int nExamps = 64; + int i, e, iLitOut[10] = {0}; + Gia_Man_t * pNew; + assert( Vec_WrdSize(vSims) % nInputs == 0 ); + pNew = Gia_ManStart( nInputs * nExamps + 10000 ); + for ( i = 0; i < nInputs; i++ ) + Gia_ManAppendCi( pNew ); + Gia_ManHashStart( pNew ); + for ( e = 0; e < nExamps; e++ ) + { + int Class = Vec_StrEntry( vSimsOut, e ); + int This = 1; + word * pSim = Vec_WrdEntryP( vSims, e*nWords ); + for ( i = 0; i < nInputs; i++ ) + This = Gia_ManHashAnd( pNew, This, Abc_Var2Lit(i+1, !Abc_TtGetBit(pSim, i)) ); + assert( Class >= 0 && Class <= 9 ); + iLitOut[Class] = Gia_ManHashOr( pNew, iLitOut[Class], This ); + //printf( "Finished example %d\n", e ); + } + for ( i = 0; i < 10; i++ ) + Gia_ManAppendCo( pNew, iLitOut[i] ); + //pNew = Gia_ManCleanup( pTemp = pNew ); + //Gia_ManStop( pTemp ); + return pNew; +} +void Gia_DeriveAigTest() +{ + extern int Gia_ManReadCifar10File( char * pFileName, Vec_Wrd_t ** pvSimsIn, Vec_Str_t ** pvSimsOut, int * pnExamples ); + char pFileName[100] = "test"; + Vec_Wrd_t * vSimsIn; + Vec_Str_t * vSimsOut; + int nExamples = 0; + int nInputs = Gia_ManReadCifar10File( pFileName, &vSimsIn, &vSimsOut, &nExamples ); + Gia_Man_t * pThis = Gia_DeriveAig( vSimsIn, vSimsOut ); + Gia_AigerWrite( pThis, "examples64.aig", 0, 0, 0 ); + printf( "Dumped file \"%s\".\n", "examples64.aig" ); + Gia_ManStop( pThis ); + Vec_WrdFree( vSimsIn ); + Vec_StrFree( vSimsOut ); + nInputs = 0; +} + + +/**Function************************************************************* + Synopsis [Populate internal simulation info.] Description [] @@ -136,6 +195,38 @@ int Gia_ManSimulateWordsInit( Gia_Man_t * p, Vec_Wrd_t * vSimsIn ) return 1; } +Vec_Wrd_t * Gia_ManSimulateWordsOut( Gia_Man_t * p, Vec_Wrd_t * vSimsIn ) +{ + Gia_Obj_t * pObj; int i, Id; + int nWords = Vec_WrdSize(vSimsIn) / Gia_ManCiNum(p); + Vec_Wrd_t * vSimsOut = Vec_WrdStart( nWords * Gia_ManCoNum(p) ); + assert( Vec_WrdSize(vSimsIn) == nWords * Gia_ManCiNum(p) ); + // allocate simulation info for one timeframe + Vec_WrdFreeP( &p->vSims ); + p->vSims = Vec_WrdStart( Gia_ManObjNum(p) * nWords ); + p->nSimWords = nWords; + // set input sim info + Gia_ManForEachCiId( p, Id, i ) + memcpy( Vec_WrdEntryP(p->vSims, Id*nWords), Vec_WrdEntryP(vSimsIn, i*nWords), sizeof(word)*nWords ); + // perform simulation + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + Gia_ManObjSimAnd( p, i ); + else if ( Gia_ObjIsCi(pObj) ) + continue; + else if ( Gia_ObjIsCo(pObj) ) + Gia_ManObjSimPo( p, i ); + else assert( 0 ); + } + // set output sim info + Gia_ManForEachCoId( p, Id, i ) + memcpy( Vec_WrdEntryP(vSimsOut, i*nWords), Vec_WrdEntryP(p->vSims, Id*nWords), sizeof(word)*nWords ); + Vec_WrdFreeP( &p->vSims ); + p->nSimWords = -1; + return vSimsOut; +} + /**Function************************************************************* Synopsis [Dump data files.] @@ -443,6 +534,224 @@ void Gia_ManCompareValues( Gia_Man_t * p, Vec_Wrd_t * vSimsIn, Vec_Int_t * vValu SeeAlso [] ***********************************************************************/ +void Gia_ManReadSimFile( char * pFileName, int * pnIns, int * pnOuts, int * pnPats, Vec_Wrd_t ** pvSimsIn, Vec_Wrd_t ** pvSimsOut ) +{ + char * pTemp, pBuffer[1000]; + Vec_Wrd_t * vSimsIn = NULL, * vSimsOut = NULL; + int i, iPat = 0, nWordsI, nWordsO, nIns = -1, nOuts = -1, nPats = -1; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return; + } + while ( fgets( pBuffer, 1000, pFile ) != NULL ) + { + pTemp = pBuffer; + if ( pTemp[0] == '\0' || pTemp[0] == '#' || pTemp[0] == ' ' ) + continue; + if ( pTemp[0] != '.' ) + break; + if ( pTemp[1] == 'i' ) + nIns = atoi(pTemp+2); + else if ( pTemp[1] == 'o' ) + nOuts = atoi(pTemp+2); + else if ( pTemp[1] == 'p' ) + { + if ( atoi(pTemp+2) % 64 == 0 ) + printf( "Expecting the number of patterns divisible by 64.\n" ); + nPats = atoi(pTemp+2) / 64; + } + } + if ( nIns == -1 || nOuts == -1 || nPats == -1 ) + { + printf( "Some of the parameters (inputs, outputs, patterns) is not specified.\n" ); + fclose( pFile ); + return; + } + nWordsI = (nIns + 63) / 64; + nWordsO = (nOuts + 63) / 64; + + vSimsIn = Vec_WrdStart( nPats * nWordsI ); + vSimsOut = Vec_WrdStart( nPats * nWordsO ); + rewind(pFile); + while ( fgets( pBuffer, 1000, pFile ) != NULL ) + { + if ( pTemp[0] == '\0' || pTemp[0] == '.' ) + continue; + for ( i = 0, pTemp = pBuffer; *pTemp != '\n'; pTemp++ ) + if ( *pTemp == '0' || *pTemp == '1' ) + { + if ( *pTemp == '1' ) + { + if ( i < nIns ) + Abc_TtSetBit( Vec_WrdEntryP(vSimsIn, nWordsI*iPat), i ); + else + Abc_TtSetBit( Vec_WrdEntryP(vSimsOut, nWordsO*iPat), i-nIns ); + } + i++; + } + iPat++; + } + if ( iPat != nPats ) + printf( "The number of patterns does not match.\n" ); + fclose( pFile ); + *pnIns = nIns; + *pnOuts = nOuts; + *pnPats = nPats; + *pvSimsIn = vSimsIn; + *pvSimsOut = vSimsOut; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManReadBinaryFile( char * pFileName, Vec_Wrd_t ** pvSimsIn, Vec_Str_t ** pvSimsOut ) +{ + extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + int nFileSize = Extra_FileSize( pFileName ); + int nExamples = 1 << 16; + int nInputs = nFileSize / nExamples - 1; + int nWords = (8*nInputs + 63)/64, i; + char * pContents = Extra_FileReadContents( pFileName ); + Vec_Wrd_t * vSimsIn = Vec_WrdStart( nExamples * nWords ); + Vec_Wrd_t * vSimsIn2 = Vec_WrdStart( nExamples * nWords ); + Vec_Str_t * vSimsOut = Vec_StrAlloc( nExamples ); + assert( nFileSize % nExamples == 0 ); + for ( i = 0; i < nExamples; i++ ) + { + memcpy( (void *)Vec_WrdEntryP(vSimsIn, i*nWords), (void *)(pContents + i*(nInputs+1)), nInputs ); + Vec_StrPush( vSimsOut, pContents[i*(nInputs+1) + nInputs] ); + } + Extra_BitMatrixTransposeP( vSimsIn, nWords, vSimsIn2, nExamples/64 ); + Vec_WrdShrink( vSimsIn2, 8*nInputs * nExamples/64 ); + Vec_WrdFree( vSimsIn ); + *pvSimsIn = vSimsIn2; + *pvSimsOut = vSimsOut; + ABC_FREE( pContents ); + return nInputs; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimLogStats2( Gia_Man_t * p, char * pDumpFile, int Total, int nPositives, float ErrorTotal, float GuessTotal ) +{ + FILE * pTable = fopen( pDumpFile, "wb" ); + fprintf( pTable, "{\n" ); + fprintf( pTable, " \"name\" : \"%s\",\n", p->pName ); + fprintf( pTable, " \"input\" : %d,\n", Gia_ManCiNum(p) ); + fprintf( pTable, " \"output\" : %d,\n", Gia_ManCoNum(p) ); + fprintf( pTable, " \"and\" : %d,\n", Gia_ManAndNum(p) ); + fprintf( pTable, " \"level\" : %d,\n", Gia_ManLevelNum(p) ); + fprintf( pTable, " \"total\" : %d,\n", Total ); + fprintf( pTable, " \"positive\" : %d,\n", nPositives ); + fprintf( pTable, " \"error\" : %e,\n", ErrorTotal ); + fprintf( pTable, " \"guess\" : %e\n", GuessTotal ); + fprintf( pTable, "}\n" ); + fclose( pTable ); +} +int Gia_ManGetExampleValue( word ** ppSims, int nSims, int iExample ) +{ + int o, Sign = 0, ValueSim = 0; + for ( o = 0; o < nSims; o++ ) + if ( (Sign = Abc_TtGetBit(ppSims[o], iExample)) ) + ValueSim |= (1 << o); + if ( Sign ) + ValueSim |= ~0 << nSims; + return ValueSim; +} +void Gia_ManCompareValues2( int nInputs, Gia_Man_t * p, Vec_Wrd_t * vSimsIn, Vec_Str_t * vValues, char * pDumpFile ) +{ + float Error1, ErrorTotal = 0, Guess1, GuessTotal = 0; + int i, o, nPositives = 0, nWords = Vec_WrdSize(vSimsIn) / Gia_ManCiNum(p); + word ** ppSims = ABC_CALLOC( word *, Gia_ManCoNum(p) ); + Gia_Obj_t * pObj; + assert( nWords == (1<<10) ); + assert( Vec_WrdSize(vSimsIn) % Gia_ManCiNum(p) == 0 ); + assert( Vec_StrSize(vValues) == (1 << 16) ); + assert( nWords*64 == (1 << 16) ); + // simulate examples given in vSimsIn + Gia_ManSimulateWordsInit( p, vSimsIn ); + // collect simulation info for the outputs + assert( p->nSimWords == nWords ); + Gia_ManForEachCo( p, pObj, o ) + ppSims[o] = Gia_ManObjSim( p, Gia_ObjId(p, pObj) ); + // compare the output for each example + for ( i = 0; i < nWords*64; i++ ) + { + int ValueGold = (int)Vec_StrEntry( vValues, i ); + int ValueImpl = Gia_ManGetExampleValue( ppSims, Gia_ManCoNum(p), i ); + // compute error for this example + Error1 = (float)(ValueGold - ValueImpl)/256; + ErrorTotal += Error1 * Error1; + // compute error of zero-output + Guess1 = ValueGold > 0 ? Abc_AbsInt(ValueImpl) : 0; + GuessTotal += Guess1 * Guess1; + // count positive values (disregard negative values due to Leaky ReLU) + nPositives += (int)(ValueGold > 0); + } + ABC_FREE( ppSims ); + printf( "Total = %6d. Positive = %6d. (%6.2f %%) Errors = %e. Guess = %e. (%6.2f %%)\n", + Vec_StrSize(vValues), nPositives, 100.0*nPositives/Vec_StrSize(vValues), + ErrorTotal, GuessTotal, 100.0*ErrorTotal/GuessTotal ); + if ( pDumpFile == NULL ) + return; + Gia_ManSimLogStats2( p, pDumpFile, Vec_StrSize(vValues), nPositives, ErrorTotal, GuessTotal ); + printf( "Finished dumping statistics into file \"%s\".\n", pDumpFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTestWordFileUnused( Gia_Man_t * p, char * pFileName, char * pDumpFile ) +{ + Vec_Wrd_t * vSimsIn; + Vec_Str_t * vSimsOut; + int nInputs = Gia_ManReadBinaryFile( pFileName, &vSimsIn, &vSimsOut ); + if ( Gia_ManCiNum(p) == 8*nInputs ) + Gia_ManCompareValues2( nInputs, p, vSimsIn, vSimsOut, pDumpFile ); + else + printf( "The number of inputs in the AIG (%d) and in the file (%d) does not match.\n", Gia_ManCiNum(p), 8*nInputs ); + Vec_WrdFree( vSimsIn ); + Vec_StrFree( vSimsOut ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ void Gia_ManTestOneFile( Gia_Man_t * p, char * pFileName, char * pDumpFile ) { Vec_Wrd_t * vSimsIn; @@ -463,6 +772,158 @@ void Gia_ManTestOneFile( Gia_Man_t * p, char * pFileName, char * pDumpFile ) Vec_IntFree( vValues ); } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManReadCifar10File( char * pFileName, Vec_Wrd_t ** pvSimsIn, Vec_Str_t ** pvSimsOut, int * pnExamples ) +{ + int nPixels = 32*32*3; + int nFileSize = Extra_FileSize( pFileName ); + int nExamples = nFileSize / (nPixels + 1); + int nWordsIn = nPixels / 8; + int nWordsOut = (nExamples + 63) / 64; int e; + if ( nFileSize % (nPixels + 1) ) + { + printf( "The input file \"%s\" with image data does not appear to be in CIFAR10 format.\n", pFileName ); + return 0; + } + else + { + Vec_Wrd_t * vSimsIn = Vec_WrdStart( 64 * nWordsOut * nWordsIn ); + Vec_Str_t * vSimsOut = Vec_StrAlloc( 64 * nWordsOut ); + unsigned char * pBuffer = ABC_ALLOC( unsigned char, nFileSize ); + FILE * pFile = fopen( pFileName, "rb" ); + int Value = fread( pBuffer, 1, nFileSize, pFile ); + fclose( pFile ); + assert( Value == nFileSize ); + printf( "Successfully read %5.2f MB (%d images) from file \"%s\".\n", (float)nFileSize/(1<<20), nExamples, pFileName ); + for ( e = 0; e < nExamples; e++ ) + { + Vec_StrPush( vSimsOut, (char)pBuffer[e*(nPixels + 1)] ); + memcpy( Vec_WrdEntryP(vSimsIn, e*nWordsIn), pBuffer + e*(nPixels + 1) + 1, nPixels ); + } + ABC_FREE( pBuffer ); + for ( ; e < 64 * nWordsOut; e++ ) + Vec_StrPush( vSimsOut, (char)0 ); + memset( Vec_WrdEntryP(vSimsIn, nExamples*nWordsIn), 0, (64*nWordsOut - nExamples)*nWordsIn ); + *pvSimsIn = vSimsIn; + *pvSimsOut = vSimsOut; + *pnExamples = nExamples; + return 8*nPixels; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSimulateBatch( Gia_Man_t * p, Vec_Wrd_t * vSimsIn, Vec_Str_t * vSimsOut, Vec_Str_t * vSimsOut2, int b, int Limit ) +{ + Gia_Obj_t * pObj; + word * ppSims[10]; + int i, o, Count = 0; + assert( Gia_ManCiNum(p) == Vec_WrdSize(vSimsIn) ); + assert( Gia_ManCoNum(p) == 10 ); + Gia_ManSimulateWordsInit( p, vSimsIn ); + Gia_ManForEachCo( p, pObj, o ) + ppSims[o] = Gia_ManObjSim( p, Gia_ObjId(p, pObj) ); + for ( i = 0; i < Limit; i++ ) + { + int Value = 0; + for ( o = 0; o < 10; o++ ) + if ( Abc_TtGetBit(ppSims[o], i) ) + { + Value = o; + break; + } + Vec_StrPush( vSimsOut, (char)Value ); + Count += Value == (int)Vec_StrEntry( vSimsOut2, 64*b+i ); + } + return Count; +} +Vec_Str_t * Gia_ManSimulateAll( Gia_Man_t * p, Vec_Wrd_t * vSimsIn, Vec_Str_t * vSimsOut, int nExamples, int fVerbose ) +{ + extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + Vec_Str_t * vRes = Vec_StrAlloc( 100 ); int b, Count; + int nWordsIn = 32*32*24/64; // one image + int nWordsOut = Vec_WrdSize(vSimsIn)/(nWordsIn*64); + assert( Vec_WrdSize(vSimsIn) % nWordsIn == 0 ); + for ( b = 0; b < nWordsOut; b++ ) + { + int Limit = b == nWordsOut-1 ? nExamples-b*64 : 64; + Vec_Wrd_t * vSimsIn1 = Vec_WrdStart( nWordsIn*64 ); + Vec_Wrd_t * vSimsIn2 = Vec_WrdStart( nWordsIn*64 ); + memcpy( Vec_WrdArray(vSimsIn1), Vec_WrdEntryP(vSimsIn, b*nWordsIn*64), sizeof(word)*nWordsIn*64 ); + Extra_BitMatrixTransposeP( vSimsIn1, nWordsIn, vSimsIn2, 1 ); + Vec_WrdFree( vSimsIn1 ); + Count = Gia_ManSimulateBatch( p, vSimsIn2, vRes, vSimsOut, b, Limit ); + Vec_WrdFree( vSimsIn2 ); + if ( fVerbose ) + printf( "Finished simulating word %4d (out of %4d). Correct = %2d. (Limit = %2d.)\n", b, nWordsOut, Count, Limit ); + } + assert( Vec_StrSize(vRes) == nExamples ); + return vRes; +} +void Gia_ManCompareCifar10Values( Gia_Man_t * p, Vec_Str_t * vRes, Vec_Str_t * vSimsOut, char * pDumpFile, int nExamples ) +{ + int i, Guess = (nExamples+9)/10, Count = 0; + for ( i = 0; i < nExamples; i++ ) + { + char ValueReal = Vec_StrEntry(vRes, i); + char ValueGold = Vec_StrEntry(vSimsOut, i); + if ( ValueReal == ValueGold ) + Count++; + } + printf( "Summary: Total = %6d. Errors = %6d. Correct = %6d. (%6.2f %%) Naive guess = %6d. (%6.2f %%)\n", + nExamples, nExamples - Count, + Count, 100.0*Count/nExamples, + Guess, 100.0*Guess/nExamples); + if ( pDumpFile == NULL ) + return; + Gia_ManSimLogStats( p, pDumpFile, nExamples, Count, Guess ); + printf( "Finished dumping statistics into file \"%s\".\n", pDumpFile ); +} +void Gia_ManTestWordFile( Gia_Man_t * p, char * pFileName, char * pDumpFile, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Vec_Wrd_t * vSimsIn; + Vec_Str_t * vSimsOut; + int i, nExamples = 0; + int nInputs = Gia_ManReadCifar10File( pFileName, &vSimsIn, &vSimsOut, &nExamples ); + char * pKnownFileNames[3] = {"small.aig", "medium.aig", "large.aig"}; + int pLimitFileSizes[3] = {10000, 100000, 1000000}; + for ( i = 0; i < 3; i++ ) + if ( p->pSpec && !strncmp(p->pSpec, pKnownFileNames[i], 5) && Gia_ManAndNum(p) > pLimitFileSizes[i] ) + printf( "Warning: The input file \"%s\" contains more than %d internal and-nodes.\n", pKnownFileNames[i], pLimitFileSizes[i] ); + if ( nInputs == Gia_ManCiNum(p) ) + { + Vec_Str_t * vRes = Gia_ManSimulateAll( p, vSimsIn, vSimsOut, nExamples, fVerbose ); + Gia_ManCompareCifar10Values( p, vRes, vSimsOut, pDumpFile, nExamples ); + Vec_StrFree( vRes ); + } + else + printf( "The primary input counts in the AIG (%d) and in the image data (%d) do not match.\n", Gia_ManCiNum(p), nInputs ); + Vec_WrdFree( vSimsIn ); + Vec_StrFree( vSimsOut ); + Abc_PrintTime( 1, "Total checking time", Abc_Clock() - clk ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaHash.c b/src/aig/gia/giaHash.c index 64e39613..063cfd31 100644 --- a/src/aig/gia/giaHash.c +++ b/src/aig/gia/giaHash.c @@ -814,6 +814,328 @@ int Gia_ManHashDualMiter( Gia_Man_t * p, Vec_Int_t * vOuts ) return iRes; } + + +/**Function************************************************************* + + Synopsis [Create multi-input tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Gia_ManCollectLiterals( int nVars ) +{ + int i, * pRes = ABC_CALLOC( int, nVars ); + for ( i = 0; i < nVars; i++ ) + pRes[i] = Abc_Var2Lit( i+1, 0 ); + return pRes; +} +int * Gia_ManGenZero( int nBits ) +{ + return ABC_CALLOC( int, nBits ); +} +int * Gia_ManGenPerm( int nBits ) +{ + int i, * pRes = ABC_CALLOC( int, nBits ); + srand( time(NULL) ); + for ( i = 0; i < nBits; i++ ) + pRes[i] = i; + for ( i = 0; i < nBits; i++ ) + { + int iPerm = rand() % nBits; + ABC_SWAP( int, pRes[i], pRes[iPerm] ); + } + return pRes; +} +int * Gia_ManGenPerm2( int nBits ) +{ + int i, * pRes = ABC_CALLOC( int, nBits ); + srand( time(NULL) ); + for ( i = 0; i < nBits; i++ ) + pRes[i] = rand() % nBits; + return pRes; +} +int Gia_ManMultiCheck( int * pPerm, int nPerm ) +{ + int i; + for ( i = 1; i < nPerm; i++ ) + if ( pPerm[i-1] <= pPerm[i] ) + return 0; + return 1; +} +int Gia_ManMultiInputPerm( Gia_Man_t * pNew, int * pVars, int nVars, int * pPerm, int fOr, int fXor ) +{ + int fPrint = 1; + int i, iLit; + if ( fPrint ) + { + for ( i = 0; i < nVars; i++ ) + printf( "%d ", pPerm[i] ); + printf( "\n" ); + } + while ( 1 ) + { + for ( i = 1; i < nVars; i++ ) + if ( pPerm[i-1] >= pPerm[i] ) + break; + if ( i == nVars ) + break; + assert( pPerm[i-1] >= pPerm[i] ); + if ( pPerm[i-1] > pPerm[i] ) + { + ABC_SWAP( int, pPerm[i-1], pPerm[i] ); + ABC_SWAP( int, pVars[i-1], pVars[i] ); + } + else + { + assert( pPerm[i-1] == pPerm[i] ); + pPerm[i-1]++; + if ( fXor ) + pVars[i-1] = Gia_ManHashXor( pNew, pVars[i-1], pVars[i] ); + else if ( fOr ) + pVars[i-1] = Gia_ManHashOr( pNew, pVars[i-1], pVars[i] ); + else + pVars[i-1] = Gia_ManHashAnd( pNew, pVars[i-1], pVars[i] ); + for ( i = i+1; i < nVars; i++ ) + { + pPerm[i-1] = pPerm[i]; + pVars[i-1] = pVars[i]; + } + nVars--; + } + if ( fPrint ) + { + for ( i = 0; i < nVars; i++ ) + printf( "%d ", pPerm[i] ); + printf( "\n" ); + } + } + iLit = pVars[0]; + for ( i = 1; i < nVars; i++ ) + if ( fXor ) + iLit = Gia_ManHashXor( pNew, iLit, pVars[i] ); + else if ( fOr ) + iLit = Gia_ManHashOr( pNew, iLit, pVars[i] ); + else + iLit = Gia_ManHashAnd( pNew, iLit, pVars[i] ); + return iLit; +} +Gia_Man_t * Gia_ManMultiInputTest( int nBits ) +{ + Gia_Man_t * pNew; + int i, iRes, * pPerm; + int * pMulti = Gia_ManCollectLiterals( nBits ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "multi" ); + for ( i = 0; i < nBits; i++ ) + Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + pPerm = Gia_ManGenPerm2( nBits ); + //pPerm = Gia_ManGenZero( nBits ); + iRes = Gia_ManMultiInputPerm( pNew, pMulti, nBits, pPerm, 0, 0 ); + Gia_ManAppendCo( pNew, iRes ); + ABC_FREE( pPerm ); + ABC_FREE( pMulti ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Create MUX tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCube( Gia_Man_t * pNew, int Vars, int nVars, int * pLits ) +{ + int i, iLit = 1; + for ( i = 0; i < nVars; i++ ) + iLit = Gia_ManHashAnd( pNew, iLit, Abc_LitNotCond(pLits[i], !((Vars >> i) & 1)) ); + return iLit; +} +int Gia_ManMuxTree_rec( Gia_Man_t * pNew, int * pCtrl, int nCtrl, int * pData ) +{ + int iLit0, iLit1; + if ( nCtrl == 0 ) + return pData[0]; + iLit0 = Gia_ManMuxTree_rec( pNew, pCtrl, nCtrl-1, pData ); + iLit1 = Gia_ManMuxTree_rec( pNew, pCtrl, nCtrl-1, pData + (1<<(nCtrl-1)) ); + return Gia_ManHashMux( pNew, pCtrl[nCtrl-1], iLit1, iLit0 ); +} +void Gia_ManUsePerm( int * pTree, int nBits, int * pPerm ) +{ + int fPrint = 0; + int i, k, m, nVars = nBits + (1 << nBits); + if ( fPrint ) + { + for ( i = 0; i < nVars; i++ ) + printf( "%d ", pPerm[i] ); + printf( "\n" ); + } + for ( i = 0; i < nBits; i++ ) + { + for ( k = i+1; k < nBits; k++ ) + if ( pPerm[i] > pPerm[k] ) + break; + if ( k == nBits ) + break; + assert( pPerm[i] > pPerm[k] ); + ABC_SWAP( int, pPerm[i], pPerm[k] ); + ABC_SWAP( int, pTree[i], pTree[k] ); + for ( m = 0; m < (1 << nBits); m++ ) + if ( ((m >> i) & 1) && !((m >> k) & 1) ) + { + ABC_SWAP( int, pTree[nBits+m], pTree[nBits+(m^(1<<i)^(1<<k))] ); + ABC_SWAP( int, pPerm[nBits+m], pPerm[nBits+(m^(1<<i)^(1<<k))] ); + } + } + if ( fPrint ) + { + for ( i = 0; i < nVars; i++ ) + printf( "%d ", pPerm[i] ); + printf( "\n" ); + } +} +int Gia_ManFindCond( int * pLits, int nBits, int iLate1, int iLate2 ) +{ + int i; + assert( iLate1 != iLate2 ); + for ( i = 0; i < nBits; i++ ) + if ( (((iLate1 ^ iLate2) >> i) & 1) ) + return Abc_LitNotCond( pLits[i], (iLate1 >> i) & 1 ); + return -1; +} +int Gia_ManLatest( int * pPerm, int nVars, int iPrev1, int iPrev2, int iPrev3 ) +{ + int i, Value = -1, iLate = -1; + for ( i = 0; i < nVars; i++ ) + if ( Value < pPerm[i] && i != iPrev1 && i != iPrev2 && i != iPrev3 ) + { + Value = pPerm[i]; + iLate = i; + } + return iLate; +} +int Gia_ManEarliest( int * pPerm, int nVars ) +{ + int i, Value = ABC_INFINITY, iLate = -1; + for ( i = 0; i < nVars; i++ ) + if ( Value > pPerm[i] ) + { + Value = pPerm[i]; + iLate = i; + } + return iLate; +} +int Gia_ManDecompOne( Gia_Man_t * pNew, int * pTree, int nBits, int * pPerm, int iLate ) +{ + int iRes, iData; + assert( iLate >= 0 && iLate < (1<<nBits) ); + iData = pTree[nBits+iLate]; + pTree[nBits+iLate] = pTree[nBits+(iLate^1)]; + iRes = Gia_ManMuxTree_rec( pNew, pTree, nBits, pTree+nBits ); + return Gia_ManHashMux( pNew, Gia_ManCube(pNew, iLate, nBits, pTree), iData, iRes ); +} +int Gia_ManDecompTwo( Gia_Man_t * pNew, int * pTree, int nBits, int * pPerm, int iLate1, int iLate2 ) +{ + int iRes, iData1, iData2, iData, iCond, iCond2; + assert( iLate1 != iLate2 ); + assert( iLate1 >= 0 && iLate1 < (1<<nBits) ); + assert( iLate2 >= 0 && iLate2 < (1<<nBits) ); + iData1 = pTree[nBits+iLate1]; + iData2 = pTree[nBits+iLate2]; + pTree[nBits+iLate1] = pTree[nBits+(iLate1^1)]; + pTree[nBits+iLate2] = pTree[nBits+(iLate2^1)]; + iRes = Gia_ManMuxTree_rec( pNew, pTree, nBits, pTree+nBits ); + iCond = Gia_ManHashOr( pNew, Gia_ManCube(pNew, iLate1, nBits, pTree), Gia_ManCube(pNew, iLate2, nBits, pTree) ); + iCond2 = Gia_ManFindCond( pTree, nBits, iLate1, iLate2 ); + iData = Gia_ManHashMux( pNew, iCond2, iData2, iData1 ); + return Gia_ManHashMux( pNew, iCond, iData, iRes ); +} +int Gia_ManDecompThree( Gia_Man_t * pNew, int * pTree, int nBits, int * pPerm, int iLate1, int iLate2, int iLate3 ) +{ + int iRes, iData1, iData2, iData3, iCube1, iCube2, iCube3, iCtrl0, iCtrl1, iMux10, iMux11; + assert( iLate1 != iLate2 ); + assert( iLate1 != iLate3 ); + assert( iLate2 != iLate3 ); + assert( iLate1 >= 0 && iLate1 < (1<<nBits) ); + assert( iLate2 >= 0 && iLate2 < (1<<nBits) ); + assert( iLate3 >= 0 && iLate3 < (1<<nBits) ); + iData1 = pTree[nBits+iLate1]; + iData2 = pTree[nBits+iLate2]; + iData3 = pTree[nBits+iLate3]; + pTree[nBits+iLate1] = pTree[nBits+(iLate1^1)]; + pTree[nBits+iLate2] = pTree[nBits+(iLate2^1)]; + pTree[nBits+iLate3] = pTree[nBits+(iLate3^1)]; + iRes = Gia_ManMuxTree_rec( pNew, pTree, nBits, pTree+nBits ); + iCube1 = Gia_ManCube( pNew, iLate1, nBits, pTree ); + iCube2 = Gia_ManCube( pNew, iLate2, nBits, pTree ); + iCube3 = Gia_ManCube( pNew, iLate3, nBits, pTree ); + iCtrl0 = Gia_ManHashOr( pNew, iCube1, iCube3 ); + iCtrl1 = Gia_ManHashOr( pNew, iCube2, iCube3 ); + iMux10 = Gia_ManHashMux( pNew, iCtrl0, iData1, iRes ); + iMux11 = Gia_ManHashMux( pNew, iCtrl0, iData3, iData2 ); + return Gia_ManHashMux( pNew, iCtrl1, iMux11, iMux10 ); +} +int Gia_ManDecomp( Gia_Man_t * pNew, int * pTree, int nBits, int * pPerm ) +{ + if ( nBits == 2 ) + return Gia_ManMuxTree_rec( pNew, pTree, nBits, pTree+nBits ); + else + { + int iBase = Gia_ManEarliest( pPerm+nBits, 1<<nBits ), BaseValue = pPerm[nBits+iBase]; + int iLate1 = Gia_ManLatest( pPerm+nBits, 1<<nBits, -1, -1, -1 ); + int iLate2 = Gia_ManLatest( pPerm+nBits, 1<<nBits, iLate1, -1, -1 ); + int iLate3 = Gia_ManLatest( pPerm+nBits, 1<<nBits, iLate1, iLate2, -1 ); + int iLate4 = Gia_ManLatest( pPerm+nBits, 1<<nBits, iLate1, iLate2, iLate3 ); + if ( 0 ) + { + int i; + for ( i = 0; i < (1<<nBits); i++ ) + printf( "%d ", pPerm[nBits+i] ); + printf( "\n" ); + } + if ( pPerm[nBits+iLate1] > BaseValue && pPerm[nBits+iLate2] > BaseValue && pPerm[nBits+iLate3] > BaseValue && pPerm[nBits+iLate4] == BaseValue ) + return Gia_ManDecompThree( pNew, pTree, nBits, pPerm, iLate1, iLate2, iLate3 ); + if ( pPerm[nBits+iLate1] > BaseValue && pPerm[nBits+iLate2] > BaseValue && pPerm[nBits+iLate3] == BaseValue ) + return Gia_ManDecompTwo( pNew, pTree, nBits, pPerm, iLate1, iLate2 ); + if ( pPerm[nBits+iLate1] > BaseValue && pPerm[nBits+iLate2] == BaseValue ) + return Gia_ManDecompOne( pNew, pTree, nBits, pPerm, iLate1 ); + return Gia_ManMuxTree_rec( pNew, pTree, nBits, pTree+nBits ); + } +} +Gia_Man_t * Gia_ManMuxTreeTest( int nBits ) +{ + Gia_Man_t * pNew; + int i, iLit, nVars = nBits + (1 << nBits); + int * pPerm, * pTree = Gia_ManCollectLiterals( nVars ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "mux_tree" ); + for ( i = 0; i < nVars; i++ ) + Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + pPerm = Gia_ManGenPerm( nVars ); + //pPerm = Gia_ManGenZero( nVars ); + pPerm[nBits+1] = 100; + pPerm[nBits+5] = 100; + pPerm[nBits+4] = 100; + Gia_ManUsePerm( pTree, nBits, pPerm ); + iLit = Gia_ManDecomp( pNew, pTree, nBits, pPerm ); + Gia_ManAppendCo( pNew, iLit ); + ABC_FREE( pPerm ); + ABC_FREE( pTree ); + return pNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaIf.c b/src/aig/gia/giaIf.c index 37ca6d4b..ae87277a 100644 --- a/src/aig/gia/giaIf.c +++ b/src/aig/gia/giaIf.c @@ -39,6 +39,8 @@ ABC_NAMESPACE_IMPL_START extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); extern int Abc_RecToGia3( Gia_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, Vec_Int_t * vLeaves, int fHash ); +extern void Gia_ManPrintGetMuxFanins( Gia_Man_t * p, Gia_Obj_t * pObj, int * pFanins ); + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -200,6 +202,7 @@ int Gia_ManLutLevel( Gia_Man_t * p, int ** ppLevels ) ***********************************************************************/ void Gia_ManLutParams( Gia_Man_t * p, int * pnCurLuts, int * pnCurEdges, int * pnCurLevels ) { + int fDisable2Lut = 1; if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t *)p->pManTime) ) { int i; @@ -219,20 +222,37 @@ void Gia_ManLutParams( Gia_Man_t * p, int * pnCurLuts, int * pnCurEdges, int * p int * pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) ); *pnCurLuts = 0; *pnCurEdges = 0; + *pnCurLevels = 0; Gia_ManForEachLut( p, i ) { - int Level = 0; + if ( Gia_ObjLutIsMux(p, i) && !(fDisable2Lut && Gia_ObjLutSize(p, i) == 2) ) + { + int pFanins[3]; + if ( Gia_ObjLutSize(p, i) == 3 ) + { + Gia_ManPrintGetMuxFanins( p, Gia_ManObj(p, i), pFanins ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[pFanins[0]]+1 ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[pFanins[1]] ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[pFanins[2]] ); + } + else if ( Gia_ObjLutSize(p, i) == 2 ) + { + pObj = Gia_ManObj( p, i ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[Gia_ObjFaninId0(pObj, i)] ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[Gia_ObjFaninId1(pObj, i)] ); + } + *pnCurLevels = Abc_MaxInt( *pnCurLevels, pLevels[i] ); + (*pnCurEdges)++; + //nMuxF++; + continue; + } (*pnCurLuts)++; (*pnCurEdges) += Gia_ObjLutSize(p, i); Gia_LutForEachFanin( p, i, iFan, k ) - if ( Level < pLevels[iFan] ) - Level = pLevels[iFan]; - pLevels[i] = Level + 1; + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[iFan] ); + pLevels[i]++; + *pnCurLevels = Abc_MaxInt( *pnCurLevels, pLevels[i] ); } - *pnCurLevels = 0; - Gia_ManForEachCo( p, pObj, k ) - if ( *pnCurLevels < pLevels[Gia_ObjFaninId0p(p, pObj)] ) - *pnCurLevels = pLevels[Gia_ObjFaninId0p(p, pObj)]; ABC_FREE( pLevels ); } } @@ -452,6 +472,7 @@ int Gia_ManCountDupLut( Gia_Man_t * p ) void Gia_ManPrintMappingStats( Gia_Man_t * p, char * pDumpFile ) { + int fDisable2Lut = 1; Gia_Obj_t * pObj; int * pLevels; int i, k, iFan, nLutSize = 0, nLuts = 0, nFanins = 0, LevelMax = 0, Ave = 0, nMuxF = 0; @@ -460,7 +481,7 @@ void Gia_ManPrintMappingStats( Gia_Man_t * p, char * pDumpFile ) pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManForEachLut( p, i ) { - if ( Gia_ObjLutIsMux(p, i) ) + if ( Gia_ObjLutIsMux(p, i) && !(fDisable2Lut && Gia_ObjLutSize(p, i) == 2) ) { int pFanins[3]; if ( Gia_ObjLutSize(p, i) == 3 ) @@ -756,6 +777,43 @@ int Gia_ManChoiceLevel( Gia_Man_t * p ) } +/**Function************************************************************* + + Synopsis [Checks integrity of choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManCheckChoices_rec( If_Man_t * pIfMan, If_Obj_t * pIfObj ) +{ + if ( !pIfObj || pIfObj->Type != IF_AND || pIfObj->fDriver ) + return; + pIfObj->fDriver = 1; + If_ManCheckChoices_rec( pIfMan, If_ObjFanin0(pIfObj) ); + If_ManCheckChoices_rec( pIfMan, If_ObjFanin1(pIfObj) ); + If_ManCheckChoices_rec( pIfMan, pIfObj->pEquiv ); +} +void If_ManCheckChoices( If_Man_t * pIfMan ) +{ + If_Obj_t * pIfObj; + int i, fFound = 0; + If_ManForEachObj( pIfMan, pIfObj, i ) + pIfObj->fDriver = 0; + If_ManForEachCo( pIfMan, pIfObj, i ) + If_ManCheckChoices_rec( pIfMan, If_ObjFanin0(pIfObj) ); + If_ManForEachNode( pIfMan, pIfObj, i ) + if ( !pIfObj->fDriver ) + printf( "Object %d is dangling.\n", i ), fFound = 1; + if ( !fFound ) + printf( "There are no dangling objects.\n" ); + If_ManForEachObj( pIfMan, pIfObj, i ) + pIfObj->fDriver = 0; +} + /**Function************************************************************* @@ -824,6 +882,7 @@ If_Man_t * Gia_ManToIf( Gia_Man_t * p, If_Par_t * pPars ) } if ( Gia_ManHasChoices(p) ) Gia_ManCleanMark0( p ); + //If_ManCheckChoices( pIfMan ); return pIfMan; } @@ -1987,6 +2046,7 @@ Gia_Man_t * Gia_ManFromIfLogic( If_Man_t * pIfMan ) pFile = fopen( Buffer, "wb" ); if ( pFile == NULL ) { + Vec_StrFree( vConfigsStr ); printf( "Cannot open file \"%s\".\n", Buffer ); return pNew; } @@ -2162,10 +2222,11 @@ void Gia_ManTransferTiming( Gia_Man_t * p, Gia_Man_t * pGia ) p->DefOutReqs = pGia->DefOutReqs; p->And2Delay = pGia->And2Delay; } - if ( pGia->vNamesIn || pGia->vNamesOut ) + if ( pGia->vNamesIn || pGia->vNamesOut || pGia->vNamesNode ) { p->vNamesIn = pGia->vNamesIn; pGia->vNamesIn = NULL; p->vNamesOut = pGia->vNamesOut; pGia->vNamesOut = NULL; + p->vNamesNode = pGia->vNamesNode; pGia->vNamesNode = NULL; } if ( pGia->vConfigs || pGia->pCellStr ) { @@ -2357,6 +2418,7 @@ Gia_Man_t * Gia_ManPerformMappingInt( Gia_Man_t * p, If_Par_t * pPars ) // transfer name assert( pNew->pName == NULL ); pNew->pName = Abc_UtilStrsav( p->pName ); + ABC_FREE( pNew->pSpec ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // print delay trace diff --git a/src/aig/gia/giaIso.c b/src/aig/gia/giaIso.c index 76419e93..fcfa3448 100644 --- a/src/aig/gia/giaIso.c +++ b/src/aig/gia/giaIso.c @@ -894,7 +894,7 @@ void Gia_ManFindCaninicalOrder( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAn Vec_PtrClear( vTemp ); Gia_ManForEachPi( p, pObj, i ) Vec_PtrPush( vTemp, pObj ); - Vec_PtrSort( vTemp, (int (*)(void))Gia_ObjCompareByValue ); + Vec_PtrSort( vTemp, (int (*)(const void *, const void *))Gia_ObjCompareByValue ); // create the result Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i ) Vec_IntPush( vCis, Gia_ObjId(p, pObj) ); @@ -917,7 +917,7 @@ void Gia_ManFindCaninicalOrder( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAn pObj->Value = Abc_Var2Lit( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) ); Vec_PtrPush( vTemp, pObj ); } - Vec_PtrSort( vTemp, (int (*)(void))Gia_ObjCompareByValue ); + Vec_PtrSort( vTemp, (int (*)(const void *, const void *))Gia_ObjCompareByValue ); Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i ) Vec_IntPush( vCos, Gia_ObjId(p, pObj) ); } @@ -926,7 +926,7 @@ void Gia_ManFindCaninicalOrder( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAn Vec_PtrClear( vTemp ); Gia_ManForEachRo( p, pObj, i ) Vec_PtrPush( vTemp, pObj ); - Vec_PtrSort( vTemp, (int (*)(void))Gia_ObjCompareByValue ); + Vec_PtrSort( vTemp, (int (*)(const void *, const void *))Gia_ObjCompareByValue ); // create the result Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i ) { diff --git a/src/aig/gia/giaIso2.c b/src/aig/gia/giaIso2.c index 576b118f..22b1d09e 100644 --- a/src/aig/gia/giaIso2.c +++ b/src/aig/gia/giaIso2.c @@ -328,7 +328,7 @@ int Gia_Iso2ManUniqify( Gia_Iso2Man_t * p ) } Vec_IntShrink( p->vTied, k ); // sort singletons - Vec_PtrSort( p->vSingles, (int (*)(void))Gia_ObjCompareByValue2 ); + Vec_PtrSort( p->vSingles, (int (*)(const void *, const void *))Gia_ObjCompareByValue2 ); // add them to unique and increment signature Vec_PtrForEachEntry( Gia_Obj_t *, p->vSingles, pObj, i ) { diff --git a/src/aig/gia/giaIso3.c b/src/aig/gia/giaIso3.c index a88a0569..8bea4bbf 100644 --- a/src/aig/gia/giaIso3.c +++ b/src/aig/gia/giaIso3.c @@ -158,6 +158,97 @@ void Gia_Iso3Test( Gia_Man_t * p ) Vec_IntFreeP( &vSign ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_Iso4Gia( Gia_Man_t * p ) +{ + Vec_Wec_t * vLevs = Gia_ManLevelizeR( p ); + Vec_Int_t * vLevel; int l; + Abc_Random( 1 ); + Vec_WecForEachLevel( vLevs, vLevel, l ) + { + Gia_Obj_t * pObj; int i; + int RandC[2] = { Abc_Random(0), Abc_Random(0) }; + if ( l == 0 ) + { + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + { + assert( Gia_ObjIsCo(pObj) ); + pObj->Value = Abc_Random(0); + Gia_ObjFanin0(pObj)->Value += pObj->Value + RandC[Gia_ObjFaninC0(pObj)]; + } + } + else + { + Gia_ManForEachObjVec( vLevel, p, pObj, i ) if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ObjFanin0(pObj)->Value += pObj->Value + RandC[Gia_ObjFaninC0(pObj)]; + Gia_ObjFanin1(pObj)->Value += pObj->Value + RandC[Gia_ObjFaninC1(pObj)]; + } + } + } + return vLevs; +} +void Gia_Iso4Test( Gia_Man_t * p ) +{ + Vec_Wec_t * vLevs = Gia_Iso4Gia( p ); + Vec_Int_t * vLevel; int l; + Vec_WecForEachLevel( vLevs, vLevel, l ) + { + Gia_Obj_t * pObj; int i; + printf( "Level %d\n", l ); + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + printf( "Obj = %5d. Value = %08x.\n", Gia_ObjId(p, pObj), pObj->Value ); + } + Vec_WecFree( vLevs ); +} +Vec_Int_t * Gia_IsoCollectData( Gia_Man_t * p, Vec_Int_t * vObjs ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vData = Vec_IntAlloc( Vec_IntSize(vObjs) ); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + Vec_IntPush( vData, pObj->Value ); + return vData; +} +void Gia_IsoCompareVecs( Gia_Man_t * pGia0, Vec_Wec_t * vLevs0, Gia_Man_t * pGia1, Vec_Wec_t * vLevs1 ) +{ + int i, Common, nLevels = Abc_MinInt( Vec_WecSize(vLevs0), Vec_WecSize(vLevs1) ); + Gia_ManPrintStats( pGia0, NULL ); + Gia_ManPrintStats( pGia1, NULL ); + printf( "Printing %d shared levels:\n", nLevels ); + for ( i = 0; i < nLevels; i++ ) + { + Vec_Int_t * vLev0 = Vec_WecEntry(vLevs0, i); + Vec_Int_t * vLev1 = Vec_WecEntry(vLevs1, i); + Vec_Int_t * vData0 = Gia_IsoCollectData( pGia0, vLev0 ); + Vec_Int_t * vData1 = Gia_IsoCollectData( pGia1, vLev1 ); + Vec_IntSort( vData0, 0 ); + Vec_IntSort( vData1, 0 ); + Common = Vec_IntTwoCountCommon( vData0, vData1 ); + printf( "Level = %3d. One = %6d. Two = %6d. Common = %6d.\n", + i, Vec_IntSize(vData0)-Common, Vec_IntSize(vData1)-Common, Common ); + Vec_IntFree( vData0 ); + Vec_IntFree( vData1 ); + } +} +void Gia_Iso4TestTwo( Gia_Man_t * pGia0, Gia_Man_t * pGia1 ) +{ + Vec_Wec_t * vLevs0 = Gia_Iso4Gia( pGia0 ); + Vec_Wec_t * vLevs1 = Gia_Iso4Gia( pGia1 ); + Gia_IsoCompareVecs( pGia0, vLevs0, pGia1, vLevs1 ); + Vec_WecFree( vLevs0 ); + Vec_WecFree( vLevs1 ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index 4ca9bfa4..a40673a7 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -81,8 +81,6 @@ Gia_Man_t * Gia_ManStart( int nObjsMax ) ***********************************************************************/ void Gia_ManStop( Gia_Man_t * p ) { - extern void Gia_DatFree( Gia_Dat_t * p ); - Gia_DatFree( p->pUData ); if ( p->vSeqModelVec ) Vec_PtrFreeFree( p->vSeqModelVec ); Gia_ManStaticFanoutStop( p ); @@ -90,11 +88,14 @@ void Gia_ManStop( Gia_Man_t * p ) assert( p->pManTime == NULL ); Vec_PtrFreeFree( p->vNamesIn ); Vec_PtrFreeFree( p->vNamesOut ); + Vec_PtrFreeFree( p->vNamesNode ); Vec_IntFreeP( &p->vSwitching ); Vec_IntFreeP( &p->vSuper ); Vec_IntFreeP( &p->vStore ); Vec_IntFreeP( &p->vClassNew ); Vec_IntFreeP( &p->vClassOld ); + Vec_IntFreeP( &p->vPats ); + Vec_BitFreeP( &p->vPolars ); Vec_WrdFreeP( &p->vSims ); Vec_WrdFreeP( &p->vSimsT ); Vec_WrdFreeP( &p->vSimsPi ); @@ -129,6 +130,7 @@ void Gia_ManStop( Gia_Man_t * p ) Vec_IntFreeP( &p->vVar2Obj ); Vec_IntErase( &p->vCopiesTwo ); Vec_IntErase( &p->vSuppVars ); + Vec_IntErase( &p->vVarMap ); Vec_WrdFreeP( &p->vSuppWords ); Vec_IntFreeP( &p->vTtNums ); Vec_IntFreeP( &p->vTtNodes ); @@ -147,6 +149,7 @@ void Gia_ManStop( Gia_Man_t * p ) Vec_IntFreeP( &p->vCoReqs ); Vec_IntFreeP( &p->vCoArrs ); Vec_IntFreeP( &p->vCoAttrs ); + Vec_IntFreeP( &p->vWeights ); Gia_ManStopP( &p->pAigExtra ); Vec_IntFree( p->vCis ); Vec_IntFree( p->vCos ); @@ -201,6 +204,7 @@ double Gia_ManMemory( Gia_Man_t * p ) Memory += Vec_FltMemory( p->vOutReqs ); Memory += Vec_PtrMemory( p->vNamesIn ); Memory += Vec_PtrMemory( p->vNamesOut ); + Memory += Vec_PtrMemory( p->vNamesNode ); return Memory; } @@ -582,7 +586,7 @@ void Gia_ManPrintStats( Gia_Man_t * p, Gps_Par_t * pPars ) Gia_ManPrintMappingStats( p, pPars ? pPars->pDumpFile : NULL ); else if ( pPars && pPars->pDumpFile ) Gia_ManLogAigStats( p, pPars->pDumpFile ); - if ( pPars && pPars->fNpn && Gia_ManHasMapping(p) && Gia_ManLutSizeMax(p) <= 4 ) + if ( pPars && pPars->fNpn && Gia_ManHasMapping(p) ) Gia_ManPrintNpnClasses( p ); if ( p->vPacking ) Gia_ManPrintPackingStats( p ); @@ -1269,13 +1273,14 @@ void Gia_ManWriteNames( FILE * pFile, char c, int n, Vec_Ptr_t * vNames, int Sta fFirst = 0; } } -void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs ) +void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs ) { FILE * pFile; Gia_Obj_t * pObj; Vec_Bit_t * vInvs, * vUsed; - int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); - int nDigits2 = Abc_Base10Log( Gia_ManPiNum(p) ); + int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); + int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); + int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); int i, k, iObj; if ( Gia_ManRegNum(p) ) { @@ -1300,20 +1305,63 @@ void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs ) fprintf( pFile, "%c", p->pName[i] ); else fprintf( pFile, "_" ); - fprintf( pFile, " (\n " ); - Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 4, 4, NULL ); - fprintf( pFile, ",\n " ); - Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 4, 4, NULL ); - fprintf( pFile, "\n );\n\n" ); + if ( fVerBufs ) + { + fprintf( pFile, " (\n " ); + Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 4, 4, NULL ); + fprintf( pFile, ",\n " ); + + Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 4, 4, NULL ); + fprintf( pFile, "\n );\n\n" ); + + fprintf( pFile, " input " ); + Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 8, 4, NULL ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " output " ); + Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 9, 4, NULL ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); + fprintf( pFile, ";\n\n" ); - fprintf( pFile, " input " ); - Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); - fprintf( pFile, ";\n\n" ); + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL ); + fprintf( pFile, ";\n\n" ); - fprintf( pFile, " output " ); - Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL ); - fprintf( pFile, ";\n\n" ); + Gia_ManForEachPi( p, pObj, i ) + { + fprintf( pFile, " buf ( %s,", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(NULL, 'a', i, nDigitsI) ); + } + fprintf( pFile, "\n" ); + + Gia_ManForEachPo( p, pObj, i ) + { + fprintf( pFile, " buf ( %s,", Gia_ObjGetDumpName(NULL, 'y', i, nDigitsO) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + } + fprintf( pFile, "\n" ); + } + else + { + fprintf( pFile, " (\n " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 4, 4, NULL ); + fprintf( pFile, ",\n " ); + + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 4, 4, NULL ); + fprintf( pFile, "\n );\n\n" ); + + fprintf( pFile, " input " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " output " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL ); + fprintf( pFile, ";\n\n" ); + } if ( Vec_BitCount(vUsed) ) { @@ -1337,7 +1385,7 @@ void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs ) fprintf( pFile, ";\n\n" ); Vec_IntForEachEntry( vObjs, iObj, i ) { - fprintf( pFile, " buf( %s,", Gia_ObjGetDumpName(NULL, 'n', iObj, nDigits) ); + fprintf( pFile, " buf ( %s,", Gia_ObjGetDumpName(NULL, 'n', iObj, nDigits) ); fprintf( pFile, " t_%d );\n", i ); } fprintf( pFile, "\n" ); @@ -1348,13 +1396,13 @@ void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs ) { if ( Vec_BitEntry(vUsed, Gia_ObjId(p, pObj)) ) { - fprintf( pFile, " buf( %s,", Gia_ObjGetDumpName(NULL, 'n', Gia_ObjId(p, pObj), nDigits) ); - fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigits2) ); + fprintf( pFile, " buf ( %s,", Gia_ObjGetDumpName(NULL, 'n', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); } if ( Vec_BitEntry(vInvs, Gia_ObjId(p, pObj)) ) { - fprintf( pFile, " not( %s,", Gia_ObjGetDumpName(NULL, 'i', Gia_ObjId(p, pObj), nDigits) ); - fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigits2) ); + fprintf( pFile, " not ( %s,", Gia_ObjGetDumpName(NULL, 'i', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); } } @@ -1373,20 +1421,19 @@ void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs ) } if ( !fSkip ) { - fprintf( pFile, " and( %s,", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + fprintf( pFile, " and ( %s,", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); fprintf( pFile, " %s,", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0(pObj, i), nDigits) ); fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC1(pObj)? 'i':'n'), Gia_ObjFaninId1(pObj, i), nDigits) ); } if ( Vec_BitEntry(vInvs, i) ) { - fprintf( pFile, " not( %s,", Gia_ObjGetDumpName(NULL, 'i', i, nDigits) ); + fprintf( pFile, " not ( %s,", Gia_ObjGetDumpName(NULL, 'i', i, nDigits) ); fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); } } // output drivers fprintf( pFile, "\n" ); - nDigits2 = Abc_Base10Log( Gia_ManPoNum(p) ); Gia_ManForEachPo( p, pObj, i ) { /* @@ -1396,7 +1443,7 @@ void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs ) else fprintf( pFile, "%s;\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0p(p, pObj), nDigits) ); */ - fprintf( pFile, " buf( %s, ", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigits2) ); + fprintf( pFile, " buf ( %s, ", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) fprintf( pFile, "1\'b%d );\n", Gia_ObjFaninC0(pObj) ); else diff --git a/src/aig/gia/giaMf.c b/src/aig/gia/giaMf.c index 7e699d9b..e732f25e 100644 --- a/src/aig/gia/giaMf.c +++ b/src/aig/gia/giaMf.c @@ -24,6 +24,7 @@ #include "misc/extra/extra.h" #include "sat/cnf/cnf.h" #include "opt/dau/dau.h" +#include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START @@ -557,8 +558,8 @@ static inline int Mf_CutComputeTruth6( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut_t assert( (int)(t & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, &t); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); - if ( p->pPars->fGenCnf && truthId == Vec_IntSize(&p->vCnfSizes) ) - Vec_IntPush( &p->vCnfSizes, Abc_Tt6CnfSize(t, pCutR->nLeaves) ); + if ( (p->pPars->fGenCnf || p->pPars->fGenLit) && truthId == Vec_IntSize(&p->vCnfSizes) ) + Vec_IntPush( &p->vCnfSizes, p->pPars->fGenCnf ? Abc_Tt6CnfSize(t, pCutR->nLeaves) : Kit_TruthLitNum((unsigned *)&t, pCutR->nLeaves, &p->vCnfMem) ); // p->nCutMux += Mf_ManTtIsMux( t ); assert( (int)pCutR->nLeaves <= nOldSupp ); // Mf_ManTruthCanonicize( &t, pCutR->nLeaves ); @@ -588,8 +589,8 @@ static inline int Mf_CutComputeTruth( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut_t * //Kit_DsdPrintFromTruth( uTruth, pCutR->nLeaves ), printf("\n" ), printf("\n" ); truthId = Vec_MemHashInsert(p->vTtMem, uTruth); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); - if ( p->pPars->fGenCnf && truthId == Vec_IntSize(&p->vCnfSizes) && LutSize <= 8 ) - Vec_IntPush( &p->vCnfSizes, Abc_Tt8CnfSize(uTruth, pCutR->nLeaves) ); + if ( (p->pPars->fGenCnf || p->pPars->fGenLit) && truthId == Vec_IntSize(&p->vCnfSizes) && LutSize <= 8 ) + Vec_IntPush( &p->vCnfSizes, p->pPars->fGenCnf ? Abc_Tt8CnfSize(uTruth, pCutR->nLeaves) : Kit_TruthLitNum((unsigned *)uTruth, pCutR->nLeaves, &p->vCnfMem) ); assert( (int)pCutR->nLeaves <= nOldSupp ); return (int)pCutR->nLeaves < nOldSupp; } @@ -612,8 +613,8 @@ static inline int Mf_CutComputeTruthMux6( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut assert( (int)(t & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, &t); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); - if ( p->pPars->fGenCnf && truthId == Vec_IntSize(&p->vCnfSizes) ) - Vec_IntPush( &p->vCnfSizes, Abc_Tt6CnfSize(t, pCutR->nLeaves) ); + if ( (p->pPars->fGenCnf || p->pPars->fGenLit) && truthId == Vec_IntSize(&p->vCnfSizes) ) + Vec_IntPush( &p->vCnfSizes, p->pPars->fGenCnf ? Abc_Tt6CnfSize(t, pCutR->nLeaves) : Kit_TruthLitNum((unsigned *)&t, pCutR->nLeaves, &p->vCnfMem) ); assert( (int)pCutR->nLeaves <= nOldSupp ); return (int)pCutR->nLeaves < nOldSupp; } @@ -642,8 +643,8 @@ static inline int Mf_CutComputeTruthMux( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut_ assert( (uTruth[0] & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, uTruth); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); - if ( p->pPars->fGenCnf && truthId == Vec_IntSize(&p->vCnfSizes) && LutSize <= 8 ) - Vec_IntPush( &p->vCnfSizes, Abc_Tt8CnfSize(uTruth, pCutR->nLeaves) ); + if ( (p->pPars->fGenCnf || p->pPars->fGenLit) && truthId == Vec_IntSize(&p->vCnfSizes) && LutSize <= 8 ) + Vec_IntPush( &p->vCnfSizes, p->pPars->fGenCnf ? Abc_Tt8CnfSize(uTruth, pCutR->nLeaves) : Kit_TruthLitNum((unsigned *)uTruth, pCutR->nLeaves, &p->vCnfMem) ); assert( (int)pCutR->nLeaves <= nOldSupp ); return (int)pCutR->nLeaves < nOldSupp; } @@ -699,6 +700,8 @@ static inline void Mf_CutPrint( Mf_Man_t * p, Mf_Cut_t * pCut ) { if ( p->pPars->fGenCnf ) printf( "CNF = %2d ", Vec_IntEntry(&p->vCnfSizes, Abc_Lit2Var(pCut->iFunc)) ); + if ( p->pPars->fGenLit ) + printf( "Lit = %2d ", Vec_IntEntry(&p->vCnfSizes, Abc_Lit2Var(pCut->iFunc)) ); Dau_DsdPrintFromTruth( Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut->iFunc)), pCut->nLeaves ); } else @@ -998,7 +1001,7 @@ static inline int Mf_CutArea( Mf_Man_t * p, int nLeaves, int iFunc ) { if ( nLeaves < 2 ) return 0; - if ( p->pPars->fGenCnf ) + if ( p->pPars->fGenCnf || p->pPars->fGenLit ) return Vec_IntEntry(&p->vCnfSizes, Abc_Lit2Var(iFunc)); if ( p->pPars->fOptEdge ) return nLeaves + p->pPars->nAreaTuner; @@ -1202,7 +1205,7 @@ int Mf_ManSetMapRefs( Mf_Man_t * p ) Mf_ObjMapRefInc( p, pCut[k] ); p->pPars->Edge += Mf_CutSize(pCut); p->pPars->Area++; - if ( p->pPars->fGenCnf ) + if ( p->pPars->fGenCnf || p->pPars->fGenLit ) p->pPars->Clause += Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); } // blend references @@ -1394,7 +1397,7 @@ Mf_Man_t * Mf_ManAlloc( Gia_Man_t * pGia, Jf_Par_t * pPars ) p->pLfObjs = ABC_CALLOC( Mf_Obj_t, Gia_ManObjNum(pGia) ); p->iCur = 2; Vec_PtrGrow( &p->vPages, 256 ); - if ( pPars->fGenCnf ) + if ( pPars->fGenCnf || pPars->fGenLit ) { Vec_IntGrow( &p->vCnfSizes, 10000 ); Vec_IntPush( &p->vCnfSizes, 1 ); @@ -1410,7 +1413,7 @@ Mf_Man_t * Mf_ManAlloc( Gia_Man_t * pGia, Jf_Par_t * pPars ) } void Mf_ManFree( Mf_Man_t * p ) { - assert( !p->pPars->fGenCnf || Vec_IntSize(&p->vCnfSizes) == Vec_MemEntryNum(p->vTtMem) ); + assert( !p->pPars->fGenCnf || !p->pPars->fGenLit || Vec_IntSize(&p->vCnfSizes) == Vec_MemEntryNum(p->vTtMem) ); if ( p->pPars->fCutMin ) Vec_MemHashFree( p->vTtMem ); if ( p->pPars->fCutMin ) @@ -1453,6 +1456,7 @@ void Mf_ManSetDefaultPars( Jf_Par_t * pPars ) pPars->fCoarsen = 1; pPars->fCutMin = 0; pPars->fGenCnf = 0; + pPars->fGenLit = 0; pPars->fPureAig = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; @@ -1469,6 +1473,8 @@ void Mf_ManPrintStats( Mf_Man_t * p, char * pTitle ) printf( "Edge =%9lu ", (long)p->pPars->Edge ); if ( p->pPars->fGenCnf ) printf( "CNF =%9lu ", (long)p->pPars->Clause ); + if ( p->pPars->fGenLit ) + printf( "FFL =%9lu ", (long)p->pPars->Clause ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); fflush( stdout ); } @@ -1483,6 +1489,7 @@ void Mf_ManPrintInit( Mf_Man_t * p ) printf( "CutMin = %d ", p->pPars->fCutMin ); printf( "Coarse = %d ", p->pPars->fCoarsen ); printf( "CNF = %d ", p->pPars->fGenCnf ); + printf( "FFL = %d ", p->pPars->fGenLit ); printf( "\n" ); printf( "Computing cuts...\r" ); fflush( stdout ); @@ -1541,51 +1548,97 @@ void Mf_ManComputeCuts( Mf_Man_t * p ) SeeAlso [] ***********************************************************************/ -int Mf_CutRef2_rec( Mf_Man_t * p, int * pCut, Vec_Int_t * vTemp, int Limit ) +int Mf_CutRef_rec( Mf_Man_t * p, int * pCut ) { int i, Count = Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); - if ( Limit == 0 ) return Count; for ( i = 1; i <= Mf_CutSize(pCut); i++ ) - { - Vec_IntPush( vTemp, pCut[i] ); if ( !Mf_ObjMapRefInc(p, pCut[i]) && Mf_ManObj(p, pCut[i])->iCutSet ) - Count += Mf_CutRef2_rec( p, Mf_ObjCutBest(p, pCut[i]), vTemp, Limit-1 ); - } + Count += Mf_CutRef_rec( p, Mf_ObjCutBest(p, pCut[i]) ); return Count; } -static inline int Mf_CutAreaDerefed2( Mf_Man_t * p, int * pCut ) +int Mf_CutDeref_rec( Mf_Man_t * p, int * pCut ) { - int Ela1, iObj, i; - Vec_IntClear( &p->vTemp ); - Ela1 = Mf_CutRef2_rec( p, pCut, &p->vTemp, 8 ); - Vec_IntForEachEntry( &p->vTemp, iObj, i ) - Mf_ObjMapRefDec( p, iObj ); + int i, Count = Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); + for ( i = 1; i <= Mf_CutSize(pCut); i++ ) + if ( !Mf_ObjMapRefDec(p, pCut[i]) && Mf_ManObj(p, pCut[i])->iCutSet ) + Count += Mf_CutDeref_rec( p, Mf_ObjCutBest(p, pCut[i]) ); + return Count; +} +static inline int Mf_CutAreaRefed( Mf_Man_t * p, int * pCut ) +{ + int Ela1 = Mf_CutDeref_rec( p, pCut ); + int Ela2 = Mf_CutRef_rec( p, pCut ); + assert( Ela1 == Ela2 ); + return Ela1; +} +static inline int Mf_CutAreaDerefed( Mf_Man_t * p, int * pCut ) +{ + int Ela1 = Mf_CutRef_rec( p, pCut ); + int Ela2 = Mf_CutDeref_rec( p, pCut ); + assert( Ela1 == Ela2 ); return Ela1; } +static inline int Mf_CutAreaMffc( Mf_Man_t * p, int iObj ) +{ + return Mf_ObjMapRefNum(p, iObj) ? + Mf_CutAreaRefed (p, Mf_ObjCutBest(p, iObj)) : + Mf_CutAreaDerefed(p, Mf_ObjCutBest(p, iObj)); +} -int Mf_CutRef_rec( Mf_Man_t * p, int * pCut ) +int Mf_CutRef2_rec( Mf_Man_t * p, int * pCut, Vec_Int_t * vTemp, int Limit ) { int i, Count = Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); + if ( Limit == 0 ) return Count; for ( i = 1; i <= Mf_CutSize(pCut); i++ ) + { + Vec_IntPush( vTemp, pCut[i] ); if ( !Mf_ObjMapRefInc(p, pCut[i]) && Mf_ManObj(p, pCut[i])->iCutSet ) - Count += Mf_CutRef_rec( p, Mf_ObjCutBest(p, pCut[i]) ); + Count += Mf_CutRef2_rec( p, Mf_ObjCutBest(p, pCut[i]), vTemp, Limit-1 ); + } return Count; } -int Mf_CutDeref_rec( Mf_Man_t * p, int * pCut ) +int Mf_CutDeref2_rec( Mf_Man_t * p, int * pCut, Vec_Int_t * vTemp, int Limit ) { int i, Count = Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); + if ( Limit == 0 ) return Count; for ( i = 1; i <= Mf_CutSize(pCut); i++ ) + { + Vec_IntPush( vTemp, pCut[i] ); if ( !Mf_ObjMapRefDec(p, pCut[i]) && Mf_ManObj(p, pCut[i])->iCutSet ) - Count += Mf_CutDeref_rec( p, Mf_ObjCutBest(p, pCut[i]) ); + Count += Mf_CutDeref2_rec( p, Mf_ObjCutBest(p, pCut[i]), vTemp, Limit-1 ); + } return Count; } -static inline int Mf_CutAreaDerefed( Mf_Man_t * p, int * pCut ) +static inline int Mf_CutAreaRefed2( Mf_Man_t * p, int * pCut ) { - int Ela1 = Mf_CutRef_rec( p, pCut ); - int Ela2 = Mf_CutDeref_rec( p, pCut ); - assert( Ela1 == Ela2 ); + int Ela1, iObj, i; + Vec_IntClear( &p->vTemp ); + Ela1 = Mf_CutDeref2_rec( p, pCut, &p->vTemp, 8 ); + Vec_IntForEachEntry( &p->vTemp, iObj, i ) + Mf_ObjMapRefInc( p, iObj ); return Ela1; } +static inline int Mf_CutAreaDerefed2( Mf_Man_t * p, int * pCut ) +{ + int Ela1, iObj, i; + Vec_IntClear( &p->vTemp ); + Ela1 = Mf_CutRef2_rec( p, pCut, &p->vTemp, 8 ); + Vec_IntForEachEntry( &p->vTemp, iObj, i ) + Mf_ObjMapRefDec( p, iObj ); + return Ela1; +} +static inline int Mf_CutAreaRefed2Multi( Mf_Man_t * p, int iObj, int ** ppCuts, int nCuts ) +{ + int Ela1 = 0, iTemp, i; + Vec_IntClear( &p->vTemp ); + for ( i = 0; i < nCuts; i++ ) + Ela1 += Mf_CutDeref2_rec( p, ppCuts[i], &p->vTemp, ABC_INFINITY ); + assert( Mf_ObjMapRefNum(p, iObj) == 0 ); + Vec_IntForEachEntry( &p->vTemp, iTemp, i ) + Mf_ObjMapRefInc( p, iTemp ); + return Ela1; +} + static inline float Mf_CutFlow( Mf_Man_t * p, int * pCut, int * pTime ) { Mf_Obj_t * pObj; @@ -1635,6 +1688,120 @@ static inline void Mf_ObjComputeBestCut( Mf_Man_t * p, int iObj ) /**Function************************************************************* + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mf_ManMappingFromMapping( Mf_Man_t * p ) +{ + Gia_Man_t * pGia = p->pGia0; + Gia_Obj_t * pObj; + int i, iObj, Count = 0; + Vec_Int_t * vMapping = Vec_IntAlloc( 3 * Gia_ManObjNum(pGia) ); + Vec_IntFill( vMapping, Gia_ManObjNum(pGia), 0 ); + Gia_ManForEachAnd( pGia, pObj, iObj ) + if ( Mf_ObjMapRefNum(p, iObj) ) + { + int * pCut = Mf_ObjCutBest(p, iObj); + Vec_IntWriteEntry( vMapping, iObj, Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Mf_CutSize(pCut) ); + for ( i = 1; i <= Mf_CutSize(pCut); i++ ) + Vec_IntPush( vMapping, pCut[i] ); + Vec_IntPush( vMapping, iObj ); + Count++; + } + assert( pGia->vMapping == NULL ); + pGia->vMapping = vMapping; + printf( "Mapping is %.2fx larger than AIG manager.\n", 1.0*Vec_IntSize(vMapping)/Gia_ManObjNum(pGia) ); + return Count; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mf_ManPrintFanoutProfile( Mf_Man_t * p, Vec_Int_t * vFanCounts ) +{ + Gia_Man_t * pGia = p->pGia0; + int i, Count, nMax = Vec_IntFindMax( vFanCounts ); + Vec_Int_t * vCounts = Vec_IntStart( nMax + 1 ); + Vec_IntForEachEntry( vFanCounts, Count, i ) + if ( Count && Gia_ObjIsAnd(Gia_ManObj(pGia, i)) ) + Vec_IntAddToEntry( vCounts, Count, 1 ); + printf( "\nFanout distribution for internal nodes:\n" ); + Vec_IntForEachEntry( vCounts, Count, i ) + if ( Count ) printf( "Fanout = %5d : Nodes = %5d.\n", i, Count ); + printf( "Total nodes with fanout = %d. Max fanout = %d.\n\n", Vec_IntCountPositive(vCounts), nMax ); + Vec_IntFree( vCounts ); +} +int Mf_ManPrintMfccStats( Mf_Man_t * p, int iObj ) +{ + Gia_Man_t * pGia = p->pGia0; + int Area; + printf( "%5d : Level = %5d Refs = %5d Mffc = %5d\n", + iObj, Gia_ObjLevelId(pGia, iObj), Mf_ObjMapRefNum(p, iObj), (Area = Mf_CutAreaMffc(p, iObj)) ); + return Area; +} +void Mf_ManOptimizationOne( Mf_Man_t * p, int iObj ) +{ + Gia_Man_t * pGia = p->pGia0; + int * ppCuts[32], nCuts = 0; + int iFanout, i, nAreaSum = 0, nAreaBest = 0; + // skip pivots whose MFFC fanouts are pointed to by COs + Gia_ObjForEachFanoutStaticId( pGia, iObj, iFanout, i ) + if ( Gia_ObjIsCo(Gia_ManObj(pGia, iFanout)) ) + return; + // the pivot is used in the mapping as well as all of its fanouts + assert( Mf_ObjMapRefNum(p, iObj) > 1 ); + Gia_ObjForEachFanoutStaticId( pGia, iObj, iFanout, i ) + assert( Mf_ObjMapRefNum(p, iFanout) > 0 ); + // print this pivot and its fanouts + printf( "\nPivot node = %d\n", iObj ); + printf( "Pivot " ), Mf_ManPrintMfccStats( p, iObj ); + Gia_ObjForEachFanoutStaticId( pGia, iObj, iFanout, i ) + printf( "Node " ), nAreaSum += Mf_ManPrintMfccStats( p, iFanout ); + // calculate the shared MFFC + Gia_ObjForEachFanoutStaticId( pGia, iObj, iFanout, i ) + Mf_ObjMapRefInc( p, iFanout ); + Gia_ObjForEachFanoutStaticId( pGia, iObj, iFanout, i ) + ppCuts[nCuts++] = Mf_ObjCutBest( p, iFanout ); + nAreaBest = Mf_CutAreaRefed2Multi( p, iObj, ppCuts, nCuts ); + Gia_ObjForEachFanoutStaticId( pGia, iObj, iFanout, i ) + Mf_ObjMapRefDec( p, iFanout ); + printf( "Sum of MFFC sizes = %d\n", nAreaSum ); + printf( "Shared MFFC size = %d\n", nAreaBest ); +} +void Mf_ManOptimization( Mf_Man_t * p ) +{ + int nOutMax = 3; + Gia_Man_t * pGia = p->pGia0; + int i, Count, nNodes = Mf_ManMappingFromMapping( p ); + Gia_ManLevelNum( pGia ); + Gia_ManStaticMappingFanoutStart( pGia ); + Mf_ManPrintFanoutProfile( p, pGia->vFanoutNums ); + printf( "\nIndividual logic cones for mapping with %d nodes:\n", nNodes ); + Vec_IntForEachEntry( pGia->vFanoutNums, Count, i ) + if ( Count >= 2 && Count <= nOutMax && Gia_ObjIsAnd(Gia_ManObj(pGia, i)) ) + Mf_ManOptimizationOne( p, i ); + printf( "\nFinished printing individual logic cones.\n" ); + Gia_ManStaticFanoutStop( pGia ); + Vec_IntFreeP( &pGia->vMapping ); +} + +/**Function************************************************************* + Synopsis [Technology mappping.] Description [] @@ -1656,7 +1823,7 @@ Gia_Man_t * Mf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) { Mf_Man_t * p; Gia_Man_t * pNew, * pCls; - if ( pPars->fGenCnf ) + if ( pPars->fGenCnf || pPars->fGenLit ) pPars->fCutMin = 1; if ( Gia_ManHasChoices(pGia) ) pPars->fCutMin = 1, pPars->fCoarsen = 0; @@ -1675,6 +1842,7 @@ Gia_Man_t * Mf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) p->fUseEla = 1; for ( ; p->Iter < p->pPars->nRounds + pPars->nRoundsEla; p->Iter++ ) Mf_ManComputeMapping( p ); + //Mf_ManOptimization( p ); if ( pPars->fVeryVerbose && pPars->fCutMin ) Vec_MemDumpTruthTables( p->vTtMem, Gia_ManName(p->pGia), pPars->nLutSize ); if ( pPars->fCutMin ) @@ -1685,8 +1853,8 @@ Gia_Man_t * Mf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) pNew = Mf_ManDeriveMapping( p ); if ( p->pPars->fGenCnf ) pGia->pData = Mf_ManDeriveCnf( p, p->pPars->fCnfObjIds, p->pPars->fAddOrCla ); -// if ( p->pPars->fGenCnf ) -// Mf_ManProfileTruths( p ); + //if ( p->pPars->fGenCnf || p->pPars->fGenLit ) + // Mf_ManProfileTruths( p ); Gia_ManMappingVerify( pNew ); Mf_ManPrintQuit( p, pNew ); Mf_ManFree( p ); diff --git a/src/aig/gia/giaMinLut.c b/src/aig/gia/giaMinLut.c new file mode 100644 index 00000000..5304486d --- /dev/null +++ b/src/aig/gia/giaMinLut.c @@ -0,0 +1,1058 @@ +/**CFile**************************************************************** + + FileName [giaMinLut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Collapsing AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaMinLut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "giaAig.h" +#include "base/main/mainInt.h" +#include "opt/sfm/sfm.h" + +#ifdef ABC_USE_CUDD +#include "bdd/extrab/extraBdd.h" +#include "bdd/dsd/dsd.h" +#endif + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Vec_WrdReadLayerText( char * pFileName, int * pnIns, int * pnOuts ) +{ + char * pThis, pLine[1000]; + Vec_Wec_t * vRes; int iLine; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return NULL; + } + vRes = Vec_WecAlloc(100); + for ( iLine = 0; fgets( pLine, 1000, pFile ); iLine++ ) + { + if ( iLine == 0 ) + { + pThis = strstr( pLine, "[" ); + *pnIns = atoi( pThis+1 ) + 1; + pThis = strstr( pThis+1, "[" ); + *pnOuts = atoi( pThis+1 ) + 1; + } + else + { + Vec_Int_t * vLevel = NULL; + for ( pThis = pLine; (pThis = strstr(pThis, "M0[")); pThis++ ) + { + if ( vLevel == NULL ) + vLevel = Vec_WecPushLevel( vRes ); + Vec_IntPush( vLevel, atoi( pThis+3 ) ); + } + if ( vLevel ) + Vec_IntReverseOrder( vLevel ); + } + } + fclose( pFile ); + //Vec_WecPrint( vRes, 0 ); + return vRes; +} +int Vec_WrdReadTruthTextOne( char * pFileName, int nIns, int nOuts, word * pRes ) +{ + int i, nWords = Abc_TtWordNum( nIns ); + char * pStart, * pBuffer = Extra_FileReadContents( pFileName ); + if ( pBuffer == NULL ) + { + printf( "Cannot read file \"%s\".\n", pFileName ); + return 0; + } + pStart = pBuffer; + for ( i = 0; i < nOuts; i++ ) + { + pStart = strstr( pStart + 1, "0x" ); + if ( !Extra_ReadHex( (unsigned *)(pRes + i*nWords), pStart + 2, nWords*16 ) ) + { + printf( "Cannot read truth table %d (out of %d) in file \"%s\".\n", i, nOuts, pFileName ); + ABC_FREE( pBuffer ); + return 0; + } + } + ABC_FREE( pBuffer ); + return 1; +} +word * Vec_WrdReadTruthText( char * pFileName, int nIns, int nOuts, int nFiles ) +{ + char FileName[1000]; + int i, nWords = Abc_TtWordNum( nIns ); + word * pRes = ABC_CALLOC( word, nOuts*nFiles*nWords ); + for ( i = 0; i < nFiles; i++ ) + { + assert( strlen(pFileName) < 900 ); + strcpy( FileName, pFileName ); + sprintf( FileName + strlen(FileName) - 2, "_N%d.bench", i ); + if ( !Vec_WrdReadTruthTextOne( FileName, nIns, nOuts, pRes + i*nOuts*nWords ) ) + { + ABC_FREE( pRes ); + return NULL; + } + } + return pRes; +} +Gia_Man_t * Vec_WrdReadTest( char * pFileName ) +{ + extern int Gia_ManPerformLNetOpt_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ); + extern Gia_Man_t * Gia_TryPermOptCare( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ); + Gia_Man_t * pPart, * pNew = NULL; Gia_Obj_t * pObj; + int i, k, nIns, nOuts, iLit; + Vec_Wec_t * vRes = Vec_WrdReadLayerText( pFileName, &nIns, &nOuts ); + int nBitsI = vRes ? Vec_WecMaxLevelSize(vRes) : 0; + int nBitsO = vRes ? nOuts / Vec_WecSize(vRes) : 0; + int nWords = Abc_TtWordNum(nBitsI); + word * pFuncs = vRes ? Vec_WrdReadTruthText( pFileName, nBitsI, nBitsO, Vec_WecSize(vRes) ) : NULL; + Vec_Int_t * vPart, * vLits = Vec_IntAlloc( nOuts ); + if ( vRes == NULL || pFuncs == NULL ) + { + Vec_WecFreeP( &vRes ); + Vec_IntFreeP( &vLits ); + ABC_FREE( pFuncs ); + return NULL; + } + assert( nOuts % Vec_WecSize(vRes) == 0 ); + pNew = Gia_ManStart( 10000 ); + pNew->pName = Abc_UtilStrsav( pFileName ); + pNew->pSpec = NULL; + for ( i = 0; i < nIns; i++ ) + Gia_ManAppendCi(pNew); + Gia_ManHashStart( pNew ); + Vec_WecForEachLevel( vRes, vPart, i ) + { + assert( Vec_IntSize(vPart) <= nBitsI ); + pPart = Gia_TryPermOptCare( pFuncs + i * nBitsO * nWords, nBitsI, nBitsO, nWords, 20, 0 ); + Gia_ManFillValue( pPart ); + Gia_ManConst0(pPart)->Value = 0; + Gia_ManForEachCi( pPart, pObj, k ) + pObj->Value = Abc_Var2Lit( 1+Vec_IntEntry(vPart, k), 0 ); + Gia_ManForEachCo( pPart, pObj, k ) + { + Gia_ManPerformLNetOpt_rec( pNew, pPart, Gia_ObjFanin0(pObj) ); + Vec_IntPush( vLits, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManStop( pPart ); + } + Gia_ManHashStop( pNew ); + Vec_IntForEachEntry( vLits, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + ABC_FREE( pFuncs ); + Vec_WecFree( vRes ); + Vec_IntFree( vLits ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Vec_WrdReadText( char * pFileName, Vec_Wrd_t ** pvSimI, Vec_Wrd_t ** pvSimO, int nIns, int nOuts ) +{ + int i, nSize, iLine, nLines, nWords; + char pLine[1000]; + Vec_Wrd_t * vSimI, * vSimO; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return; + } + fseek( pFile, 0, SEEK_END ); + nSize = ftell( pFile ); + if ( nSize % (nIns + nOuts + 1) > 0 ) + { + printf( "Cannot read file with simulation data that is not aligned at 8 bytes (remainder = %d).\n", nSize % (nIns + nOuts + 1) ); + fclose( pFile ); + return; + } + rewind( pFile ); + nLines = nSize / (nIns + nOuts + 1); + nWords = (nLines + 63)/64; + vSimI = Vec_WrdStart( nIns *nWords ); + vSimO = Vec_WrdStart( nOuts*nWords ); + for ( iLine = 0; fgets( pLine, 1000, pFile ); iLine++ ) + { + for ( i = 0; i < nIns; i++ ) + if ( pLine[nIns-1-i] == '1' ) + Abc_TtXorBit( Vec_WrdArray(vSimI) + i*nWords, iLine ); + else assert( pLine[nIns-1-i] == '0' ); + for ( i = 0; i < nOuts; i++ ) + if ( pLine[nIns+nOuts-1-i] == '1' ) + Abc_TtXorBit( Vec_WrdArray(vSimO) + i*nWords, iLine ); + else assert( pLine[nIns+nOuts-1-i] == '0' ); + } + fclose( pFile ); + *pvSimI = vSimI; + *pvSimO = vSimO; + printf( "Read %d words of simulation data for %d inputs and %d outputs (padded %d zero-patterns).\n", nWords, nIns, nOuts, nWords*64-nLines ); +} +int Vec_WrdReadText2( char * pFileName, Vec_Wrd_t ** pvSimI ) +{ + int i, nSize, iLine, nLines, nWords, nIns; + char pLine[1000]; + Vec_Wrd_t * vSimI; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return 0; + } + if ( !fgets(pLine, 1000, pFile) || (nIns = strlen(pLine)-1) < 1 ) + { + printf( "Cannot find the number of inputs in file \"%s\".\n", pFileName ); + fclose( pFile ); + return 0; + } + fseek( pFile, 0, SEEK_END ); + nSize = ftell( pFile ); + if ( nSize % (nIns + 1) > 0 ) + { + printf( "Cannot read file with simulation data that is not aligned at 8 bytes (remainder = %d).\n", nSize % (nIns + 1) ); + fclose( pFile ); + return 0; + } + rewind( pFile ); + nLines = nSize / (nIns + 1); + nWords = (nLines + 63)/64; + vSimI = Vec_WrdStart( nIns *nWords ); + for ( iLine = 0; fgets( pLine, 1000, pFile ); iLine++ ) + { + for ( i = 0; i < nIns; i++ ) + if ( pLine[nIns-1-i] == '1' ) + Abc_TtXorBit( Vec_WrdArray(vSimI) + i*nWords, iLine ); + else assert( pLine[nIns-1-i] == '0' ); + } + fclose( pFile ); + *pvSimI = vSimI; + printf( "Read %d words of simulation data for %d inputs (padded to 64-bit boundary with %d zero-patterns).\n", nWords, nIns, nWords*64-nLines ); + return nIns; +} +Vec_Int_t * Vec_WrdReadNumsOut( char * pFileName, int fVerbose ) +{ + char pLine[1000]; + Vec_Int_t * vNums; int iLine; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return NULL; + } + vNums = Vec_IntAlloc( 1000 ); + for ( iLine = 0; fgets( pLine, 1000, pFile ); iLine++ ) + Vec_IntPush( vNums, atoi(pLine) ); + fclose( pFile ); + if ( fVerbose ) + printf( "Finished reading %d output values from file \"%s\".\n", Vec_IntSize(vNums), pFileName ); + return vNums; +} +Vec_Wrd_t * Vec_WrdReadTextOut( char * pFileName, int nOuts ) +{ + int i, iLine, nLines, nWords; + Vec_Wrd_t * vSimO; + Vec_Int_t * vNums = Vec_WrdReadNumsOut( pFileName, 1 ); + if ( vNums == NULL ) + return NULL; + nLines = Vec_IntSize(vNums); + nWords = (nLines + 63)/64; + vSimO = Vec_WrdStart( nOuts*nWords ); + Vec_IntForEachEntry( vNums, i, iLine ) + Abc_TtXorBit( Vec_WrdArray(vSimO) + i*nWords, iLine ); + Vec_IntFree( vNums ); + printf( "Read %d words of simulation data for %d outputs (padded %d zero-patterns).\n", nWords, nOuts, nWords*64-nLines ); + return vSimO; +} +void Gia_ManReadSimInfoInputs( char * pFileName, char * pFileOut1, int fVerbose ) +{ + Vec_Wrd_t * vSimI; + Vec_WrdReadText2( pFileName, &vSimI ); + Vec_WrdDumpBin( pFileOut1, vSimI, fVerbose ); + Vec_WrdFree( vSimI ); +} +void Gia_ManReadSimInfoOutputs( char * pFileName, char * pFileOut, int nOuts ) +{ + Vec_Wrd_t * vSimO = Vec_WrdReadTextOut( pFileName, nOuts ); + Vec_WrdDumpBin( pFileOut, vSimO, 1 ); + Vec_WrdFree( vSimO ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Vec_WrdZoneExtract( int ZoneSize, Vec_Wrd_t * p, int iWord, int nWords ) +{ + int z, nZones = Vec_WrdSize(p)/ZoneSize; + int w, Limit = Abc_MinInt( nWords, ZoneSize-iWord ); + Vec_Wrd_t * pNew = Vec_WrdStart( nZones*nWords ); + for ( z = 0; z < nZones; z++ ) + for ( w = 0; w < Limit; w++ ) + Vec_WrdWriteEntry( pNew, z*nWords + w, Vec_WrdEntry(p, z*ZoneSize + iWord + w) ); + return pNew; +} +void Vec_WrdZoneInsert( Vec_Wrd_t * pNew, int ZoneSize, Vec_Wrd_t * p, int iWord, int nWords ) +{ + int z, nZones = Vec_WrdSize(pNew)/ZoneSize; + int w, Limit = Abc_MinInt( nWords, ZoneSize-iWord ); + for ( z = 0; z < nZones; z++ ) + for ( w = 0; w < Limit; w++ ) + Vec_WrdWriteEntry( pNew, z*ZoneSize + iWord + w, Vec_WrdEntry(p, z*nWords + w) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimInfoPrintOne( Gia_Man_t * p, Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nWords, int nPats ) +{ + int Id, i, k; + for ( k = 0; k < nPats; k++ ) + { + Gia_ManForEachCiId( p, Id, i ) + // printf( "%d", Vec_WrdEntry(p->vSims, p->nSimWords*Id) & 1 ); + printf( "%d", (int)(Vec_WrdEntry(vSimsIn, nWords*i) >> k) & 1 ); + printf( " " ); + Gia_ManForEachCoId( p, Id, i ) + // printf( "%d", Vec_WrdEntry(p->vSims, p->nSimWords*Id) & 1 ); + printf( "%d", (int)(Vec_WrdEntry(vSimsOut, nWords*i) >> k) & 1 ); + printf( "\n" ); + } +} +Vec_Wrd_t * Gia_ManSimInfoTryOne( Gia_Man_t * p, Vec_Wrd_t * vSimI, int fPrint ) +{ + extern Vec_Wrd_t * Gia_ManSimulateWordsOut( Gia_Man_t * p, Vec_Wrd_t * vSimsIn ); + Vec_Wrd_t * vSimsOut = Gia_ManSimulateWordsOut( p, vSimI ); + int nWords = Vec_WrdSize(vSimI) / Gia_ManCiNum(p); + assert( Vec_WrdSize(vSimI) % Gia_ManCiNum(p) == 0 ); + if ( fPrint ) + Gia_ManSimInfoPrintOne( p, vSimI, vSimsOut, nWords, 6 ); + return vSimsOut; +} +int Gia_ManSimEvalOne( Gia_Man_t * p, Vec_Wrd_t * vSimO, Vec_Wrd_t * vSimO_new ) +{ + int i, Count = 0, nWords = Vec_WrdSize(vSimO) / Gia_ManCoNum(p); + word * pSim0 = ABC_CALLOC( word, nWords ); + assert( Vec_WrdSize(vSimO) == Vec_WrdSize(vSimO_new) ); + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + { + word * pSimGold = Vec_WrdEntryP( vSimO, i * nWords ); + word * pSimImpl = Vec_WrdEntryP( vSimO_new, i * nWords ); + Abc_TtOrXor( pSim0, pSimImpl, pSimGold, nWords ); + } + Count = Abc_TtCountOnesVec( pSim0, nWords ); + printf( "Number of failed patterns is %d (%8.4f %% of %d). The first one is %d.\n", + Count, 100.0*Count/(64*nWords), 64*nWords, Abc_TtFindFirstBit2(pSim0, nWords) ); + ABC_FREE( pSim0 ); + return Count; +} +int Gia_ManSimEvalOne2( Gia_Man_t * p, Vec_Wrd_t * vSimO, Vec_Wrd_t * vSimO_new ) +{ + int i, Count = 0, nWords = Vec_WrdSize(vSimO) / Gia_ManCoNum(p); + word * pSim0 = ABC_CALLOC( word, nWords ); + assert( Vec_WrdSize(vSimO) == Vec_WrdSize(vSimO_new) ); + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + { + word * pSimGold = Vec_WrdEntryP( vSimO, i * nWords ); + word * pSimImpl = Vec_WrdEntryP( vSimO_new, i * nWords ); + Abc_TtXor( pSim0, pSimImpl, pSimGold, nWords, 0 ); + Count += Abc_TtCountOnesVec( pSim0, nWords ); + } + printf( "Number of failed patterns is %d (%8.4f %% of %d). The first one is %d.\n", + Count, 100.0*Count/(64*nWords*Gia_ManCoNum(p)), 64*nWords*Gia_ManCoNum(p), Abc_TtFindFirstBit2(pSim0, nWords) ); + ABC_FREE( pSim0 ); + return Count; +} +int Gia_ManSimEvalMaxValue( Vec_Wrd_t * vSimO, int nWords, int nOuts, int nBits, int iPat ) +{ + int o, ValueMax = -1, OutMax = -1; + for ( o = 0; o < nOuts; o++ ) + { + int i, Value = 0; + for ( i = 0; i < nBits; i++ ) + { + word * pSim = Vec_WrdEntryP( vSimO, (o*nBits+i) * nWords ); + if ( Abc_TtGetBit(pSim, iPat) ) + Value |= 1 << i; + } + if ( ValueMax <= Value ) + { + ValueMax = Value; + OutMax = o; + } + } + return OutMax; +} +int Gia_ManSimEvalOne3( Gia_Man_t * p, Vec_Wrd_t * vSimO, Vec_Int_t * vValues, int nBits ) +{ + int i, Value, nOuts = Gia_ManCoNum(p) / nBits; + int First = -1, Count = 0, nWords = Vec_WrdSize(vSimO) / Gia_ManCoNum(p); + assert( Gia_ManCoNum(p) % nBits == 0 ); + assert( 64*(nWords-1) < Vec_IntSize(vValues) && Vec_IntSize(vValues) <= 64*nWords ); + Vec_IntForEachEntry( vValues, Value, i ) + if ( Value == Gia_ManSimEvalMaxValue(vSimO, nWords, nOuts, nBits, i) ) + { + Count++; + if ( First == -1 ) + First = i; + } + printf( "The accuracy is %8.4f %% (%d out of %d output are correct, for example, output number %d).\n", + 100.0*Count/Vec_IntSize(vValues), Count, Vec_IntSize(vValues), First ); + if ( 0 ) + { + FILE * pTable = fopen( "stats.txt", "a+" ); + fprintf( pTable, "%0.2f \n", 100.0*Count/Vec_IntSize(vValues) ); + fclose( pTable ); + } + return Count; +} +Vec_Wrd_t * Gia_ManSimInfoTry( Gia_Man_t * p, Vec_Wrd_t * vSimI ) +{ + int nWords = Vec_WrdSize(vSimI) / Gia_ManCiNum(p); + int w, nWordsOne = 200, nWordBatches = (nWords + nWordsOne - 1)/nWordsOne; + Vec_Wrd_t * vSimO_new = Vec_WrdStart( nWords * Gia_ManCoNum(p) ); + for ( w = 0; w < nWordBatches; w++ ) + { + //int Value = printf( "%3d / %3d : ", w, nWordBatches ); + Vec_Wrd_t * vSimI_ = Vec_WrdZoneExtract( nWords, vSimI, w*nWordsOne, nWordsOne ); + Vec_Wrd_t * vSimO_ = Gia_ManSimInfoTryOne( p, vSimI_, 0 ); + Vec_WrdZoneInsert( vSimO_new, nWords, vSimO_, w*nWordsOne, nWordsOne ); + Vec_WrdFree( vSimI_ ); + Vec_WrdFree( vSimO_ ); + //Value = 0; + } + return vSimO_new; +} +int Gia_ManSimInfoEval_old( Gia_Man_t * p, Vec_Wrd_t * vSimO, Vec_Wrd_t * vSimO_new ) +{ + int nResult = Gia_ManSimEvalOne2(p, vSimO, vSimO_new); + //Vec_WrdDumpBin( "temp.simo", vSimO_new, 1 ); + printf( "Total errors = %d. ", nResult ); + printf( "Density of output patterns %8.4f.\n", (float)Abc_TtCountOnesVec(Vec_WrdArray(vSimO_new), Vec_WrdSize(vSimO_new))/(64*Vec_WrdSize(vSimO_new)) ); + return nResult; +} +void Gia_ManSimInfoPassTest( Gia_Man_t * p, char * pFileName, char * pFileName2, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Vec_Wrd_t * vSimI = Vec_WrdReadBin( pFileName, fVerbose ); + Vec_Wrd_t * vSimO = Gia_ManSimInfoTry( p, vSimI ); + if ( fVerbose ) + printf( "Density of input patterns %8.4f.\n", (float)Abc_TtCountOnesVec(Vec_WrdArray(vSimI), Vec_WrdSize(vSimI))/(64*Vec_WrdSize(vSimI)) ); + if ( fVerbose ) + printf( "Density of output patterns %8.4f.\n", (float)Abc_TtCountOnesVec(Vec_WrdArray(vSimO), Vec_WrdSize(vSimO))/(64*Vec_WrdSize(vSimO)) ); + Vec_WrdDumpBin( pFileName2, vSimO, fVerbose ); + Vec_WrdFree( vSimI ); + Vec_WrdFree( vSimO ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} +void Gia_ManSimInfoEval( Gia_Man_t * p, char * pFileName, char * pFileName2, int nOuts, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Vec_Wrd_t * vSim1 = Vec_WrdReadBin( pFileName, fVerbose ); + Vec_Int_t * vNums = Vec_WrdReadNumsOut( pFileName2, fVerbose ); + assert( nOuts > 0 ); + if ( fVerbose ) + printf( "Density of input patterns %8.4f.\n", (float)Abc_TtCountOnesVec(Vec_WrdArray(vSim1), Vec_WrdSize(vSim1))/(64*Vec_WrdSize(vSim1)) ); + Gia_ManSimEvalOne3( p, vSim1, vNums, nOuts ); + Vec_WrdFree( vSim1 ); + Vec_IntFree( vNums ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word * Gia_ManCountFraction( Gia_Man_t * p, Vec_Wrd_t * vSimI, Vec_Int_t * vSupp, int Thresh, int fVerbose, int * pCare ) +{ + Gia_Obj_t * pObj; + int i, k, nUsed = 0, nGood = 0; + int nWords = Vec_WrdSize(vSimI) / Gia_ManCiNum(p); + int nMints = 1 << Vec_IntSize(vSupp); + word ** pSims = ABC_ALLOC( word *, Vec_IntSize(vSupp) ); + word * pRes = ABC_CALLOC( word, Abc_Truth6WordNum(Vec_IntSize(vSupp)) ); + int * pCounts = ABC_CALLOC( int, nMints ); + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + pSims[i] = Vec_WrdEntryP( vSimI, Gia_ObjCioId(pObj) * nWords ); + for ( k = 0; k < 64*nWords; k++ ) + { + int iMint = 0; + for ( i = 0; i < Vec_IntSize(vSupp); i++ ) + if ( Abc_TtGetBit(pSims[i], k) ) + iMint |= 1 << i; + assert( iMint < nMints ); + pCounts[iMint]++; + } + for ( k = 0; k < nMints; k++ ) + { + nUsed += (pCounts[k] > 0); + nGood += (pCounts[k] >= Thresh); + if ( pCounts[k] >= Thresh ) + Abc_TtXorBit( pRes, k ); + //printf( "%d ", pCounts[k] ); + } + if ( Vec_IntSize(vSupp) < 6 ) + pRes[0] = Abc_Tt6Stretch( pRes[0], Vec_IntSize(vSupp) ); + //printf( "\n" ); + if ( fVerbose ) + printf( "Used %4d and good %4d (out of %4d).\n", nUsed, nGood, nMints ); + ABC_FREE( pSims ); + ABC_FREE( pCounts ); + *pCare = nGood; + return pRes; +} +void Gia_ManPermuteSupp_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vLevels, Vec_Int_t * vCounts ) +{ + Gia_Obj_t * pObj; int n; + if ( !iObj || Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManPermuteSupp_rec( p, Gia_ObjFaninId0(pObj, iObj), vLevels, vCounts ); + Gia_ManPermuteSupp_rec( p, Gia_ObjFaninId1(pObj, iObj), vLevels, vCounts ); + for ( n = 0; n < 2; n++ ) + { + Gia_Obj_t * pFanin = n ? Gia_ObjFanin1(pObj) : Gia_ObjFanin0(pObj); + if ( !Gia_ObjIsCi(pFanin) ) + continue; + Vec_IntAddToEntry( vLevels, Gia_ObjCioId(pFanin), Gia_ObjLevel(p, pObj) ); + Vec_IntAddToEntry( vCounts, Gia_ObjCioId(pFanin), 1 ); + } +} +void Gia_ManPermuteSupp( Gia_Man_t * p, int iOut, int nOuts, Vec_Int_t * vSupp ) +{ + Vec_Int_t * vLevels = Vec_IntStart( Gia_ManCiNum(p) ); + Vec_Int_t * vCounts = Vec_IntStart( Gia_ManCiNum(p) ); + int i, * pCost = ABC_CALLOC( int, Gia_ManCiNum(p) ); + Gia_Obj_t * pObj; + Gia_ManIncrementTravId( p ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManPermuteSupp_rec( p, Gia_ObjFaninId0p(p, Gia_ManCo(p, iOut+i)), vLevels, vCounts ); + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + pCost[i] = 10000 * Vec_IntEntry(vLevels, Gia_ObjCioId(pObj)) / Abc_MaxInt(1, Vec_IntEntry(vCounts, Gia_ObjCioId(pObj))); + Vec_IntFree( vCounts ); + Vec_IntFree( vLevels ); + Vec_IntSelectSortCost2( Vec_IntArray(vSupp), Vec_IntSize(vSupp), pCost ); + assert( Vec_IntSize(vSupp) < 2 || pCost[0] <= pCost[1] ); + ABC_FREE( pCost ); +} +void Gia_ManCollectSupp_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vSupp ) +{ + Gia_Obj_t * pObj; + if ( !iObj || Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + { + //Vec_IntPush( vSupp, Gia_ObjCioId(pObj) ); + Vec_IntPush( vSupp, Gia_ObjId(p, pObj) ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManCollectSupp_rec( p, Gia_ObjFaninId0(pObj, iObj), vSupp ); + Gia_ManCollectSupp_rec( p, Gia_ObjFaninId1(pObj, iObj), vSupp ); +} +Vec_Int_t * Gia_ManCollectSupp( Gia_Man_t * p, int iOut, int nOuts ) +{ + Vec_Int_t * vSupp = Vec_IntAlloc( 16 ); int i; + Gia_ManIncrementTravId( p ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManCollectSupp_rec( p, Gia_ObjFaninId0p(p, Gia_ManCo(p, iOut+i)), vSupp ); + return vSupp; +} +Vec_Int_t * Gia_ManCollectSuppNew( Gia_Man_t * p, int iOut, int nOuts ) +{ + Vec_Int_t * vRes = Gia_ManCollectSupp( p, iOut, nOuts ); + Gia_ManPermuteSupp( p, iOut, nOuts, vRes ); + return vRes; +} +int Gia_ManPerformLNetOpt_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return pObj->Value; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManPerformLNetOpt_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManPerformLNetOpt_rec( pNew, p, Gia_ObjFanin1(pObj) ); + return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManPerformLNetOpt( Gia_Man_t * p, int fTryNew, char * pFileName, int nIns, int nOuts, int Thresh, int nRounds, int fVerbose ) +{ + extern Gia_Man_t * Gia_TryPermOpt( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ); + extern Gia_Man_t * Gia_TryPermOptCare( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ); + extern int Kit_TruthToGia2( Gia_Man_t * p, unsigned * pTruth0, unsigned * pTruth1, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); + abctime clk = Abc_Clock(); + Gia_Man_t * pNew; Gia_Obj_t * pObj; + Vec_Int_t * vMemory = Vec_IntAlloc( 1 << 18 ); + Vec_Int_t * vLeaves = Vec_IntAlloc( nIns ); + Vec_Wrd_t * vSimI = pFileName ? Vec_WrdReadBin( pFileName, fVerbose ) : NULL; + word * pTruth0 = ABC_CALLOC( word, Abc_Truth6WordNum(nIns) ); + word * pTruth1 = ABC_CALLOC( word, Abc_Truth6WordNum(nIns) ); int g, k; float CareAve = 0; + word * pTruthsTry = ABC_CALLOC( word, 2*nOuts*Abc_Truth6WordNum(nIns) ); + if ( vSimI && fVerbose ) + { + //int nPats = 64*Vec_WrdSize(vSimI)/Gia_ManCiNum(p); + printf( "Density of input patterns %8.4f.\n", (float)Abc_TtCountOnesVec(Vec_WrdArray(vSimI), Vec_WrdSize(vSimI))/(64*Vec_WrdSize(vSimI)) ); + printf( "Using patterns with count %d and higher as cares.\n", Thresh ); + } + Gia_ManLevelNum( p ); + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, k ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ObjComputeTruthTableStart( p, nIns ); + Gia_ManHashStart( pNew ); + for ( g = 0; g < Gia_ManCoNum(p); g += nOuts ) + { + Vec_Int_t * vSupp = Gia_ManCollectSuppNew( p, g, nOuts ); + int Care = 1 << Vec_IntSize(vSupp), Temp = fVerbose ? printf( "Group %3d / %3d / %3d : Supp = %3d %s", g, nOuts, Gia_ManCoNum(p), Vec_IntSize(vSupp), vSimI ? "":"\n" ) : 0; + word * pCare = vSimI ? Gia_ManCountFraction( p, vSimI, vSupp, Thresh, fVerbose, &Care ) : ABC_FALLOC( word, Abc_Truth6WordNum(Vec_IntSize(vSupp)) ); + int nWords = Abc_Truth6WordNum( Vec_IntSize(vSupp) ); + CareAve += 100.0*Care/(1 << Vec_IntSize(vSupp)); + assert( Vec_IntSize(vSupp) <= nIns ); + Vec_IntClear( vLeaves ); + Gia_ManForEachObjVec( vSupp, p, pObj, k ) + Vec_IntPush( vLeaves, pObj->Value ); + for ( k = 0; k < nOuts; k++ ) + { + Gia_Obj_t * pObj = Gia_ManCo( p, g+k ); + word * pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ObjFanin0(pObj), vSupp ); + Abc_TtSharp( pTruth0, pCare, pTruth, nWords ); + Abc_TtAnd( pTruth1, pCare, pTruth, nWords, 0 ); + if ( vSimI ) + { + Abc_TtCopy( pTruthsTry + (2*k+0)*nWords, pTruth1, nWords, 0 ); + Abc_TtCopy( pTruthsTry + (2*k+1)*nWords, pTruth0, nWords, 0 ); + } + else + Abc_TtCopy( pTruthsTry + k*nWords, pTruth1, nWords, 0 ); + if ( !fTryNew ) + { + pObj->Value = Kit_TruthToGia2( pNew, (unsigned *)pTruth0, (unsigned *)pTruth1, Vec_IntSize(vLeaves), vMemory, vLeaves, 1 ); + pObj->Value ^= Gia_ObjFaninC0(pObj); + } + } + if ( fTryNew ) + { + Gia_Man_t * pMin; + if ( vSimI ) + pMin = Gia_TryPermOpt( pTruthsTry, Vec_IntSize(vSupp), 2*nOuts, nWords, nRounds, fVerbose ); + else + pMin = Gia_TryPermOptCare( pTruthsTry, Vec_IntSize(vSupp), nOuts, nWords, nRounds, fVerbose ); + Gia_ManFillValue( pMin ); + Gia_ManConst0(pMin)->Value = 0; + Gia_ManForEachCi( pMin, pObj, k ) + pObj->Value = Vec_IntEntry( vLeaves, k ); + for ( k = 0; k < nOuts; k++ ) + { + Gia_Obj_t * pObj = Gia_ManCo( p, g+k ); + Gia_Obj_t * pObj2 = Gia_ManCo( pMin, k ); + pObj->Value = Gia_ManPerformLNetOpt_rec( pNew, pMin, Gia_ObjFanin0(pObj2) ); + pObj->Value ^= Gia_ObjFaninC0(pObj2); + pObj->Value ^= Gia_ObjFaninC0(pObj); + } + Gia_ManStop( pMin ); + } + ABC_FREE( pCare ); + Vec_IntFree( vSupp ); + Temp = 0; + } + CareAve /= Gia_ManCoNum(p)/nOuts; + Gia_ManHashStop( pNew ); + Gia_ManForEachCo( p, pObj, k ) + pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); + Gia_ObjComputeTruthTableStop( p ); + ABC_FREE( pTruth0 ); + ABC_FREE( pTruth1 ); + Vec_IntFree( vLeaves ); + Vec_IntFree( vMemory ); + Vec_WrdFreeP( &vSimI ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + printf( "Using patterns with count %d and higher as cares. Average care set is %8.4f %%. ", Thresh, CareAve ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + if ( 0 ) + { + FILE * pTable = fopen( "stats.txt", "a+" ); + fprintf( pTable, "%0.2f ", CareAve ); + fclose( pTable ); + } + ABC_FREE( pTruthsTry ); + return pNew; +} +Gia_Man_t * Gia_ManPerformLNetOptNew( Gia_Man_t * p, char * pFileName, int nIns, int nOuts, int Thresh, int nRounds, int fVerbose ) +{ + extern Gia_Man_t * Gia_TryPermOptNew( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ); + abctime clk = Abc_Clock(); + Gia_Man_t * pNew, * pMin; Gia_Obj_t * pObj; + Vec_Int_t * vLeaves = Vec_IntAlloc( nIns ); + Vec_Wrd_t * vSimI = pFileName ? Vec_WrdReadBin( pFileName, fVerbose ) : NULL; + word * pTruthsTry = ABC_CALLOC( word, (nOuts+1)*Abc_Truth6WordNum(nIns) ); + int k, g; float CareAve = 0; + if ( vSimI && fVerbose ) + { + //int nPats = 64*Vec_WrdSize(vSimI)/Gia_ManCiNum(p); + printf( "Density of input patterns %8.4f.\n", (float)Abc_TtCountOnesVec(Vec_WrdArray(vSimI), Vec_WrdSize(vSimI))/(64*Vec_WrdSize(vSimI)) ); + printf( "Using patterns with count %d and higher as cares.\n", Thresh ); + } + Gia_ManLevelNum( p ); + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, k ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ObjComputeTruthTableStart( p, nIns ); + Gia_ManHashStart( pNew ); + for ( g = 0; g < Gia_ManCoNum(p); g += nOuts ) + { + for ( k = 0; k < nOuts; k++ ) + if ( Gia_ObjIsAnd(Gia_ObjFanin0(Gia_ManCo( p, g+k ))) ) + break; + if ( k == nOuts ) + { + for ( k = 0; k < nOuts; k++ ) + { + Gia_Obj_t * pObj = Gia_ManCo( p, g+k ); + pObj->Value = Gia_ObjFanin0Copy(pObj); + } + continue; + } + else + { + + Vec_Int_t * vSupp = Gia_ManCollectSuppNew( p, g, nOuts ); + int Care = 1 << Vec_IntSize(vSupp), Temp = fVerbose ? printf( "Group %3d / %3d / %3d : Supp = %3d %s", g, nOuts, Gia_ManCoNum(p), Vec_IntSize(vSupp), vSimI ? "":"\n" ) : 0; + word * pCare = vSimI ? Gia_ManCountFraction( p, vSimI, vSupp, Thresh, fVerbose, &Care ) : ABC_FALLOC( word, Abc_Truth6WordNum(Vec_IntSize(vSupp)) ); + int nWords = Abc_Truth6WordNum( Vec_IntSize(vSupp) ); + CareAve += 100.0*Care/(1 << Vec_IntSize(vSupp)); + assert( Vec_IntSize(vSupp) <= nIns ); + Vec_IntClear( vLeaves ); + Gia_ManForEachObjVec( vSupp, p, pObj, k ) + Vec_IntPush( vLeaves, pObj->Value ); + for ( k = 0; k < nOuts; k++ ) + { + Gia_Obj_t * pObj = Gia_ManCo( p, g+k ); + word * pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ObjFanin0(pObj), vSupp ); + Abc_TtCopy( pTruthsTry + k*nWords, pTruth, nWords, Gia_ObjFaninC0(pObj) ); + } + Abc_TtCopy( pTruthsTry + nOuts*nWords, pCare, nWords, 0 ); + ABC_FREE( pCare ); + pMin = Gia_TryPermOptNew( pTruthsTry, Vec_IntSize(vSupp), nOuts, nWords, nRounds, fVerbose ); + Gia_ManFillValue( pMin ); + Gia_ManConst0(pMin)->Value = 0; + Gia_ManForEachCi( pMin, pObj, k ) + pObj->Value = Vec_IntEntry( vLeaves, k ); + Gia_ManForEachCo( pMin, pObj, k ) + { + Gia_Obj_t * pObj0 = Gia_ManCo( p, g+k ); + pObj0->Value = Gia_ManPerformLNetOpt_rec( pNew, pMin, Gia_ObjFanin0(pObj) ); + pObj0->Value ^= Gia_ObjFaninC0(pObj); + } + Gia_ManStop( pMin ); + Vec_IntFree( vSupp ); + Temp = 0; + + } + } + CareAve /= Gia_ManCoNum(p)/nOuts; + Gia_ManHashStop( pNew ); + Gia_ManForEachCo( p, pObj, k ) + pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); + Gia_ObjComputeTruthTableStop( p ); + Vec_IntFree( vLeaves ); + Vec_WrdFreeP( &vSimI ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + printf( "Using patterns with count %d and higher as cares. Average care set is %8.4f %%. ", Thresh, CareAve ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + if ( 0 ) + { + FILE * pTable = fopen( "stats.txt", "a+" ); + fprintf( pTable, "%0.2f ", CareAve ); + fclose( pTable ); + } + ABC_FREE( pTruthsTry ); + return pNew; +} + +#ifdef ABC_USE_CUDD + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDoMuxMapping( Gia_Man_t * p ) +{ + extern Gia_Man_t * Gia_ManPerformMfs( Gia_Man_t * p, Sfm_Par_t * pPars ); + Gia_Man_t * pTemp, * pNew = Gia_ManDup( p ); + Jf_Par_t Pars, * pPars = &Pars; int c, nIters = 2; + Sfm_Par_t Pars2, * pPars2 = &Pars2; + Lf_ManSetDefaultPars( pPars ); + Sfm_ParSetDefault( pPars2 ); + pPars2->nTfoLevMax = 5; + pPars2->nDepthMax = 100; + pPars2->nWinSizeMax = 2000; + for ( c = 0; c < nIters; c++ ) + { + pNew = Lf_ManPerformMapping( pTemp = pNew, pPars ); + Gia_ManStop( pTemp ); + pNew = Gia_ManPerformMfs( pTemp = pNew, pPars2 ); + Gia_ManStop( pTemp ); + if ( c == nIters-1 ) + break; + pNew = (Gia_Man_t *)Dsm_ManDeriveGia( pTemp = pNew, 0 ); + Gia_ManStop( pTemp ); + } + return pNew; +} +Gia_Man_t * Gia_ManDoMuxTransform( Gia_Man_t * p, int fReorder ) +{ + extern Gia_Man_t * Abc_NtkStrashToGia( Abc_Ntk_t * pNtk ); + extern int Abc_NtkBddToMuxesPerformGlo( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int Limit, int fReorder, int fUseAdd ); + Gia_Man_t * pRes = NULL; + Aig_Man_t * pMan = Gia_ManToAig( p, 0 ); + Abc_Ntk_t * pNtk = Abc_NtkFromAigPhase( pMan ); + Abc_Ntk_t * pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + pNtk->pName = Extra_UtilStrsav( pMan->pName ); + Aig_ManStop( pMan ); + //pNtkNew = Abc_NtkBddToMuxes( pNtk, 1, 1000000, 1 ); + if ( Abc_NtkBddToMuxesPerformGlo( pNtk, pNtkNew, 1000000, fReorder, 0 ) ) + { + Abc_Ntk_t * pStrash = Abc_NtkStrash( pNtkNew, 1, 1, 0 ); + pRes = Abc_NtkStrashToGia( pStrash ); + Abc_NtkDelete( pStrash ); + } + Abc_NtkDelete( pNtkNew ); + Abc_NtkDelete( pNtk ); + return pRes; +} +int Gia_ManDoTest1( Gia_Man_t * p, int fReorder ) +{ + Gia_Man_t * pTemp, * pNew; int Res; + pNew = Gia_ManDoMuxTransform( p, fReorder ); + pNew = Gia_ManDoMuxMapping( pTemp = pNew ); + Gia_ManStop( pTemp ); + Res = Gia_ManLutNum( pNew ); + Gia_ManStop( pNew ); + return Res; +} +Abc_Ntk_t * Gia_ManDoTest2( Gia_Man_t * p, int fReorder, int fTryNew ) +{ + extern Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p, int fFindEnables, int fUseBuffs ); + Abc_Ntk_t * pNtkNew; + Gia_Man_t * pTemp, * pNew; + pNew = fTryNew ? Gia_ManDup(p) : Gia_ManDoMuxTransform( p, fReorder ); + pNew = Gia_ManDoMuxMapping( pTemp = pNew ); + Gia_ManStop( pTemp ); + pNtkNew = Abc_NtkFromMappedGia( pNew, 0, 0 ); + pNtkNew->pName = Extra_UtilStrsav(p->pName); + Gia_ManStop( pNew ); + Abc_NtkToSop( pNtkNew, 1, ABC_INFINITY ); + return pNtkNew; +} +Abc_Ntk_t * Abc_NtkMapTransform( Gia_Man_t * p, int nOuts, int fUseFixed, int fTryNew, int fVerbose ) +{ + extern Abc_Ntk_t * Abc_NtkSpecialMapping( Abc_Ntk_t * pNtk, int fVerbose ); + int i, k, g, nGroups = Gia_ManCoNum(p) / nOuts, CountsAll[3] = {0}; + Abc_Obj_t * pObjNew, * pFaninNew; Gia_Obj_t * pObj; + Abc_Ntk_t * pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + assert( Gia_ManCoNum(p) % nOuts == 0 ); + pNtkNew->pName = Extra_UtilStrsav(p->pName); + pNtkNew->pSpec = Extra_UtilStrsav(p->pSpec); + Gia_ManFillValue( p ); + Gia_ManForEachPi( p, pObj, i ) + Abc_NtkCreatePi( pNtkNew ); + Gia_ManForEachPo( p, pObj, i ) + Abc_NtkCreatePo( pNtkNew ); + assert( nOuts <= 64 ); + for ( g = 0; g < nGroups; g++ ) + { + Gia_Man_t * pNew; Aig_Man_t * pMan; + Abc_Ntk_t * pNtk, * pNtkRes, * pNtkMap; + int pPos[64], Counter = 0, Counts[3] = {0}; + for ( i = 0; i < nOuts; i++ ) + pPos[i] = g*nOuts+i; + pNew = Gia_ManDupCones( p, pPos, nOuts, 1 ); + if ( !fUseFixed ) + pNtkMap = Gia_ManDoTest2( pNew, 1, fTryNew ); + else + { + pMan = Gia_ManToAig( pNew, 0 ); + pNtk = Abc_NtkFromAigPhase( pMan ); + Aig_ManStop( pMan ); + pNtkRes = Abc_NtkBddToMuxes( pNtk, 1, 1000000, 1 ); + Abc_NtkDelete( pNtk ); + pNtkMap = Abc_NtkSpecialMapping( pNtkRes, 0 ); + Abc_NtkDelete( pNtkRes ); + } + Gia_ManStop( pNew ); + Gia_ManForEachCi( p, pObj, i ) + if ( ~pObj->Value ) + Abc_NtkCi(pNtkMap, Counter++)->pCopy = Abc_NtkCi(pNtkNew, i); + assert( Counter == Abc_NtkCiNum(pNtkMap) ); + Abc_NtkForEachNode( pNtkMap, pObjNew, i ) + { + pObjNew->pCopy = Abc_NtkDupObj( pNtkNew, pObjNew, 0 ); + pObjNew->pCopy->fPersist = pObjNew->fPersist; + if ( pObjNew->fPersist ) + Counts[1]++; + else + Counts[0]++; + Abc_ObjForEachFanin( pObjNew, pFaninNew, k ) + Abc_ObjAddFanin( pObjNew->pCopy, pFaninNew->pCopy ); + } + Abc_NtkForEachCo( pNtkMap, pObjNew, i ) + Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, g*nOuts+i), Abc_ObjFanin0(pObjNew)->pCopy ); + Abc_NtkDelete( pNtkMap ); + + if ( fVerbose ) + { + printf( "%3d / %3d : ", g, nGroups ); + printf( "Test = %4d ", Counts[0] ); + printf( "MarkA = %4d ", Counts[1] ); + printf( "MarkB = %4d ", Counts[2] ); + printf( "\n" ); + } + + CountsAll[0] += Counts[0]; + CountsAll[1] += Counts[1]; + CountsAll[2] += Counts[2]; + } + if ( fVerbose ) + printf( "Total LUT count = %5d. MarkA = %5d. MarkB = %5d.\n", CountsAll[0], CountsAll[1], CountsAll[2] ); + // create names + Abc_NtkAddDummyPiNames( pNtkNew ); + Abc_NtkAddDummyPoNames( pNtkNew ); + Abc_NtkAddDummyBoxNames( pNtkNew ); + // check the resulting AIG + if ( !Abc_NtkCheck( pNtkNew ) ) + Abc_Print( 1, "Abc_NtkFromMappedGia(): Network check has failed.\n" ); + return pNtkNew; +} + +Abc_Ntk_t * Gia_ManPerformLNetMap( Gia_Man_t * p, int GroupSize, int fUseFixed, int fTryNew, int fVerbose ) +{ + int fPrintOnly = 0; + int Res1, Res2, Result = 0; + int g, nGroups = Gia_ManCoNum(p) / GroupSize; + assert( Gia_ManCoNum(p) % GroupSize == 0 ); + assert( GroupSize <= 64 ); + if ( fPrintOnly ) + { + for ( g = 0; g < nGroups; g++ ) + { + Gia_Man_t * pNew; + int o, pPos[64]; + for ( o = 0; o < GroupSize; o++ ) + pPos[o] = g*GroupSize+o; + pNew = Gia_ManDupCones( p, pPos, GroupSize, 0 ); + printf( "%3d / %3d : ", g, nGroups ); + printf( "Test1 = %4d ", Res1 = Gia_ManDoTest1(pNew, 0) ); + printf( "Test2 = %4d ", Res2 = Gia_ManDoTest1(pNew, 1) ); + printf( "Test = %4d ", Abc_MinInt(Res1, Res2) ); + printf( "\n" ); + Result += Abc_MinInt(Res1, Res2); + //Gia_ManPrintStats( pNew, NULL ); + Gia_ManStop( pNew ); + } + printf( "Total LUT count = %d.\n", Result ); + return NULL; + + } + return Abc_NtkMapTransform( p, GroupSize, fUseFixed, fTryNew, fVerbose ); +} + +#else + +Abc_Ntk_t * Gia_ManPerformLNetMap( Gia_Man_t * p, int GroupSize, int fUseFixed, int fTryNew, int fVerbose ) +{ + return NULL; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/gia/giaMinLut2.c b/src/aig/gia/giaMinLut2.c new file mode 100644 index 00000000..85cae0d2 --- /dev/null +++ b/src/aig/gia/giaMinLut2.c @@ -0,0 +1,1372 @@ +/**CFile**************************************************************** + + FileName [giaMinLut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Collapsing AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaMinLut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "giaAig.h" +#include "base/main/mainInt.h" +#include "opt/sfm/sfm.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define TREE_MAX_VARS 16 + +typedef struct Tree_Sto_t_ Tree_Sto_t; +struct Tree_Sto_t_ +{ + int nIns; + int nOuts; + int pTried[TREE_MAX_VARS]; + int pPerm[TREE_MAX_VARS]; + int pIPerm[TREE_MAX_VARS]; + int nNodes[TREE_MAX_VARS]; + Vec_Int_t vCofs[TREE_MAX_VARS]; + word * pMem; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Tree_Sto_t * Gia_ManTreeDup( Tree_Sto_t * p ) +{ + Tree_Sto_t * pSto = ABC_CALLOC( Tree_Sto_t, 1 ); + int i, k, Obj; + *pSto = *p; + pSto->pMem = Abc_TtDup( pSto->pMem, p->nOuts*Abc_TtWordNum(p->nIns), 0 ); + memset( pSto->vCofs, 0, sizeof(Vec_Int_t)*TREE_MAX_VARS ); + for ( i = 0; i < TREE_MAX_VARS; i++ ) + Vec_IntForEachEntry( p->vCofs+i, Obj, k ) + Vec_IntPush( pSto->vCofs+i, Obj ); + return pSto; +} +void Gia_ManTreeFree( Tree_Sto_t * p ) +{ + int i; + for ( i = 0; i < TREE_MAX_VARS; i++ ) + ABC_FREE( p->vCofs[i].pArray ); + ABC_FREE( p->pMem ); + ABC_FREE( p ); +} +int Gia_ManTreeCountNodes( Tree_Sto_t * p ) +{ + int i, nNodes = 0; + for ( i = 0; i < TREE_MAX_VARS; i++ ) + nNodes += p->nNodes[i]; + return nNodes; +} +void Gia_ManTreePrint( Tree_Sto_t * p ) +{ + int i; + printf( "Tree with %d nodes:\n", Gia_ManTreeCountNodes(p) ); + for ( i = p->nIns-1; i >= 0; i-- ) + printf( "Level %2d Var %2d : %s Nodes = %3d Cofs = %3d\n", + i, p->pIPerm[i], p->pTried[i]?"*":" ", p->nNodes[i], Vec_IntSize(p->vCofs+i) ); +// for ( i = p->nIns-1; i >= 0; i-- ) +// printf( "Var %2d Level %2d\n", i, p->pPerm[i] ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFindOrAddNode( Tree_Sto_t * pSto, int iVar, int Truth, word * pCof ) +{ + int k, Obj; + if ( iVar > 5 ) + { + int nWords = Abc_TtWordNum(iVar); + Vec_IntForEachEntry( pSto->vCofs+iVar, Obj, k ) + if ( Abc_TtEqual( pSto->pMem + Obj, pCof, nWords ) ) + return 1; + Vec_IntPush( pSto->vCofs+iVar, pCof - pSto->pMem ); + } + else + { + Vec_IntForEachEntry( pSto->vCofs+iVar, Obj, k ) + if ( Obj == Truth ) + return 1; + Vec_IntPush( pSto->vCofs+iVar, Truth ); + } + return 0; +} +int Gia_ManProcessLevel( Tree_Sto_t * pSto, int iVar ) +{ + int k, Obj, nNodes = 0; + //Vec_IntPrint( pSto->vCofs+iVar ); + Vec_IntClear( pSto->vCofs+iVar ); + if ( iVar > 5 ) + { + int nWords = Abc_TtWordNum(iVar); + Vec_IntForEachEntry( pSto->vCofs+iVar+1, Obj, k ) + { + word * pCof0 = pSto->pMem + Obj; + word * pCof1 = pCof0 + nWords; + Gia_ManFindOrAddNode( pSto, iVar, -1, pCof0 ); + if ( Abc_TtEqual( pCof0, pCof1, nWords ) ) + continue; + Gia_ManFindOrAddNode( pSto, iVar, -1, pCof1 ); + nNodes++; + } + } + else + { + Vec_IntForEachEntry( pSto->vCofs+iVar+1, Obj, k ) + { + unsigned Cof0 = iVar < 5 ? Abc_Tt5Cofactor0( Obj, iVar ) : (unsigned) pSto->pMem[Obj]; + unsigned Cof1 = iVar < 5 ? Abc_Tt5Cofactor1( Obj, iVar ) : (unsigned)(pSto->pMem[Obj] >> 32); + Gia_ManFindOrAddNode( pSto, iVar, Cof0, NULL ); + if ( Cof0 == Cof1 ) + continue; + Gia_ManFindOrAddNode( pSto, iVar, Cof1, NULL ); + nNodes++; + } + } + //printf( "Level %2d : Nodes = %3d Cofs = %3d\n", iVar, nNodes, Vec_IntSize(pSto->vCofs+iVar) ); + //Vec_IntPrint( pSto->vCofs+iVar ); + //printf( "\n" ); + return nNodes; +} +Tree_Sto_t * Gia_ManContructTree( word * pTruths, int nIns, int nOuts, int nWords ) +{ + Tree_Sto_t * pSto = ABC_CALLOC( Tree_Sto_t, 1 ); int i; + assert( Abc_TtWordNum(nIns) == nWords ); + assert( nIns+1 <= TREE_MAX_VARS ); + pSto->pMem = Abc_TtDup(pTruths, nOuts*nWords, 0); + pSto->nIns = nIns; + pSto->nOuts = nOuts; + for ( i = 0; i < nIns; i++ ) + pSto->pPerm[i] = pSto->pIPerm[i] = i; + for ( i = 0; i < nOuts; i++ ) + Gia_ManFindOrAddNode( pSto, nIns, (unsigned)pSto->pMem[i], pSto->pMem + i*nWords ); + for ( i = nIns-1; i >= 0; i-- ) + pSto->nNodes[i] = Gia_ManProcessLevel( pSto, i ); + return pSto; +} +void Gia_ManContructTreeTest( word * pTruths, int nIns, int nOuts, int nWords ) +{ + Tree_Sto_t * pSto = Gia_ManContructTree( pTruths, nIns, nOuts, nWords ); + printf( "Total nodes = %d.\n", Gia_ManTreeCountNodes(pSto) ); + Gia_ManTreeFree( pSto ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSwapTree( Tree_Sto_t * pSto, int i ) +{ + int nNodes = pSto->nNodes[i+1] + pSto->nNodes[i]; + int v, o, nWords = Abc_TtWordNum(pSto->nIns); + //printf( "Swapping %2d and %2d ", i, i+1 ); + assert( i >= 0 && i < pSto->nIns-1 ); + for ( o = 0; o < pSto->nOuts; o++ ) + Abc_TtSwapAdjacent( pSto->pMem + o*nWords, nWords, i ); + for ( v = 5; v > i+1; v-- ) + pSto->nNodes[v] = Gia_ManProcessLevel( pSto, v ); + pSto->nNodes[i+1] = Gia_ManProcessLevel( pSto, i+1 ); + pSto->nNodes[i] = Gia_ManProcessLevel( pSto, i ); + ABC_SWAP( int, pSto->pTried[i], pSto->pTried[i+1] ); + ABC_SWAP( int, pSto->pIPerm[i], pSto->pIPerm[i+1] ); + pSto->pPerm[pSto->pIPerm[i+1]] = i+1; + pSto->pPerm[pSto->pIPerm[i]] = i; + return pSto->nNodes[i+1] + pSto->nNodes[i] - nNodes; +} +int Gia_ManFindBestPosition( word * pTruths, int nIns, int nOuts, int nWords, word * pStore, int fMoveMore, int * pnNodesMin, int fVerbose ) +{ + Tree_Sto_t * pSto = Gia_ManContructTree( pTruths, nIns, nOuts, nWords ); + //int v, vBest = nIns-1, nNodesCur = Gia_ManTreeCountNodes(pSto), nNodesMin = nNodesCur; + int v, vBest = -1, nNodesCur = Gia_ManTreeCountNodes(pSto), nNodesMin = ABC_INFINITY; + if ( fVerbose ) + Gia_ManTreePrint( pSto ); + Abc_TtCopy( pStore+(nIns-1)*nOuts*nWords, pSto->pMem, nOuts*nWords, 0 ); + for ( v = nIns-2; v >= 0; v-- ) + { + nNodesCur += Gia_ManSwapTree( pSto, v ); + if ( fMoveMore ? nNodesMin >= nNodesCur : nNodesMin > nNodesCur ) + { + nNodesMin = nNodesCur; + vBest = v; + } + if ( fVerbose ) + printf( "Level %2d -> %2d : Nodes = %4d. ", v+1, v, nNodesCur ); + Abc_TtCopy( pStore+v*nOuts*nWords, pSto->pMem, nOuts*nWords, 0 ); + if ( fVerbose ) + Gia_ManContructTreeTest( pSto->pMem, nIns, nOuts, nWords ); + } + assert( vBest != nIns-1 ); + Gia_ManTreeFree( pSto ); + if ( fVerbose ) + printf( "Best level = %d. Best nodes = %d.\n", vBest, nNodesMin ); + if ( pnNodesMin ) + *pnNodesMin = nNodesMin; + return vBest; +} +void Gia_ManPermStats( int nIns, int * pIPerm, int * pTried ) +{ + int v; + for ( v = nIns-1; v >= 0; v-- ) + printf( "Level = %2d : Var = %2d Tried = %2d\n", v, pIPerm[v], pTried[v] ); + printf( "\n" ); +} +int Gia_ManPermuteTreeOne( word * pTruths, int nIns, int nOuts, int nWords, int fRandom, int * pIPermOut, int fVeryVerbose, int fVerbose ) +{ + extern void Gia_ManDumpMuxes( Tree_Sto_t * p, char * pFileName, int * pIPerm ); + word * pStore = ABC_ALLOC( word, nIns*nOuts*nWords ); + int pTried[TREE_MAX_VARS] = {0}; + int pIPerm[TREE_MAX_VARS] = {0}; + int v, r, Pos, nNodesPrev = -1, nNodesMin = 0, nNoChange = 0; + int nNodesBeg, nNodesEnd; + Tree_Sto_t * pSto; + for ( v = 0; v < nIns; v++ ) + pIPerm[v] = v; + pSto = Gia_ManContructTree( pTruths, nIns, nOuts, nWords ); + nNodesBeg = Gia_ManTreeCountNodes(pSto); + //Gia_ManDumpMuxes( pSto, "from_tt1.aig", pIPerm ); + Gia_ManTreeFree( pSto ); + if ( fRandom ) + for ( v = 0; v < nIns; v++ ) + { + //int o, vRand = rand() % nIns; + int o, vRand = Gia_ManRandom(0) % nIns; + for ( o = 0; o < nOuts; o++ ) + Abc_TtSwapVars( pTruths + o*nWords, nIns, v, vRand ); + ABC_SWAP( int, pIPerm[vRand], pIPerm[v] ); + } + for ( r = 0; r < 10*nIns; r++ ) + { + nNodesPrev = nNodesMin; + if ( fVeryVerbose ) + printf( "\nRound %d:\n", r ); + Pos = Gia_ManFindBestPosition( pTruths, nIns, nOuts, nWords, pStore, r&1, &nNodesMin, fVeryVerbose ); + Abc_TtCopy( pTruths, pStore+Pos*nOuts*nWords, nOuts*nWords, 0 ); + pTried[nIns-1]++; + for ( v = nIns-2; v >= Pos; v-- ) + { + ABC_SWAP( int, pTried[v+1], pTried[v] ); + ABC_SWAP( int, pIPerm[v+1], pIPerm[v] ); + } + if ( fVeryVerbose ) + Gia_ManPermStats( nIns, pIPerm, pTried ); + nNoChange = nNodesPrev == nNodesMin ? nNoChange + 1 : 0; + if ( nNoChange == 4 ) + break; + } + pSto = Gia_ManContructTree( pTruths, nIns, nOuts, nWords ); + nNodesEnd = Gia_ManTreeCountNodes(pSto); + //Gia_ManDumpMuxes( pSto, "from_tt2.aig", pIPerm ); + if ( fVerbose ) + printf( "Nodes %5d -> %5d. ", nNodesBeg, nNodesEnd ); + Gia_ManTreeFree( pSto ); + ABC_FREE( pStore ); + if ( pIPermOut ) + memcpy( pIPermOut, pIPerm, sizeof(int)*nIns ); + return nNodesEnd; +} +void Gia_ManPermuteTree( word * pTruths, int nIns, int nOuts, int nWords, int fRandom, int fVerbose ) +{ + abctime clk = Abc_Clock(); + word * pTruthDup = Abc_TtDup( pTruths, nOuts*nWords, 0 ); + int r; + //srand( time(NULL) ); + Gia_ManRandom(1); + for ( r = 0; r < 100; r++ ) + { + Gia_ManPermuteTreeOne( pTruthDup, nIns, nOuts, nWords, fRandom, NULL, 0, fVerbose ); + Abc_TtCopy( pTruthDup, pTruths, nOuts*nWords, 0 ); + } + ABC_FREE( pTruthDup ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +#define TT_UNDEF ABC_CONST(0x1234567887654321) + +static inline word Abc_Tt6Min_rec( word uF, word uR, int nVars, Vec_Wrd_t * vNodes ) +{ + word uF0, uF1, uR0, uR1, uRes0, uRes1, uRes2; int i, Var; + assert( nVars <= 6 ); + assert( (uF & uR) == 0 ); + if ( !uF && !uR ) + return TT_UNDEF; + if ( !uF && !~uR ) + return 0; + if ( !~uF && !uR ) + return ~(word)0; + assert( nVars > 0 ); + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_Tt6HasVar( uF, Var ) || Abc_Tt6HasVar( uR, Var ) ) + break; + assert( Var >= 0 ); + if ( 1 && vNodes ) + Vec_WrdForEachEntry( vNodes, uRes2, i ) + if ( !(uF & ~uRes2) && !(uRes2 & uR) ) + return uRes2; +// else if ( !(uF & uRes2) && !(~uRes2 & uR) ) +// return ~uRes2; + uF0 = Abc_Tt6Cofactor0( uF, Var ); + uF1 = Abc_Tt6Cofactor1( uF, Var ); + uR0 = Abc_Tt6Cofactor0( uR, Var ); + uR1 = Abc_Tt6Cofactor1( uR, Var ); + uRes0 = Abc_Tt6Min_rec( uF0, uR0, Var, vNodes ); + uRes1 = Abc_Tt6Min_rec( uF1, uR1, Var, vNodes ); + if ( uRes0 == TT_UNDEF && uRes1 == TT_UNDEF ) + return TT_UNDEF; + if ( uRes0 == TT_UNDEF ) + return uRes1; + if ( uRes1 == TT_UNDEF ) + return uRes0; + if ( uRes0 == uRes1 ) + return uRes0; +// if ( (uRes0 & ~uRes1) == 0 ) +// printf( "0" ); +// else if ( (~uRes0 & uRes1) == 0 ) +// printf( "1" ); +// else +// printf( "*" ); + uRes2 = (uRes0 & s_Truths6Neg[Var]) | (uRes1 & s_Truths6[Var]); + assert( !(uF & ~uRes2) ); + assert( !(uRes2 & uR) ); + if ( vNodes ) + Vec_WrdPush( vNodes, uRes2 ); + return uRes2; +} +word * Abc_TtMin_rec( word * pF, word * pR, int nVars, Vec_Wrd_t * vMemory, Vec_Wrd_t * vNodes, Vec_Wec_t * vNodes2 ) +{ + int i, Entry, nWords = Abc_TtWordNum(nVars); + word * pRes0, * pRes1, * pRes2 = Vec_WrdFetch( vMemory, nWords ); + if ( nVars <= 6 ) + { + pRes2[0] = Abc_Tt6Min_rec( pF[0], pR[0], nVars, vNodes ); + return pRes2; + } + assert( !Abc_TtIntersect(pF, pR, nWords, 0) ); + if ( Abc_TtIsConst0(pF, nWords) && Abc_TtIsConst0(pR, nWords) ) + return NULL; + if ( Abc_TtIsConst0(pF, nWords) && Abc_TtIsConst1(pR, nWords) ) + { + Abc_TtClear( pRes2, nWords ); + return pRes2; + } + if ( Abc_TtIsConst1(pF, nWords) && Abc_TtIsConst0(pR, nWords) ) + { + Abc_TtFill( pRes2, nWords ); + return pRes2; + } + nWords >>= 1; + if ( !Abc_TtHasVar( pF, nVars, nVars-1 ) && !Abc_TtHasVar( pR, nVars, nVars-1 ) ) + { + pRes0 = Abc_TtMin_rec( pF, pR, nVars-1, vMemory, vNodes, vNodes2 ); + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes0, nWords, 0 ); + return pRes2; + } + if ( 1 && vNodes2 ) + { + Vec_Int_t * vLayer = Vec_WecEntry( vNodes2, nVars ); + Vec_IntForEachEntry( vLayer, Entry, i ) + { + word * pTemp = Vec_WrdEntryP( vMemory, Entry ); + if ( !Abc_TtIntersect(pTemp, pF, 2*nWords, 1) && !Abc_TtIntersect(pTemp, pR, 2*nWords, 0) ) + return pTemp; +/* + if ( !Abc_TtIntersect(pTemp, pF, 2*nWords, 0) && !Abc_TtIntersect(pTemp, pR, 2*nWords, 1) ) + { + Abc_TtCopy( pRes2, pTemp, 2*nWords, 1 ); + return pRes2; + } +*/ + } + } + assert( nVars > 6 ); + pRes0 = Abc_TtMin_rec( pF, pR, nVars-1, vMemory, vNodes, vNodes2 ); + pRes1 = Abc_TtMin_rec( pF + nWords, pR + nWords, nVars-1, vMemory, vNodes, vNodes2 ); + if ( pRes0 == NULL && pRes1 == NULL ) + return NULL; + if ( pRes0 == NULL || pRes1 == NULL || Abc_TtEqual(pRes0, pRes1, nWords) ) + { + Abc_TtCopy( pRes2, pRes0 ? pRes0 : pRes1, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes0 ? pRes0 : pRes1, nWords, 0 ); + return pRes2; + } + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes1, nWords, 0 ); + assert( !Abc_TtIntersect(pRes2, pF, 2*nWords, 1) ); // assert( !(uF & ~uRes2) ); + assert( !Abc_TtIntersect(pRes2, pR, 2*nWords, 0) ); // assert( !(uRes2 & uR) ); + if ( vNodes2 ) + Vec_WecPush( vNodes2, nVars, pRes2 - Vec_WrdArray(vMemory) ); + return pRes2; +} +word * Abc_TtMin( word * pF, word * pR, int nVars, Vec_Wrd_t * vMemory, Vec_Wrd_t * vNodes, Vec_Wec_t * vNodes2 ) +{ + word * pResult; + int i, nWords = Abc_TtWordNum(nVars); + assert( nVars >= 0 && nVars <= 16 ); + for ( i = nVars; i < 6; i++ ) + assert( !Abc_Tt6HasVar(pF[0], i) && !Abc_Tt6HasVar(pR[0], i) ); + Vec_WrdClear( vMemory ); + Vec_WrdGrow( vMemory, 1 << 20 ); + pResult = Abc_TtMin_rec( pF, pR, nVars, vMemory, vNodes, vNodes2 ); + if ( pResult == NULL ) + { + Vec_WrdFill( vMemory, nWords, 0 ); + return Vec_WrdArray( vMemory ); + } + //printf( "Memory %d (Truth table %d)\n", Vec_WrdSize(vMemory), nWords ); + Abc_TtCopy( Vec_WrdArray(vMemory), pResult, nWords, 0 ); + Vec_WrdShrink( vMemory, nWords ); + return Vec_WrdArray(vMemory); +} +word * Abc_TtMinArray( word * p, int nOuts, int nVars, int * pnNodes, int fVerbose ) +{ + int o, i, nWords = Abc_TtWordNum(nVars); + word * pRes, * pResult = ABC_ALLOC( word, nOuts*nWords/2 ); + Vec_Wrd_t * vMemory = Vec_WrdAlloc( 100 ); + Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 ); + Vec_Wec_t * vNodes2 = Vec_WecStart( nVars+1 ); + Vec_WrdGrow( vMemory, 1 << 20 ); + for ( o = 0; o < nOuts/2; o++ ) + { + word * pF = p + (2*o+0)*nWords; + word * pR = p + (2*o+1)*nWords; + for ( i = nVars; i < 6; i++ ) + assert( !Abc_Tt6HasVar(pF[0], i) && !Abc_Tt6HasVar(pR[0], i) ); + pRes = Abc_TtMin_rec( pF, pR, nVars, vMemory, vNodes, vNodes2 ); + if ( pResult == NULL ) + Abc_TtClear( pResult + o*nWords, nWords ); + else + Abc_TtCopy( pResult + o*nWords, pRes, nWords, 0 ); + } + if ( fVerbose ) + printf( "Nodes = %5d. Nodes2 = %5d. Total = %5d. ", + Vec_WrdSize(vNodes), Vec_WecSizeSize(vNodes2), Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2) ); + //printf( "Memory %d (Truth table %d)\n", Vec_WrdSize(vMemory), nWords ); + if ( pnNodes ) + *pnNodes = Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2); + Vec_WrdFree( vMemory ); + Vec_WrdFree( vNodes ); + Vec_WecFree( vNodes2 ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline word Abc_TtSimple6Min_rec( Gia_Man_t * p, word uF, word uC, int nVars, Vec_Wrd_t * vNodes, int * piLit, int * pPerm ) +{ + word uF0, uF1, uC0, uC1, uRes0, uRes1, uRes2; int i, Var, iLit0, iLit1; + word uFC = uF & uC; + word uRC = ~uF & uC; + assert( nVars <= 6 ); + *piLit = 0; + if ( !uFC ) + { + *piLit = 0; + return 0; + } + if ( !uRC ) + { + *piLit = 1; + return ~(word)0; + } + assert( nVars > 0 ); + if ( 1 && vNodes ) + { + int iLit; + Vec_WrdForEachEntryDouble( vNodes, uRes2, iLit, i ) + if ( !((uF ^ uRes2) & uC) ) + { + *piLit = (unsigned)iLit; + return uRes2; + } + else if ( !((uF ^ ~uRes2) & uC) ) + { + *piLit = Abc_LitNot( (unsigned)iLit ); + return ~uRes2; + } + } + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_Tt6HasVar( uF, Var ) ) + break; + else + uC = Abc_Tt6Cofactor0(uC, Var) | Abc_Tt6Cofactor1(uC, Var); + assert( Var >= 0 ); + uF0 = Abc_Tt6Cofactor0( uF, Var ); + uF1 = Abc_Tt6Cofactor1( uF, Var ); + uC0 = Abc_Tt6Cofactor0( uC, Var ); + uC1 = Abc_Tt6Cofactor1( uC, Var ); + uRes0 = Abc_TtSimple6Min_rec( p, uF0, uC0, Var, vNodes, &iLit0, pPerm ); + uRes1 = Abc_TtSimple6Min_rec( p, uF1, uC1, Var, vNodes, &iLit1, pPerm ); + if ( uRes0 == uRes1 ) + { + *piLit = iLit0; + return uRes0; + } + uRes2 = (uRes0 & s_Truths6Neg[Var]) | (uRes1 & s_Truths6[Var]); + Var = pPerm ? pPerm[Var] : Var; + //if ( !(uRes0 & ~uRes1 & uC1) ) + if ( !(uRes0 & ~uRes1) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 0), iLit1), iLit0 ); + //else if ( !(uRes1 & ~uRes0 & uC0) ) + else if ( !(uRes1 & ~uRes0) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 1), iLit0), iLit1 ); + else + *piLit = Gia_ManHashMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 ); + assert( !(uFC & ~uRes2) ); + assert( !(uRes2 & uRC) ); + if ( vNodes ) + Vec_WrdPushTwo( vNodes, uRes2, (word)*piLit ); + return uRes2; +} +word * Abc_TtSimpleMin_rec( Gia_Man_t * p, word * pF, word * pC, int nVars, Vec_Wrd_t * vMemory, Vec_Wrd_t * vNodes, Vec_Wec_t * vNodes2, int * piLit, int * pPerm ) +{ + int i, Entry, Var, iLit0, iLit1, nWords = Abc_TtWordNum(nVars); + word * pRes0, * pRes1, * pRes2 = Vec_WrdFetch( vMemory, nWords ); + *piLit = 0; + if ( nVars <= 6 ) + { + pRes2[0] = Abc_TtSimple6Min_rec( p, pF[0], pC[0], nVars, vNodes, piLit, pPerm ); + return pRes2; + } + if ( !Abc_TtIntersect(pF, pC, nWords, 0) ) + { + *piLit = 0; + Abc_TtClear( pRes2, nWords ); + return pRes2; + } + if ( !Abc_TtIntersect(pF, pC, nWords, 1) ) + { + *piLit = 1; + Abc_TtFill( pRes2, nWords ); + return pRes2; + } + nWords >>= 1; + if ( !Abc_TtHasVar( pF, nVars, nVars-1 ) ) + { + word * pCn = Vec_WrdFetch( vMemory, nWords ); + Abc_TtOr( pCn, pC, pC + nWords, nWords ); + pRes0 = Abc_TtSimpleMin_rec( p, pF, pCn, nVars-1, vMemory, vNodes, vNodes2, piLit, pPerm ); + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes0, nWords, 0 ); + return pRes2; + } + if ( 1 && vNodes2 ) + { + Vec_Int_t * vLayer = Vec_WecEntry( vNodes2, nVars ); int iLit; + Vec_IntForEachEntryDouble( vLayer, Entry, iLit, i ) + { + word * pTemp = Vec_WrdEntryP( vMemory, Entry ); + if ( Abc_TtEqualCare(pTemp, pF, pC, 0, 2*nWords) ) + { + *piLit = iLit; + return pTemp; + } + else if ( Abc_TtEqualCare(pTemp, pF, pC, 1, 2*nWords) ) + { + *piLit = Abc_LitNot(iLit); + Abc_TtCopy( pRes2, pTemp, 2*nWords, 1 ); + return pRes2; + } + } + } + assert( nVars > 6 ); + pRes0 = Abc_TtSimpleMin_rec( p, pF, pC, nVars-1, vMemory, vNodes, vNodes2, &iLit0, pPerm ); + pRes1 = Abc_TtSimpleMin_rec( p, pF + nWords, pC + nWords, nVars-1, vMemory, vNodes, vNodes2, &iLit1, pPerm ); + if ( Abc_TtEqual(pRes0, pRes1, nWords) ) + { + *piLit = iLit0; + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes0, nWords, 0 ); + return pRes2; + } + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes1, nWords, 0 ); + Var = pPerm ? pPerm[nVars-1] : nVars-1; + //if ( !Abc_TtIntersectCare(pRes1, pRes0, pC + nWords, nWords, 1) ) + if ( !Abc_TtIntersect(pRes1, pRes0, nWords, 1) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 0), iLit1), iLit0 ); + //else if ( !Abc_TtIntersectCare(pRes0, pRes1, pC, nWords, 1) ) + else if ( !Abc_TtIntersect(pRes0, pRes1, nWords, 1) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 1), iLit0), iLit1 ); + else + *piLit = Gia_ManHashMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 ); + assert( Abc_TtEqualCare(pRes2, pF, pC, 0, 2*nWords) ); + if ( vNodes2 ) + { + Vec_Int_t * vLayer = Vec_WecEntry( vNodes2, nVars ); + Vec_IntPushTwo( vLayer, pRes2 - Vec_WrdArray(vMemory), *piLit ); + } + return pRes2; +} +Gia_Man_t * Abc_TtSimpleMinArrayNew( word * p, int nVars, int nOuts, int * pnNodes, int fVerbose, int * pIPerm ) +{ + Gia_Man_t * pNew, * pTemp; + int o, i, iLit, nWords = Abc_TtWordNum(nVars); + word * pF = ABC_ALLOC( word, nWords ); + word * pR = ABC_ALLOC( word, nWords ); + Vec_Wrd_t * vMemory = Vec_WrdAlloc( 100 ); + Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 ); + Vec_Wec_t * vNodes2 = Vec_WecStart( nVars+1 ); + Vec_WrdGrow( vMemory, 1 << 20 ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "muxes" ); + for ( i = 0; i < nVars; i++ ) + Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + + for ( o = 0; o < nOuts; o++ ) + { + word * pCare = p + nOuts*nWords; + word * pTruth = p + o*nWords; + for ( i = nVars; i < 6; i++ ) + assert( !Abc_Tt6HasVar(pTruth[0], i) && !Abc_Tt6HasVar(pCare[0], i) ); + Abc_TtSimpleMin_rec( pNew, pTruth, pCare, nVars, vMemory, vNodes, vNodes2, &iLit, pIPerm ); + Gia_ManAppendCo( pNew, iLit ); + } + if ( fVerbose ) + printf( "Nodes = %5d. Nodes2 = %5d. Total = %5d. ", + Vec_WrdSize(vNodes), Vec_WecSizeSize(vNodes2), Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2) ); + //printf( "Memory %d (Truth table %d)\n", Vec_WrdSize(vMemory), nWords ); + if ( pnNodes ) + *pnNodes = Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2); + Vec_WrdFree( vMemory ); + Vec_WrdFree( vNodes ); + Vec_WecFree( vNodes2 ); + ABC_FREE( pF ); + ABC_FREE( pR ); + + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline word Abc_TtGia6Min_rec( Gia_Man_t * p, word uF, word uR, int nVars, Vec_Wrd_t * vNodes, int * piLit, int * pPerm ) +{ + word uF0, uF1, uR0, uR1, uRes0, uRes1, uRes2; int i, Var, iLit0, iLit1; + assert( nVars <= 6 ); + assert( (uF & uR) == 0 ); + *piLit = 0; + if ( !uF && !uR ) + return TT_UNDEF; + if ( !uF && !~uR ) + { + *piLit = 0; + return 0; + } + if ( !~uF && !uR ) + { + *piLit = 1; + return ~(word)0; + } + assert( nVars > 0 ); + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_Tt6HasVar( uF, Var ) || Abc_Tt6HasVar( uR, Var ) ) + break; + assert( Var >= 0 ); + if ( 1 && vNodes ) + { + int iLit; + Vec_WrdForEachEntryDouble( vNodes, uRes2, iLit, i ) + if ( !(uF & ~uRes2) && !(uRes2 & uR) ) + { + *piLit = (unsigned)iLit; + return uRes2; + } + else if ( !(uF & uRes2) && !(~uRes2 & uR) ) + { + *piLit = Abc_LitNot( (unsigned)iLit ); + return ~uRes2; + } + } + uF0 = Abc_Tt6Cofactor0( uF, Var ); + uF1 = Abc_Tt6Cofactor1( uF, Var ); + uR0 = Abc_Tt6Cofactor0( uR, Var ); + uR1 = Abc_Tt6Cofactor1( uR, Var ); + uRes0 = Abc_TtGia6Min_rec( p, uF0, uR0, Var, vNodes, &iLit0, pPerm ); + uRes1 = Abc_TtGia6Min_rec( p, uF1, uR1, Var, vNodes, &iLit1, pPerm ); + if ( uRes0 == TT_UNDEF && uRes1 == TT_UNDEF ) + return TT_UNDEF; + if ( uRes0 == TT_UNDEF ) + { + *piLit = iLit1; + return uRes1; + } + if ( uRes1 == TT_UNDEF || uRes0 == uRes1 ) + { + *piLit = iLit0; + return uRes0; + } +// if ( (uRes0 & ~uRes1) == 0 ) +// printf( "0" ); +// else if ( (~uRes0 & uRes1) == 0 ) +// printf( "1" ); +// else +// printf( "*" ); + uRes2 = (uRes0 & s_Truths6Neg[Var]) | (uRes1 & s_Truths6[Var]); + Var = pPerm ? pPerm[Var] : Var; + if ( !(uRes0 & ~uRes1) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 0), iLit1), iLit0 ); + else if ( !(uRes1 & ~uRes0) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 1), iLit0), iLit1 ); + else + *piLit = Gia_ManHashMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 ); + assert( !(uF & ~uRes2) ); + assert( !(uRes2 & uR) ); + if ( vNodes ) + Vec_WrdPushTwo( vNodes, uRes2, (word)*piLit ); + return uRes2; +} +word * Abc_TtGiaMin_rec( Gia_Man_t * p, word * pF, word * pR, int nVars, Vec_Wrd_t * vMemory, Vec_Wrd_t * vNodes, Vec_Wec_t * vNodes2, int * piLit, int * pPerm ) +{ + int i, Entry, Var, iLit0, iLit1, nWords = Abc_TtWordNum(nVars); + word * pRes0, * pRes1, * pRes2 = Vec_WrdFetch( vMemory, nWords ); + *piLit = 0; + if ( nVars <= 6 ) + { + pRes2[0] = Abc_TtGia6Min_rec( p, pF[0], pR[0], nVars, vNodes, piLit, pPerm ); + return pRes2; + } + assert( !Abc_TtIntersect(pF, pR, nWords, 0) ); + if ( Abc_TtIsConst0(pF, nWords) && Abc_TtIsConst0(pR, nWords) ) + return NULL; + if ( Abc_TtIsConst0(pF, nWords) && Abc_TtIsConst1(pR, nWords) ) + { + *piLit = 0; + Abc_TtClear( pRes2, nWords ); + return pRes2; + } + if ( Abc_TtIsConst1(pF, nWords) && Abc_TtIsConst0(pR, nWords) ) + { + *piLit = 1; + Abc_TtFill( pRes2, nWords ); + return pRes2; + } + nWords >>= 1; + if ( !Abc_TtHasVar( pF, nVars, nVars-1 ) && !Abc_TtHasVar( pR, nVars, nVars-1 ) ) + { + pRes0 = Abc_TtGiaMin_rec( p, pF, pR, nVars-1, vMemory, vNodes, vNodes2, piLit, pPerm ); + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes0, nWords, 0 ); + return pRes2; + } + if ( 1 && vNodes2 ) + { + Vec_Int_t * vLayer = Vec_WecEntry( vNodes2, nVars ); int iLit; + Vec_IntForEachEntryDouble( vLayer, Entry, iLit, i ) + { + word * pTemp = Vec_WrdEntryP( vMemory, Entry ); + if ( !Abc_TtIntersect(pTemp, pF, 2*nWords, 1) && !Abc_TtIntersect(pTemp, pR, 2*nWords, 0) ) + { + *piLit = iLit; + return pTemp; + } + else if ( !Abc_TtIntersect(pTemp, pF, 2*nWords, 0) && !Abc_TtIntersect(pTemp, pR, 2*nWords, 1) ) + { + *piLit = Abc_LitNot(iLit); + Abc_TtCopy( pRes2, pTemp, 2*nWords, 1 ); + return pRes2; + } + } +/* + if ( nVars > 7 ) + { + vLayer = Vec_WecEntry( vNodes2, nVars-1 ); + Vec_IntForEachEntryDouble( vLayer, Entry, iLit, i ) + { + word * pTemp = Vec_WrdEntryP( vMemory, Entry ); + if ( !Abc_TtIntersect(pTemp, pF, 2*nWords, 1) && !Abc_TtIntersect(pTemp, pR, 2*nWords, 0) ) + { + *piLit = iLit; + return pTemp; + } + else if ( !Abc_TtIntersect(pTemp, pF, 2*nWords, 0) && !Abc_TtIntersect(pTemp, pR, 2*nWords, 1) ) + { + *piLit = Abc_LitNot(iLit); + Abc_TtCopy( pRes2, pTemp, 2*nWords, 1 ); + return pRes2; + } + } + } +*/ + } + assert( nVars > 6 ); + pRes0 = Abc_TtGiaMin_rec( p, pF, pR, nVars-1, vMemory, vNodes, vNodes2, &iLit0, pPerm ); + pRes1 = Abc_TtGiaMin_rec( p, pF + nWords, pR + nWords, nVars-1, vMemory, vNodes, vNodes2, &iLit1, pPerm ); + if ( pRes0 == NULL && pRes1 == NULL ) + return NULL; + if ( pRes0 == NULL || pRes1 == NULL || Abc_TtEqual(pRes0, pRes1, nWords) ) + { + *piLit = pRes0 ? iLit0 : iLit1; + Abc_TtCopy( pRes2, pRes0 ? pRes0 : pRes1, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes0 ? pRes0 : pRes1, nWords, 0 ); + return pRes2; + } + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes1, nWords, 0 ); + Var = pPerm ? pPerm[nVars-1] : nVars-1; + if ( !Abc_TtIntersect(pRes1, pRes0, nWords, 1) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 0), iLit1), iLit0 ); + else if ( !Abc_TtIntersect(pRes0, pRes1, nWords, 1) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 1), iLit0), iLit1 ); + else + *piLit = Gia_ManHashMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 ); + assert( !Abc_TtIntersect(pRes2, pF, 2*nWords, 1) ); // assert( !(uF & ~uRes2) ); + assert( !Abc_TtIntersect(pRes2, pR, 2*nWords, 0) ); // assert( !(uRes2 & uR) ); + if ( vNodes2 ) + { + Vec_Int_t * vLayer = Vec_WecEntry( vNodes2, nVars ); + Vec_IntPushTwo( vLayer, pRes2 - Vec_WrdArray(vMemory), *piLit ); + } + return pRes2; +} +Gia_Man_t * Abc_TtGiaMinArray( word * p, int nVars, int nOuts, int * pnNodes, int fVerbose, int * pIPerm ) +{ + Gia_Man_t * pNew, * pTemp; + int o, i, iLit, nWords = Abc_TtWordNum(nVars); + word * pRes, * pResult = ABC_ALLOC( word, nOuts*nWords/2 ); + Vec_Wrd_t * vMemory = Vec_WrdAlloc( 100 ); + Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 ); + Vec_Wec_t * vNodes2 = Vec_WecStart( nVars+1 ); + Vec_WrdGrow( vMemory, 1 << 20 ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "muxes" ); + for ( i = 0; i < nVars; i++ ) + Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + + for ( o = 0; o < nOuts/2; o++ ) + { + word * pF = p + (2*o+0)*nWords; + word * pR = p + (2*o+1)*nWords; + for ( i = nVars; i < 6; i++ ) + assert( !Abc_Tt6HasVar(pF[0], i) && !Abc_Tt6HasVar(pR[0], i) ); + pRes = Abc_TtGiaMin_rec( pNew, pF, pR, nVars, vMemory, vNodes, vNodes2, &iLit, pIPerm ); + if ( pResult == NULL ) + { + Abc_TtClear( pResult + o*nWords, nWords ); + Gia_ManAppendCo( pNew, 0 ); + } + else + { + Abc_TtCopy( pResult + o*nWords, pRes, nWords, 0 ); + Gia_ManAppendCo( pNew, iLit ); + } + } + if ( fVerbose ) + printf( "Nodes = %5d. Nodes2 = %5d. Total = %5d. ", + Vec_WrdSize(vNodes), Vec_WecSizeSize(vNodes2), Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2) ); + //printf( "Memory %d (Truth table %d)\n", Vec_WrdSize(vMemory), nWords ); + if ( pnNodes ) + *pnNodes = Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2); + Vec_WrdFree( vMemory ); + Vec_WrdFree( vNodes ); + Vec_WecFree( vNodes2 ); + ABC_FREE( pResult ); + + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +Gia_Man_t * Abc_TtGiaMinArrayNew( word * p, int nVars, int nOuts, int * pnNodes, int fVerbose, int * pIPerm ) +{ + Gia_Man_t * pNew, * pTemp; + int o, i, iLit, nWords = Abc_TtWordNum(nVars); + word * pF = ABC_ALLOC( word, nWords ); + word * pR = ABC_ALLOC( word, nWords ); + Vec_Wrd_t * vMemory = Vec_WrdAlloc( 100 ); + Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 ); + Vec_Wec_t * vNodes2 = Vec_WecStart( nVars+1 ); + Vec_WrdGrow( vMemory, 1 << 20 ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "muxes" ); + for ( i = 0; i < nVars; i++ ) + Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + + for ( o = 0; o < nOuts; o++ ) + { + word * pCare = p + nOuts*nWords; + word * pTruth = p + o*nWords; + Abc_TtAnd( pF, pCare, pTruth, nWords, 0 ); + Abc_TtSharp( pR, pCare, pTruth, nWords ); + for ( i = nVars; i < 6; i++ ) + assert( !Abc_Tt6HasVar(pF[0], i) && !Abc_Tt6HasVar(pR[0], i) ); + Abc_TtGiaMin_rec( pNew, pF, pR, nVars, vMemory, vNodes, vNodes2, &iLit, pIPerm ); + Gia_ManAppendCo( pNew, iLit ); + } + if ( fVerbose ) + printf( "Nodes = %5d. Nodes2 = %5d. Total = %5d. ", + Vec_WrdSize(vNodes), Vec_WecSizeSize(vNodes2), Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2) ); + //printf( "Memory %d (Truth table %d)\n", Vec_WrdSize(vMemory), nWords ); + if ( pnNodes ) + *pnNodes = Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2); + Vec_WrdFree( vMemory ); + Vec_WrdFree( vNodes ); + Vec_WecFree( vNodes2 ); + ABC_FREE( pF ); + ABC_FREE( pR ); + + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManBuildMuxes6_rec( Gia_Man_t * p, word t, int nVars, int * pPerm ) +{ + int iLit0, iLit1, Var; + assert( nVars <= 6 ); + if ( t == 0 ) + return 0; + if ( ~t == 0 ) + return 1; + assert( nVars > 0 ); + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_Tt6HasVar( t, Var ) ) + break; + assert( Var >= 0 ); + iLit0 = Gia_ManBuildMuxes6_rec( p, Abc_Tt6Cofactor0(t, Var), Var, pPerm ); + iLit1 = Gia_ManBuildMuxes6_rec( p, Abc_Tt6Cofactor1(t, Var), Var, pPerm ); + Var = pPerm ? pPerm[Var] : Var; + return Gia_ManAppendMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 ); +} +int Gia_ManBuildMuxes_rec( Gia_Man_t * p, word * pTruth, int nVars, int * pPerm ) +{ + int iLit0, iLit1, Var, nWords = Abc_TtWordNum(nVars); + if ( nVars <= 6 ) + return Gia_ManBuildMuxes6_rec( p, pTruth[0], nVars, pPerm ); + if ( Abc_TtIsConst0(pTruth, nWords) ) + return 0; + if ( Abc_TtIsConst1(pTruth, nWords) ) + return 1; +/* + assert( nVars > 0 ); + if ( !Abc_TtHasVar( pTruth, nVars, nVars-1 ) ) + return Gia_ManBuildMuxes_rec( p, pTruth, nVars-1 ); + assert( nVars > 6 ); + iLit0 = Gia_ManBuildMuxes_rec( p, pTruth, nVars-1 ); + iLit1 = Gia_ManBuildMuxes_rec( p, pTruth+nWords/2, nVars-1 ); +*/ + assert( nVars > 0 ); + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_TtHasVar( pTruth, nVars, Var ) ) + break; + assert( Var >= 0 ); + if ( Var < 6 ) + return Gia_ManBuildMuxes6_rec( p, pTruth[0], Var+1, pPerm ); + iLit0 = Gia_ManBuildMuxes_rec( p, pTruth, Var, pPerm ); + iLit1 = Gia_ManBuildMuxes_rec( p, pTruth+Abc_TtWordNum(Var), Var, pPerm ); + Var = pPerm ? pPerm[Var] : Var; + return Gia_ManAppendMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 ); +} +Gia_Man_t * Gia_ManBuildMuxesTest( word * pTruth, int nIns, int nOuts, int * pPerm ) +{ + Gia_Man_t * pNew, * pTemp; + int i, nWords = Abc_TtWordNum(nIns); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "muxes" ); + for ( i = 0; i < nIns; i++ ) + Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManAppendCo( pNew, Gia_ManBuildMuxes_rec( pNew, pTruth+i*nWords, nIns, pPerm ) ); + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +Gia_Man_t * Gia_ManBuildMuxes( Tree_Sto_t * p, int * pIPerm ) +{ + return Gia_ManBuildMuxesTest( p->pMem, p->nIns, p->nOuts, pIPerm ? pIPerm : p->pIPerm ); +} +void Gia_ManDumpMuxes( Tree_Sto_t * p, char * pFileName, int * pIPerm ) +{ + Gia_Man_t * pNew = Gia_ManBuildMuxes( p, pIPerm ); + Gia_AigerWrite( pNew, pFileName, 0, 0, 0 ); + Gia_ManStop( pNew ); + printf( "Finished dumping tree into AIG file \"%s\".\n", pFileName ); +} +Gia_Man_t * Gia_ManCreateMuxGia( word * pTruths, int nIns, int nOuts, int nWords, int * pIPerm ) +{ + Tree_Sto_t * pSto = Gia_ManContructTree( pTruths, nIns, nOuts, nWords ); + Gia_Man_t * pNew = Gia_ManBuildMuxes( pSto, pIPerm ); + //printf( "Internal nodes = %5d.\n", Gia_ManTreeCountNodes(pSto) ); + Gia_ManTreeFree( pSto ); + return pNew; +} +void Gia_ManDumpMuxGia( word * pTruths, int nIns, int nOuts, int nWords, int * pIPerm, char * pFileName ) +{ + Tree_Sto_t * pSto = Gia_ManContructTree( pTruths, nIns, nOuts, nWords ); + Gia_ManDumpMuxes( pSto, pFileName, pIPerm ); + Gia_ManTreeFree( pSto ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_TryPermOptCare( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Gia_Man_t * pNew; + word * pTruthDup = Abc_TtDup( pTruths, nOuts*nWords, 0 ); + word * pTruthBest = ABC_FALLOC( word, (nOuts+1)*nWords ); + int pIPermBest[TREE_MAX_VARS] = {0}; + int pIPerm[TREE_MAX_VARS] = {0}; + int r, rBest = -1, nNodes = -1, nNodesBest = ABC_INFINITY; + //Gia_ManDumpMuxGia( pTruths, nIns, nOuts, nWords, NULL, "tt_beg.aig" ); + //srand( time(NULL) ); + Gia_ManRandom(1); + for ( r = 0; r < nRounds; r++ ) + { + nNodes = Gia_ManPermuteTreeOne( pTruthDup, nIns, nOuts, nWords, r>0, pIPerm, 0, fVerbose ); + if ( nNodesBest > nNodes ) + { + nNodesBest = nNodes; + memcpy( pIPermBest, pIPerm, sizeof(int)*nIns ); + Abc_TtCopy( pTruthBest, pTruthDup, nOuts*nWords, 0 ); + rBest = r; + } + Abc_TtCopy( pTruthDup, pTruths, nOuts*nWords, 0 ); + if ( fVerbose ) + printf( "\n" ); + } + if ( fVerbose ) + printf( "Best round %3d. Best nodes %5d. ", rBest, nNodesBest ); + ABC_FREE( pTruthDup ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + //pNew = Gia_ManCreateMuxGia( pTruthBest, nIns, nOuts, nWords, pIPermBest ); + pNew = Abc_TtSimpleMinArrayNew( pTruthBest, nIns, nOuts, NULL, 0, pIPermBest ); + //Gia_ManDumpMuxGia( pTruthBest, nIns, nOuts, nWords, pIPermBest, "tt_end.aig" ); + ABC_FREE( pTruthBest ); + return pNew; +} +Gia_Man_t * Gia_TryPermOpt2( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Gia_Man_t * pNew; + word * pRes, * pTruthDup = Abc_TtDup( pTruths, nOuts*nWords, 0 ); + word * pTruthBest = ABC_ALLOC( word, nOuts*nWords/2 ); + int pIPermBest[TREE_MAX_VARS] = {0}; + int pIPerm[TREE_MAX_VARS] = {0}; + int r, rBest = -1, nNodes = -1, nNodesBest = ABC_INFINITY; + assert( nOuts % 2 == 0 ); + // collect onsets + //for ( r = 0; r < nOuts/2; r++ ) + // Abc_TtCopy( pTruthBest+r*nWords, pTruths+2*r*nWords, nWords, 0 ); + //Gia_ManDumpMuxGia( pTruthBest, nIns, nOuts/2, nWords, NULL, "tt_beg.aig" ); + //srand( time(NULL) ); + Gia_ManRandom(1); + for ( r = 0; r < nRounds; r++ ) + { + int nNodesAll = Gia_ManPermuteTreeOne( pTruthDup, nIns, nOuts, nWords, r>0, pIPerm, 0, fVerbose ); + pRes = Abc_TtMinArray( pTruthDup, nOuts, nIns, &nNodes, fVerbose ); + if ( nNodesBest > nNodes ) + { + nNodesBest = nNodes; + memcpy( pIPermBest, pIPerm, sizeof(int)*nIns ); + Abc_TtCopy( pTruthBest, pRes, nOuts*nWords/2, 0 ); + rBest = r; + } + ABC_FREE( pRes ); + Abc_TtCopy( pTruthDup, pTruths, nOuts*nWords, 0 ); + if ( fVerbose ) + printf( "\n" ); + nNodesAll = 0; + } + if ( fVerbose ) + printf( "Best round %3d. Best nodes %5d. ", rBest, nNodesBest ); + ABC_FREE( pTruthDup ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + pNew = Gia_ManCreateMuxGia( pTruthBest, nIns, nOuts/2, nWords, pIPermBest ); + //Gia_ManDumpMuxGia( pTruthBest, nIns, nOuts/2, nWords, pIPermBest, "tt_end.aig" ); + ABC_FREE( pTruthBest ); + return pNew; +} +Gia_Man_t * Gia_TryPermOpt( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Gia_Man_t * pBest = NULL; + word * pTruthDup = Abc_TtDup( pTruths, nOuts*nWords, 0 ); + int pIPermBest[TREE_MAX_VARS] = {0}; + int pIPerm[TREE_MAX_VARS] = {0}; + int r, rBest = -1, nNodes2 = -1, nNodesBest = ABC_INFINITY; + assert( nOuts % 2 == 0 ); + //srand( time(NULL) ); + Gia_ManRandom(1); + for ( r = 0; r < nRounds; r++ ) + { + int nNodesAll = Gia_ManPermuteTreeOne( pTruthDup, nIns, nOuts, nWords, r>0, pIPerm, 0, fVerbose ); + Gia_Man_t * pTemp = Abc_TtGiaMinArray( pTruthDup, nIns, nOuts, NULL, 0, pIPerm ); + nNodes2 = Gia_ManAndNum(pTemp); + if ( nNodesBest > nNodes2 ) + { + nNodesBest = nNodes2; + memcpy( pIPermBest, pIPerm, sizeof(int)*nIns ); + rBest = r; + + Gia_ManStopP( &pBest ); + pBest = pTemp; + pTemp = NULL; + } + Gia_ManStopP( &pTemp ); + Abc_TtCopy( pTruthDup, pTruths, nOuts*nWords, 0 ); + if ( fVerbose ) + printf( "Permuted = %5d. AIG = %5d.\n", nNodesAll, nNodes2 ); + nNodesAll = 0; + } + if ( fVerbose ) + printf( "Best round %3d. Best nodes %5d. ", rBest, nNodesBest ); + ABC_FREE( pTruthDup ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return pBest; +} +Gia_Man_t * Gia_TryPermOptNew( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Gia_Man_t * pTemp, * pBest = NULL; + word * pTruthDup = Abc_TtDup( pTruths, (nOuts+1)*nWords, 0 ); + int pIPermBest[TREE_MAX_VARS] = {0}; + int pIPerm[TREE_MAX_VARS] = {0}; + int r, rBest = -1, nNodes2 = -1, nNodesBest = ABC_INFINITY; + //srand( time(NULL) ); + Gia_ManRandom(1); + for ( r = 0; r < nRounds; r++ ) + { + int nNodesAll = Gia_ManPermuteTreeOne( pTruthDup, nIns, nOuts, nWords, r>0, pIPerm, 0, fVerbose ); + Abc_TtPermute( pTruthDup + nOuts*nWords, pIPerm, nIns ); + //pTemp = Abc_TtGiaMinArrayNew( pTruthDup, nIns, nOuts, NULL, 0, pIPerm ); + pTemp = Abc_TtSimpleMinArrayNew( pTruthDup, nIns, nOuts, NULL, 0, pIPerm ); + nNodes2 = Gia_ManAndNum(pTemp); + if ( nNodesBest > nNodes2 ) + { + nNodesBest = nNodes2; + memcpy( pIPermBest, pIPerm, sizeof(int)*nIns ); + rBest = r; + + Gia_ManStopP( &pBest ); + pBest = pTemp; + pTemp = NULL; + } + Gia_ManStopP( &pTemp ); +/* + for ( i = 0; i <= nOuts; i++ ) + { + Abc_TtUnpermute( pTruthDup + i*nWords, pIPerm, nIns ); + if ( !Abc_TtEqual(pTruthDup + i*nWords, pTruths + i*nWords, nWords) ) + printf( "Verification failed for output %d (out of %d).\n", i, nOuts ); + } +*/ + Abc_TtCopy( pTruthDup, pTruths, (nOuts+1)*nWords, 0 ); + if ( fVerbose ) + printf( "Permuted = %5d. AIG = %5d.\n", nNodesAll, nNodes2 ); + nNodesAll = 0; + } + if ( fVerbose ) + printf( "Best round %3d. Best nodes %5d. ", rBest, nNodesBest ); + ABC_FREE( pTruthDup ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return pBest; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_Tt6MinTest3( Gia_Man_t * p ) +{ + word f = ABC_CONST(0x513B00000819050F); + //word r = ABC_CONST(0xA000571507200000); + word r = ~f; + Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 ); + word Res = Abc_Tt6Min_rec( f, r, 6, vNodes ); + printf( "Nodes = %d.\n", Vec_WrdSize(vNodes) ); + if ( Res == f ) + printf( "Verification successful.\n" ); + else + printf( "Verification FAILED.\n" ); + Vec_WrdFree( vNodes ); +} +void Abc_Tt6MinTest2( Gia_Man_t * p ) +{ + int fVerbose = 0; + int i, nWords = Abc_TtWordNum(Gia_ManCiNum(p)); + word * pTruth = ABC_ALLOC( word, 3*nWords ); + word * pRes = NULL, * pTruths[3] = { pTruth, pTruth+nWords, pTruth+2*nWords }; + + Vec_Int_t * vSupp = Vec_IntAlloc( 100 ); + Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 ); + Vec_Wec_t * vNodes2 = Vec_WecAlloc( 100 ); + Vec_Wrd_t * vMemory = Vec_WrdAlloc( 0 ); + + Gia_Obj_t * pObj; + Gia_ManForEachCi( p, pObj, i ) + Vec_IntPush( vSupp, Gia_ObjId(p, pObj) ); + + Gia_ObjComputeTruthTableStart( p, Gia_ManCiNum(p) ); + assert( Gia_ManCoNum(p) == 3 ); + Gia_ManForEachCo( p, pObj, i ) + { + word * pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ObjFanin0(pObj), vSupp ); + Abc_TtCopy( pTruths[i], pTruth, nWords, Gia_ObjFaninC0(pObj) ); + } + Gia_ObjComputeTruthTableStop( p ); + + + //Abc_TtSharp( pTruths[0], pTruths[0], pTruths[1], nWords ); + Abc_TtReverseVars( pTruths[0], Gia_ManCiNum(p) ); + Abc_TtCopy( pTruths[1], pTruths[0], nWords, 1 ); + + pRes = Abc_TtMin( pTruths[0], pTruths[1], Gia_ManCiNum(p), vMemory, vNodes, vNodes2 ); + printf( "Nodes = %d.\n", Vec_WrdSize(vNodes) ); + printf( "Nodes2 = %d.\n", Vec_WecSizeSize(vNodes2) ); + if ( Abc_TtEqual(pRes, pTruths[0], nWords) ) + printf( "Verification successful.\n" ); + else + printf( "Verification FAILED.\n" ); + + //printf( "Printing the tree:\n" ); +// Gia_ManPermuteTree( pTruths[0], Gia_ManCiNum(p), 1, nWords, fVerbose ); + Gia_ManPermuteTree( pTruth, Gia_ManCiNum(p), 3, nWords, 0, fVerbose ); + + +/* + Abc_TtReverseVars( pTruths[0], Gia_ManCiNum(p) ); + Abc_TtReverseVars( pTruths[1], Gia_ManCiNum(p) ); + Abc_TtReverseVars( pTruths[2], Gia_ManCiNum(p) ); + printf( "Printing the tree:\n" ); + Gia_ManContructTree( pTruth, Gia_ManCiNum(p), 3, nWords ); +*/ + +/* + pNew = Gia_ManBuildMuxesTest( pTruth, Gia_ManCiNum(p), Gia_ManCoNum(p), NULL ); + Gia_AigerWrite( pNew, "from_tt.aig", 0, 0, 0 ); + printf( "Dumping file \"%s\".\n", "from_tt.aig" ); + Gia_ManStop( pNew ); +*/ + + Vec_WrdFree( vMemory ); + Vec_WrdFree( vNodes ); + Vec_WecFree( vNodes2 ); + Vec_IntFree( vSupp ); + ABC_FREE( pTruth ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/gia/giaMini.c b/src/aig/gia/giaMini.c index ce42f73c..6cc528f2 100644 --- a/src/aig/gia/giaMini.c +++ b/src/aig/gia/giaMini.c @@ -32,6 +32,8 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -57,7 +59,7 @@ int Gia_ObjFromMiniFanin1Copy( Gia_Man_t * pGia, Vec_Int_t * vCopies, Mini_Aig_t int Lit = Mini_AigNodeFanin1( p, Id ); return Abc_LitNotCond( Vec_IntEntry(vCopies, Abc_Lit2Var(Lit)), Abc_LitIsCompl(Lit) ); } -Gia_Man_t * Gia_ManFromMiniAig( Mini_Aig_t * p, Vec_Int_t ** pvCopies ) +Gia_Man_t * Gia_ManFromMiniAig( Mini_Aig_t * p, Vec_Int_t ** pvCopies, int fGiaSimple ) { Gia_Man_t * pGia, * pTemp; Vec_Int_t * vCopies; @@ -71,7 +73,10 @@ Gia_Man_t * Gia_ManFromMiniAig( Mini_Aig_t * p, Vec_Int_t ** pvCopies ) vCopies = Vec_IntAlloc( nNodes ); Vec_IntPush( vCopies, 0 ); // iterate through the objects - Gia_ManHashAlloc( pGia ); + if ( fGiaSimple ) + pGia->fGiaSimple = fGiaSimple; + else + Gia_ManHashAlloc( pGia ); for ( i = 1; i < nNodes; i++ ) { if ( Mini_AigNodeIsPi( p, i ) ) @@ -83,17 +88,19 @@ Gia_Man_t * Gia_ManFromMiniAig( Mini_Aig_t * p, Vec_Int_t ** pvCopies ) else assert( 0 ); Vec_IntPush( vCopies, iGiaLit ); } - Gia_ManHashStop( pGia ); assert( Vec_IntSize(vCopies) == nNodes ); if ( pvCopies ) *pvCopies = vCopies; else Vec_IntFree( vCopies ); Gia_ManSetRegNum( pGia, Mini_AigRegNum(p) ); - pGia = Gia_ManCleanup( pTemp = pGia ); - if ( pvCopies ) - Gia_ManDupRemapLiterals( *pvCopies, pTemp ); - Gia_ManStop( pTemp ); + if ( !fGiaSimple ) + { + pGia = Gia_ManCleanup( pTemp = pGia ); + if ( pvCopies ) + Gia_ManDupRemapLiterals( *pvCopies, pTemp ); + Gia_ManStop( pTemp ); + } return pGia; } @@ -148,7 +155,7 @@ void Abc_FrameGiaInputMiniAig( Abc_Frame_t * pAbc, void * p ) printf( "ABC framework is not initialized by calling Abc_Start()\n" ); Gia_ManStopP( &pAbc->pGiaMiniAig ); Vec_IntFreeP( &pAbc->vCopyMiniAig ); - pGia = Gia_ManFromMiniAig( (Mini_Aig_t *)p, &pAbc->vCopyMiniAig ); + pGia = Gia_ManFromMiniAig( (Mini_Aig_t *)p, &pAbc->vCopyMiniAig, 0 ); Abc_FrameUpdateGia( pAbc, pGia ); pAbc->pGiaMiniAig = Gia_ManDup( pGia ); // Gia_ManDelete( pGia ); @@ -175,10 +182,10 @@ void * Abc_FrameGiaOutputMiniAig( Abc_Frame_t * pAbc ) SeeAlso [] ***********************************************************************/ -Gia_Man_t * Gia_ManReadMiniAig( char * pFileName ) +Gia_Man_t * Gia_ManReadMiniAig( char * pFileName, int fGiaSimple ) { Mini_Aig_t * p = Mini_AigLoad( pFileName ); - Gia_Man_t * pGia = Gia_ManFromMiniAig( p, NULL ); + Gia_Man_t * pGia = Gia_ManFromMiniAig( p, NULL, fGiaSimple ); ABC_FREE( pGia->pName ); pGia->pName = Extra_FileNameGeneric( pFileName ); Mini_AigStop( p ); @@ -260,6 +267,65 @@ Gia_Man_t * Gia_ManFromMiniLut( Mini_Lut_t * p, Vec_Int_t ** pvCopies ) return pGia; } + +/**Function************************************************************* + + Synopsis [Converts MiniLUT into GIA.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFromMiniLut2( Mini_Lut_t * p, Vec_Int_t ** pvCopies ) +{ + Gia_Man_t * pGia; + Vec_Int_t * vCopies; + Vec_Int_t * vCover = Vec_IntAlloc( 1000 ); + Vec_Int_t * vLits = Vec_IntAlloc( 100 ); + int i, k, Fan, iGiaLit, nNodes; + // get the number of nodes + nNodes = Mini_LutNodeNum(p); + // create ABC network + pGia = Gia_ManStart( 3 * nNodes ); + pGia->pName = Abc_UtilStrsav( "MiniLut" ); + // create mapping from MiniLUT objects into ABC objects + vCopies = Vec_IntAlloc( nNodes ); + Vec_IntPush( vCopies, 0 ); + Vec_IntPush( vCopies, 1 ); + // iterate through the objects + pGia->fGiaSimple = 1; + for ( i = 2; i < nNodes; i++ ) + { + if ( Mini_LutNodeIsPi( p, i ) ) + iGiaLit = Gia_ManAppendCi(pGia); + else if ( Mini_LutNodeIsPo( p, i ) ) + iGiaLit = Gia_ManAppendCo(pGia, Vec_IntEntry(vCopies, Mini_LutNodeFanin(p, i, 0))); + else if ( Mini_LutNodeIsNode( p, i ) ) + { + unsigned * puTruth = Mini_LutNodeTruth( p, i ); + Vec_IntClear( vLits ); + Mini_LutForEachFanin( p, i, Fan, k ) + Vec_IntPush( vLits, Vec_IntEntry(vCopies, Fan) ); + iGiaLit = Kit_TruthToGia( pGia, puTruth, Vec_IntSize(vLits), vCover, vLits, 0 ); + } + else assert( 0 ); + Vec_IntPush( vCopies, iGiaLit ); + } + Vec_IntFree( vCover ); + Vec_IntFree( vLits ); + assert( Vec_IntSize(vCopies) == nNodes ); + if ( pvCopies ) + *pvCopies = vCopies; + else + Vec_IntFree( vCopies ); + Gia_ManSetRegNum( pGia, Mini_LutRegNum(p) ); + return pGia; +} + + /**Function************************************************************* Synopsis [Marks LUTs that should be complemented.] @@ -412,6 +478,15 @@ void Abc_FrameGiaInputMiniLut( Abc_Frame_t * pAbc, void * p ) Abc_FrameUpdateGia( pAbc, pGia ); // Gia_ManDelete( pGia ); } +void Abc_FrameGiaInputMiniLut2( Abc_Frame_t * pAbc, void * p ) +{ + if ( pAbc == NULL ) + printf( "ABC framework is not initialized by calling Abc_Start()\n" ); + Vec_IntFreeP( &pAbc->vCopyMiniLut ); + Gia_ManStopP( &pAbc->pGiaMiniLut ); + pAbc->pGiaMiniLut = Gia_ManFromMiniLut2( (Mini_Lut_t *)p, &pAbc->vCopyMiniLut ); +// Abc_FrameUpdateGia( pAbc, pGia ); +} void * Abc_FrameGiaOutputMiniLut( Abc_Frame_t * pAbc ) { Mini_Lut_t * pRes = NULL; @@ -589,6 +664,39 @@ int * Abc_FrameReadMiniLutNameMapping( Abc_Frame_t * pAbc ) Gia_ManStop( pGia ); return pRes; } +int * Abc_FrameReadMiniLutSwitching( Abc_Frame_t * pAbc ) +{ + Vec_Int_t * vSwitching; + int i, iObj, * pRes = NULL; + if ( pAbc->pGiaMiniLut == NULL ) + { + printf( "GIA derived from MiniLut is not available.\n" ); + return NULL; + } + vSwitching = Gia_ManComputeSwitchProbs( pAbc->pGiaMiniLut, 48, 16, 0 ); + pRes = ABC_CALLOC( int, Vec_IntSize(pAbc->vCopyMiniLut) ); + Vec_IntForEachEntry( pAbc->vCopyMiniLut, iObj, i ) + if ( iObj >= 0 ) + pRes[i] = (int)(10000*Vec_FltEntry( (Vec_Flt_t *)vSwitching, Abc_Lit2Var(iObj) )); + Vec_IntFree( vSwitching ); + return pRes; +} +int * Abc_FrameReadMiniLutSwitchingPo( Abc_Frame_t * pAbc ) +{ + Vec_Int_t * vSwitching; + int i, iObj, * pRes = NULL; + if ( pAbc->pGiaMiniAig == NULL ) + { + printf( "GIA derived from MiniAIG is not available.\n" ); + return NULL; + } + vSwitching = Gia_ManComputeSwitchProbs( pAbc->pGiaMiniAig, 48, 16, 0 ); + pRes = ABC_CALLOC( int, Gia_ManCoNum(pAbc->pGiaMiniAig) ); + Gia_ManForEachCoDriverId( pAbc->pGiaMiniAig, iObj, i ) + pRes[i] = (int)(10000*Vec_FltEntry( (Vec_Flt_t *)vSwitching, iObj )); + Vec_IntFree( vSwitching ); + return pRes; +} /**Function************************************************************* @@ -797,6 +905,274 @@ void Gia_MiniAigVerify( Abc_Frame_t * pAbc, char * pFileName ) Mini_AigStop( p ); } +/**Function************************************************************* + + Synopsis [Collects supergate for the outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_MiniAigSuperGates_rec( Mini_Aig_t * p, int iObj, Vec_Int_t * vRes, Vec_Int_t * vMap ) +{ + int iFan0, iFan1; + if ( Mini_AigNodeIsPi(p, iObj) ) + { + assert( Vec_IntEntry(vMap, iObj) >= 0 ); + Vec_IntPush( vRes, Vec_IntEntry(vMap, iObj) ); + return; + } + iFan0 = Mini_AigNodeFanin0( p, iObj ); + iFan1 = Mini_AigNodeFanin1( p, iObj ); + assert( !Abc_LitIsCompl(iFan0) ); + assert( !Abc_LitIsCompl(iFan1) ); + Gia_MiniAigSuperGates_rec( p, Abc_Lit2Var(iFan0), vRes, vMap ); + Gia_MiniAigSuperGates_rec( p, Abc_Lit2Var(iFan1), vRes, vMap ); +} +Vec_Wec_t * Gia_MiniAigSuperGates( Mini_Aig_t * p ) +{ + Vec_Wec_t * vRes = Vec_WecStart( Mini_AigPoNum(p) ); + Vec_Int_t * vMap = Vec_IntStartFull( Mini_AigNodeNum(p) ); + int i, Index = 0; + Mini_AigForEachPi( p, i ) + Vec_IntWriteEntry( vMap, i, Index++ ); + assert( Index == Mini_AigPiNum(p) ); + Index = 0; + Mini_AigForEachPo( p, i ) + { + int iFan0 = Mini_AigNodeFanin0( p, i ); + assert( !Abc_LitIsCompl(iFan0) ); + Gia_MiniAigSuperGates_rec( p, Abc_Lit2Var(iFan0), Vec_WecEntry(vRes, Index++), vMap ); + } + assert( Index == Mini_AigPoNum(p) ); + Vec_IntFree( vMap ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [Transform.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_MiniAigSuperPrintDouble( Vec_Int_t * p, int nPis ) +{ + int i, Entry; + printf( "\n" ); + Vec_IntForEachEntry( p, Entry, i ) + printf( "%d(%d) ", Entry%nPis, Entry/nPis ); + printf( " Total = %d\n", Vec_IntSize(p) ); +} +int Gia_MiniAigSuperMerge( Vec_Int_t * p, int nPis ) +{ + int i, k = 0, This, Prev = -1, fChange = 0; + Vec_IntForEachEntry( p, This, i ) + { + if ( Prev == This ) + { + Vec_IntWriteEntry( p, k++, (This/nPis+1)*nPis + This%nPis ); + Prev = -1; + fChange = 1; + } + else + { + if ( Prev != -1 ) + Vec_IntWriteEntry( p, k++, Prev ); + Prev = This; + } + } + if ( Prev != -1 ) + Vec_IntWriteEntry( p, k++, Prev ); + Vec_IntShrink( p, k ); + return fChange; +} +int Gia_MiniAigSuperPreprocess( Mini_Aig_t * p, Vec_Wec_t * vSuper, int nPis, int fVerbose ) +{ + Vec_Int_t * vRes; + int i, nIters, Multi = 1; + Vec_WecForEachLevel( vSuper, vRes, i ) + { + Vec_IntSort( vRes, 0 ); + if ( fVerbose ) + printf( "\nOutput %d\n", i ); + if ( fVerbose ) + Gia_MiniAigSuperPrintDouble( vRes, nPis ); + for ( nIters = 1; Gia_MiniAigSuperMerge(vRes, nPis); nIters++ ) + { + if ( fVerbose ) + Gia_MiniAigSuperPrintDouble( vRes, nPis ); + } + Multi = Abc_MaxInt( Multi, nIters ); + } + if ( fVerbose ) + printf( "Multi = %d.\n", Multi ); + return Multi; +} + +/**Function************************************************************* + + Synopsis [Derive AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_MiniAigSuperDeriveGia( Vec_Wec_t * p, int nPis, int Multi ) +{ + Gia_Man_t * pNew; + Vec_Int_t * vTemp, * vLits = Vec_IntAlloc( 100 ); + Vec_Int_t * vDrivers = Vec_IntAlloc(100); + int i, k, iObj, iLit, nInputs = nPis*Multi; + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "tree" ); + for ( i = 0; i < nInputs; i++ ) + Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + Vec_WecForEachLevel( p, vTemp, i ) + { + Vec_IntClear( vLits ); + Vec_IntForEachEntry( vTemp, iObj, k ) + { + assert( iObj < nInputs ); + Vec_IntPush( vLits, 2+2*((iObj%nPis)*Multi+iObj/nPis) ); + } + Vec_IntPush( vDrivers, Gia_ManHashAndMulti2(pNew, vLits) ); + } + Gia_ManHashStop( pNew ); + Vec_IntFree( vLits ); + Vec_IntForEachEntry( vDrivers, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + Vec_IntFree( vDrivers ); + return pNew; +} +Gia_Man_t * Gia_MiniAigSuperDerive( char * pFileName, int fVerbose ) +{ + Mini_Aig_t * p = Mini_AigLoad( pFileName ); + Vec_Wec_t * vSuper = Gia_MiniAigSuperGates( p ); + int Multi = Gia_MiniAigSuperPreprocess( p, vSuper, Mini_AigPiNum(p), fVerbose ); + Gia_Man_t * pNew = Gia_MiniAigSuperDeriveGia( vSuper, Mini_AigPiNum(p), Multi ); + Vec_WecFree( vSuper ); + Mini_AigStop( p ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Process file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_MiniAigProcessFile() +{ + Vec_Int_t * vTriples = Vec_IntAlloc( 100 ); + char * pFileName = "test.txt"; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + printf( "Cannot open the file.\n" ); + else + { + int nLines = 0, nLinesAll = 0; + char * pToken; + char Buffer[1000]; + while ( fgets( Buffer, 1000, pFile ) != NULL ) + { + nLinesAll++; + if ( Buffer[0] != '#' ) + continue; + //printf( "%s", Buffer ); + nLines++; + pToken = strtok( Buffer+3, " \r\n\r+=" ); + while ( pToken ) + { + Vec_IntPush( vTriples, atoi(pToken) ); + pToken = strtok( NULL, " \r\n\r+=" ); + } + } + fclose( pFile ); + printf( "Collected %d (out of %d) lines.\n", nLines, nLinesAll ); + printf( "Entries = %d\n", Vec_IntSize(vTriples) ); + } + return vTriples; +} +void Gia_MiniAigGenerate_rec( Mini_Aig_t * p, Vec_Int_t * vTriples, int iObj, Vec_Int_t * vDefs, Vec_Int_t * vMap ) +{ + int Index, Entry0, Entry1, Entry2, Value; + if ( Vec_IntEntry(vMap, iObj) >= 0 ) + return; + Index = Vec_IntEntry( vDefs, iObj ); + Entry0 = Vec_IntEntry( vTriples, 3*Index+0 ); + Entry1 = Vec_IntEntry( vTriples, 3*Index+1 ); + Entry2 = Vec_IntEntry( vTriples, 3*Index+2 ); + Gia_MiniAigGenerate_rec( p, vTriples, Entry1, vDefs, vMap ); + Gia_MiniAigGenerate_rec( p, vTriples, Entry2, vDefs, vMap ); + assert( Vec_IntEntry(vMap, Entry1) >= 0 ); + assert( Vec_IntEntry(vMap, Entry2) >= 0 ); + Value = Mini_AigAnd( p, Vec_IntEntry(vMap, Entry1), Vec_IntEntry(vMap, Entry2) ); + Vec_IntWriteEntry( vMap, Entry0, Value ); +} +void Gia_MiniAigGenerateFromFile() +{ + Mini_Aig_t * p = Mini_AigStart(); + Vec_Int_t * vTriples = Gia_MiniAigProcessFile(); + Vec_Int_t * vDefs = Vec_IntStartFull( Vec_IntSize(vTriples) ); + Vec_Int_t * vMap = Vec_IntStartFull( Vec_IntSize(vTriples) ); + Vec_Int_t * vMapIn = Vec_IntStart( Vec_IntSize(vTriples) ); + Vec_Int_t * vMapOut = Vec_IntStart( Vec_IntSize(vTriples) ); + Vec_Int_t * vPis = Vec_IntAlloc( 100 ); + Vec_Int_t * vPos = Vec_IntAlloc( 100 ); + int i, ObjOut, ObjIn; + assert( Vec_IntSize(vTriples) % 3 == 0 ); + for ( i = 0; i < Vec_IntSize(vTriples)/3; i++ ) + { + int Entry0 = Vec_IntEntry(vTriples, 3*i+0); + int Entry1 = Vec_IntEntry(vTriples, 3*i+1); + int Entry2 = Vec_IntEntry(vTriples, 3*i+2); + Vec_IntWriteEntry( vDefs, Entry0, i ); + Vec_IntAddToEntry( vMapOut, Entry0, 1 ); + Vec_IntAddToEntry( vMapIn, Entry1, 1 ); + Vec_IntAddToEntry( vMapIn, Entry2, 1 ); + } + Vec_IntForEachEntryTwo( vMapOut, vMapIn, ObjOut, ObjIn, i ) + if ( !ObjOut && ObjIn ) + Vec_IntPush( vPis, i ); + else if ( ObjOut && !ObjIn ) + Vec_IntPush( vPos, i ); + Vec_IntForEachEntry( vPis, ObjIn, i ) + Vec_IntWriteEntry( vMap, ObjIn, Mini_AigCreatePi(p) ); + Vec_IntForEachEntry( vPos, ObjOut, i ) + Gia_MiniAigGenerate_rec( p, vTriples, ObjOut, vDefs, vMap ); + Vec_IntForEachEntry( vPos, ObjOut, i ) + { + assert( Vec_IntEntry(vMap, ObjOut) >= 0 ); + Mini_AigCreatePo( p, Vec_IntEntry(vMap, ObjOut) ); + } + Vec_IntFree( vTriples ); + Vec_IntFree( vDefs ); + Vec_IntFree( vMap ); + Vec_IntFree( vMapIn ); + Vec_IntFree( vMapOut ); + Vec_IntFree( vPis ); + Vec_IntFree( vPos ); + Mini_AigDump( p, "test.miniaig" ); + Mini_AigStop( p ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaPat2.c b/src/aig/gia/giaPat2.c new file mode 100644 index 00000000..f14ce34a --- /dev/null +++ b/src/aig/gia/giaPat2.c @@ -0,0 +1,1329 @@ +/**CFile**************************************************************** + + FileName [giaPat2.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Pattern generation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaPat2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/vec/vecHsh.h" +#include "sat/cnf/cnf.h" +#include "sat/bsat/satStore.h" +#include "misc/util/utilTruth.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Min_Man_t_ Min_Man_t; +struct Min_Man_t_ +{ + int nCis; + int nCos; + int FirstAndLit; + int FirstCoLit; + Vec_Int_t vFans; + Vec_Str_t vValsN; + Vec_Str_t vValsL; + Vec_Int_t vVis; + Vec_Int_t vPat; +}; + +static inline int Min_ManCiNum( Min_Man_t * p ) { return p->nCis; } +static inline int Min_ManCoNum( Min_Man_t * p ) { return p->nCos; } +static inline int Min_ManObjNum( Min_Man_t * p ) { return Vec_IntSize(&p->vFans) >> 1; } +static inline int Min_ManAndNum( Min_Man_t * p ) { return Min_ManObjNum(p) - p->nCis - p->nCos - 1; } + +static inline int Min_ManCi( Min_Man_t * p, int i ) { return 1 + i; } +static inline int Min_ManCo( Min_Man_t * p, int i ) { return Min_ManObjNum(p) - Min_ManCoNum(p) + i; } + +static inline int Min_ObjIsCi( Min_Man_t * p, int i ) { return i > 0 && i <= Min_ManCiNum(p); } +static inline int Min_ObjIsNode( Min_Man_t * p, int i ) { return i > Min_ManCiNum(p) && i < Min_ManObjNum(p) - Min_ManCoNum(p); } +static inline int Min_ObjIsAnd( Min_Man_t * p, int i ) { return Min_ObjIsNode(p, i) && Vec_IntEntry(&p->vFans, 2*i) < Vec_IntEntry(&p->vFans, 2*i+1); } +static inline int Min_ObjIsXor( Min_Man_t * p, int i ) { return Min_ObjIsNode(p, i) && Vec_IntEntry(&p->vFans, 2*i) > Vec_IntEntry(&p->vFans, 2*i+1); } +static inline int Min_ObjIsBuf( Min_Man_t * p, int i ) { return Min_ObjIsNode(p, i) && Vec_IntEntry(&p->vFans, 2*i) ==Vec_IntEntry(&p->vFans, 2*i+1); } +static inline int Min_ObjIsCo( Min_Man_t * p, int i ) { return i >= Min_ManObjNum(p) - Min_ManCoNum(p) && i < Min_ManObjNum(p); } + +static inline int Min_ObjLit( Min_Man_t * p, int i, int n ) { return Vec_IntEntry(&p->vFans, i + i + n); } +static inline int Min_ObjLit0( Min_Man_t * p, int i ) { return Vec_IntEntry(&p->vFans, i + i + 0); } +static inline int Min_ObjLit1( Min_Man_t * p, int i ) { return Vec_IntEntry(&p->vFans, i + i + 1); } +static inline int Min_ObjCioId( Min_Man_t * p, int i ) { assert( i && !Min_ObjIsNode(p, i) ); return Min_ObjLit1(p, i); } + +static inline int Min_ObjFan0( Min_Man_t * p, int i ) { return Abc_Lit2Var( Min_ObjLit0(p, i) ); } +static inline int Min_ObjFan1( Min_Man_t * p, int i ) { return Abc_Lit2Var( Min_ObjLit1(p, i) ); } + +static inline int Min_ObjFanC0( Min_Man_t * p, int i ) { return Abc_LitIsCompl( Min_ObjLit0(p, i) ); } +static inline int Min_ObjFanC1( Min_Man_t * p, int i ) { return Abc_LitIsCompl( Min_ObjLit1(p, i) ); } + +static inline char Min_ObjValN( Min_Man_t * p, int i ) { return Vec_StrEntry(&p->vValsN, i); } +static inline void Min_ObjSetValN( Min_Man_t * p, int i, char v ){ Vec_StrWriteEntry(&p->vValsN, i, v); } + +static inline char Min_LitValL( Min_Man_t * p, int i ) { return Vec_StrEntry(&p->vValsL, i); } +static inline void Min_LitSetValL( Min_Man_t * p, int i, char v ){ assert(v==0 || v==1); Vec_StrWriteEntry(&p->vValsL, i, v); Vec_StrWriteEntry(&p->vValsL, i^1, (char)!v); Vec_IntPush(&p->vVis, Abc_Lit2Var(i)); } +static inline void Min_ObjCleanValL( Min_Man_t * p, int i ) { ((short *)Vec_StrArray(&p->vValsL))[i] = 0x0202; } +static inline void Min_ObjMarkValL( Min_Man_t * p, int i ) { ((short *)Vec_StrArray(&p->vValsL))[i] |= 0x0404; } +static inline void Min_ObjMark2ValL( Min_Man_t * p, int i ) { ((short *)Vec_StrArray(&p->vValsL))[i] |= 0x0808; } +static inline void Min_ObjUnmark2ValL( Min_Man_t * p, int i ) { ((short *)Vec_StrArray(&p->vValsL))[i] &= 0xF7F7; } + +static inline int Min_LitIsCi( Min_Man_t * p, int v ) { return v > 1 && v < p->FirstAndLit; } +static inline int Min_LitIsNode( Min_Man_t * p, int v ) { return v >= p->FirstAndLit && v < p->FirstCoLit; } +static inline int Min_LitIsCo( Min_Man_t * p, int v ) { return v >= p->FirstCoLit; } + +static inline int Min_LitIsAnd( int v, int v0, int v1 ) { return Abc_LitIsCompl(v) ^ (v0 < v1); } +static inline int Min_LitIsXor( int v, int v0, int v1 ) { return Abc_LitIsCompl(v) ^ (v0 > v1); } +static inline int Min_LitIsBuf( int v, int v0, int v1 ) { return v0 == v1; } + +static inline int Min_LitFan( Min_Man_t * p, int v ) { return Vec_IntEntry(&p->vFans, v); } +static inline int Min_LitFanC( Min_Man_t * p, int v ) { return Abc_LitIsCompl( Min_LitFan(p, v) ); } + +static inline void Min_ManStartValsN( Min_Man_t * p ) { Vec_StrGrow(&p->vValsN, Vec_IntCap(&p->vFans)/2); Vec_StrFill(&p->vValsN, Min_ManObjNum(p), 2); } +static inline void Min_ManStartValsL( Min_Man_t * p ) { Vec_StrGrow(&p->vValsL, Vec_IntCap(&p->vFans)); Vec_StrFill(&p->vValsL, Vec_IntSize(&p->vFans), 2); } +static inline int Min_ManCheckCleanValsL( Min_Man_t * p ) { int i; char c; Vec_StrForEachEntry( &p->vValsL, c, i ) if ( c != 2 ) return 0; return 1; } +static inline void Min_ManCleanVisitedValL( Min_Man_t * p ) { int i, iObj; Vec_IntForEachEntry(&p->vVis, iObj, i) Min_ObjCleanValL(p, iObj); Vec_IntClear(&p->vVis); } + + +#define Min_ManForEachObj( p, i ) \ + for ( i = 0; i < Min_ManObjNum(p); i++ ) +#define Min_ManForEachCi( p, i ) \ + for ( i = 1; i <= Min_ManCiNum(p); i++ ) +#define Min_ManForEachCo( p, i ) \ + for ( i = Min_ManObjNum(p) - Min_ManCoNum(p); i < Min_ManObjNum(p); i++ ) +#define Min_ManForEachAnd( p, i ) \ + for ( i = 1 + Min_ManCiNum(p); i < Min_ManObjNum(p) - Min_ManCoNum(p); i++ ) + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Min_Man_t * Min_ManStart( int nObjMax ) +{ + Min_Man_t * p = ABC_CALLOC( Min_Man_t, 1 ); + Vec_IntGrow( &p->vFans, nObjMax ); + Vec_IntPushTwo( &p->vFans, -1, -1 ); + return p; +} +static inline void Min_ManStop( Min_Man_t * p ) +{ + Vec_IntErase( &p->vFans ); + Vec_StrErase( &p->vValsN ); + Vec_StrErase( &p->vValsL ); + Vec_IntErase( &p->vVis ); + Vec_IntErase( &p->vPat ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Min_ManAppendObj( Min_Man_t * p, int iLit0, int iLit1 ) +{ + int iLit = Vec_IntSize(&p->vFans); + Vec_IntPushTwo( &p->vFans, iLit0, iLit1 ); + return iLit; +} +static inline int Min_ManAppendCi( Min_Man_t * p ) +{ + p->nCis++; + p->FirstAndLit = Vec_IntSize(&p->vFans) + 2; + return Min_ManAppendObj( p, 0, p->nCis-1 ); +} +static inline int Min_ManAppendCo( Min_Man_t * p, int iLit0 ) +{ + p->nCos++; + if ( p->FirstCoLit == 0 ) + p->FirstCoLit = Vec_IntSize(&p->vFans); + return Min_ManAppendObj( p, iLit0, p->nCos-1 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Min_ManFromGia_rec( Min_Man_t * pNew, Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Min_ManFromGia_rec( pNew, p, Gia_ObjFaninId0(pObj, iObj) ); + Min_ManFromGia_rec( pNew, p, Gia_ObjFaninId1(pObj, iObj) ); + pObj->Value = Min_ManAppendObj( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Min_Man_t * Min_ManFromGia( Gia_Man_t * p, Vec_Int_t * vOuts ) +{ + Gia_Obj_t * pObj; int i; + Min_Man_t * pNew = Min_ManStart( Gia_ManObjNum(p) ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Min_ManAppendCi( pNew ); + if ( vOuts == NULL ) + { + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Min_ManAppendObj( pNew, Gia_ObjFaninLit0(pObj, i), Gia_ObjFaninLit1(pObj, i) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Min_ManAppendCo( pNew, Gia_ObjFaninLit0p(p, pObj) ); + } + else + { + Gia_ManForEachCoVec( vOuts, p, pObj, i ) + Min_ManFromGia_rec( pNew, p, Gia_ObjFaninId0p(p, pObj) ); + Gia_ManForEachCoVec( vOuts, p, pObj, i ) + Min_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + return pNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline char Min_XsimNot( char Val ) +{ + if ( Val < 2 ) + return Val ^ 1; + return 2; +} +static inline char Min_XsimXor( char Val0, char Val1 ) +{ + if ( Val0 < 2 && Val1 < 2 ) + return Val0 ^ Val1; + return 2; +} +static inline char Min_XsimAnd( char Val0, char Val1 ) +{ + if ( Val0 == 0 || Val1 == 0 ) + return 0; + if ( Val0 == 1 && Val1 == 1 ) + return 1; + return 2; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char Min_LitVerify_rec( Min_Man_t * p, int iLit ) +{ + char Val = Min_LitValL(p, iLit); + if ( Val == 2 && Min_LitIsNode(p, iLit) ) // unassigned + { + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitVerify_rec( p, iLit0 ); + char Val1 = Min_LitVerify_rec( p, iLit1 ); + assert( Val0 < 3 && Val1 < 3 ); + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + else + Vec_IntPush( &p->vVis, Abc_Lit2Var(iLit) ); + Min_ObjMark2ValL( p, Abc_Lit2Var(iLit) ); + } + return Val&3; +} +char Min_LitVerify( Min_Man_t * p, int iLit, Vec_Int_t * vLits ) +{ + int i, Entry; char Res; + if ( iLit < 2 ) return 1; + assert( !Min_LitIsCo(p, iLit) ); + //assert( Min_ManCheckCleanValsL(p) ); + assert( Vec_IntSize(&p->vVis) == 0 ); + Vec_IntForEachEntry( vLits, Entry, i ) + Min_LitSetValL( p, Entry, 1 ); // ms notation + Res = Min_LitVerify_rec( p, iLit ); + Min_ManCleanVisitedValL( p ); + return Res; +} + +void Min_LitMinimize( Min_Man_t * p, int iLit, Vec_Int_t * vLits ) +{ + int i, iObj, iTemp; char Res; + Vec_IntClear( &p->vPat ); + if ( iLit < 2 ) return; + assert( !Min_LitIsCo(p, iLit) ); + //assert( Min_ManCheckCleanValsL(p) ); + assert( Vec_IntSize(&p->vVis) == 0 ); + Vec_IntForEachEntry( vLits, iTemp, i ) + Min_LitSetValL( p, iTemp, 1 ); // ms notation + Res = Min_LitVerify_rec( p, iLit ); + assert( Res == 1 ); + Min_ObjMarkValL( p, Abc_Lit2Var(iLit) ); + Vec_IntForEachEntryReverse( &p->vVis, iObj, i ) + { + int iLit = Abc_Var2Lit( iObj, 0 ); + int Value = 7 & Min_LitValL(p, iLit); + if ( Value >= 4 ) + { + if ( Min_LitIsCi(p, iLit) ) + Vec_IntPush( &p->vPat, Abc_LitNotCond(iLit, !(Value&1)) ); + else + { + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL( p, iLit0 ); + char Val1 = Min_LitValL( p, iLit1 ); + if ( Value&1 ) // value == 1 + { + assert( (Val0&1) && (Val1&1) ); + Min_ObjMarkValL( p, Abc_Lit2Var(iLit0) ); + Min_ObjMarkValL( p, Abc_Lit2Var(iLit1) ); + } + else // value == 0 + { + int Zero0 = !(Val0&3); + int Zero1 = !(Val1&3); + assert( Zero0 || Zero1 ); + if ( Zero0 && !Zero1 ) + Min_ObjMarkValL( p, Abc_Lit2Var(iLit0) ); + else if ( !Zero0 && Zero1 ) + Min_ObjMarkValL( p, Abc_Lit2Var(iLit1) ); + else if ( Val0 == 4 && Val1 != 4 ) + Min_ObjMarkValL( p, Abc_Lit2Var(iLit0) ); + else if ( Val1 == 4 && Val1 != 4 ) + Min_ObjMarkValL( p, Abc_Lit2Var(iLit1) ); + else if ( Abc_Random(0) & 1 ) + Min_ObjMarkValL( p, Abc_Lit2Var(iLit0) ); + else + Min_ObjMarkValL( p, Abc_Lit2Var(iLit1) ); + } + } + } + Min_ObjCleanValL( p, Abc_Lit2Var(iLit) ); + } + Vec_IntClear( &p->vVis ); + //Min_ManCleanVisitedValL( p ); + //assert( Min_LitVerify(p, iLit, &p->vPat) == 1 ); + assert( Vec_IntSize(&p->vPat) <= Vec_IntSize(vLits) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline char Min_LitIsImplied1( Min_Man_t * p, int iLit ) +{ + char Val = 2; + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + assert( Min_LitIsNode(p, iLit) ); // internal node + assert( Min_LitValL(p, iLit) == 2 ); // unassigned + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + return Val; +} +static inline char Min_LitIsImplied2( Min_Man_t * p, int iLit ) +{ + char Val = 2; + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + assert( Min_LitIsNode(p, iLit) ); // internal node + assert( Min_LitValL(p, iLit) == 2 ); // unassigned + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) + Val0 = Min_LitIsImplied1(p, iLit0); + if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) + Val1 = Min_LitIsImplied1(p, iLit1); + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + return Val; +} +static inline char Min_LitIsImplied3( Min_Man_t * p, int iLit ) +{ + char Val = 2; + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + assert( Min_LitIsNode(p, iLit) ); // internal node + assert( Min_LitValL(p, iLit) == 2 ); // unassigned + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) + Val0 = Min_LitIsImplied2(p, iLit0); + if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) + Val1 = Min_LitIsImplied2(p, iLit1); + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + return Val; +} +static inline char Min_LitIsImplied4( Min_Man_t * p, int iLit ) +{ + char Val = 2; + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + assert( Min_LitIsNode(p, iLit) ); // internal node + assert( Min_LitValL(p, iLit) == 2 ); // unassigned + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) + Val0 = Min_LitIsImplied3(p, iLit0); + if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) + Val1 = Min_LitIsImplied3(p, iLit1); + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + return Val; +} +static inline char Min_LitIsImplied5( Min_Man_t * p, int iLit ) +{ + char Val = 2; + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + assert( Min_LitIsNode(p, iLit) ); // internal node + assert( Min_LitValL(p, iLit) == 2 ); // unassigned + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) + Val0 = Min_LitIsImplied4(p, iLit0); + if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) + Val1 = Min_LitIsImplied4(p, iLit1); + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + return Val; +} + +// this recursive procedure is about 10% slower +char Min_LitIsImplied_rec( Min_Man_t * p, int iLit, int Depth ) +{ + char Val = 2; + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + assert( Depth > 0 ); + assert( Min_LitIsNode(p, iLit) ); // internal node + assert( Min_LitValL(p, iLit) == 2 ); // unassigned + if ( Depth > 1 && Val0 == 2 && Min_LitIsNode(p, iLit0) ) + { + Val0 = Min_LitIsImplied_rec(p, iLit0, Depth-1); + Val1 = Min_LitValL(p, iLit1); + } + if ( Depth > 1 && Val1 == 2 && Min_LitIsNode(p, iLit1) ) + { + Val1 = Min_LitIsImplied_rec(p, iLit1, Depth-1); + Val0 = Min_LitValL(p, iLit0); + } + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + return Val; +} +int Min_LitJustify_rec( Min_Man_t * p, int iLit ) +{ + int Res = 1, LitValue = !Abc_LitIsCompl(iLit); + int Val = (int)Min_LitValL(p, iLit); + if ( Val < 2 ) // assigned + return Val == LitValue; + // unassigned + if ( Min_LitIsCi(p, iLit) ) + Vec_IntPush( &p->vPat, iLit ); // ms notation + else + { + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + { + if ( Val0 < 2 && Val1 < 2 ) + Res = LitValue == (Val0 ^ Val1); + else if ( Val0 < 2 ) + Res = Min_LitJustify_rec(p, iLit1^Val0^!LitValue); + else if ( Val1 < 2 ) + Res = Min_LitJustify_rec(p, iLit0^Val1^!LitValue); + else if ( Abc_Random(0) & 1 ) + Res = Min_LitJustify_rec(p, iLit0) && Min_LitJustify_rec(p, iLit1^ LitValue); + else + Res = Min_LitJustify_rec(p, iLit0^1) && Min_LitJustify_rec(p, iLit1^!LitValue); + assert( !Res || LitValue == Min_XsimXor(Min_LitValL(p, iLit0), Min_LitValL(p, iLit1)) ); + } + else if ( LitValue ) // value 1 + { + if ( Val0 == 0 || Val1 == 0 ) + Res = 0; + else if ( Val0 == 1 && Val1 == 1 ) + Res = 1; + else if ( Val0 == 1 ) + Res = Min_LitJustify_rec(p, iLit1); + else if ( Val1 == 1 ) + Res = Min_LitJustify_rec(p, iLit0); + else + Res = Min_LitJustify_rec(p, iLit0) && Min_LitJustify_rec(p, iLit1); + assert( !Res || 1 == Min_XsimAnd(Min_LitValL(p, iLit0), Min_LitValL(p, iLit1)) ); + } + else // value 0 + { +/* + int Depth = 3; + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) + { + Val0 = Min_LitIsImplied_rec(p, iLit0, Depth); + Val1 = Min_LitValL(p, iLit1); + } + if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) + { + Val1 = Min_LitIsImplied_rec(p, iLit1, Depth); + Val0 = Min_LitValL(p, iLit0); + } +*/ + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) + { + Val0 = Min_LitIsImplied3(p, iLit0); + Val1 = Min_LitValL(p, iLit1); + } + if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) + { + Val1 = Min_LitIsImplied3(p, iLit1); + Val0 = Min_LitValL(p, iLit0); + } + if ( Val0 == 0 || Val1 == 0 ) + Res = 1; + else if ( Val0 == 1 && Val1 == 1 ) + Res = 0; + else if ( Val0 == 1 ) + Res = Min_LitJustify_rec(p, iLit1^1); + else if ( Val1 == 1 ) + Res = Min_LitJustify_rec(p, iLit0^1); + else if ( Abc_Random(0) & 1 ) + //else if ( (p->Random >> (iLit & 0x1F)) & 1 ) + Res = Min_LitJustify_rec(p, iLit0^1); + else + Res = Min_LitJustify_rec(p, iLit1^1); + //Val0 = Min_LitValL(p, iLit0); + //Val1 = Min_LitValL(p, iLit1); + assert( !Res || 0 == Min_XsimAnd(Min_LitValL(p, iLit0), Min_LitValL(p, iLit1)) ); + } + } + if ( Res ) + Min_LitSetValL( p, iLit, 1 ); + return Res; +} +int Min_LitJustify( Min_Man_t * p, int iLit ) +{ + int Res, fCheck = 0; + Vec_IntClear( &p->vPat ); + if ( iLit < 2 ) return 1; + assert( !Min_LitIsCo(p, iLit) ); + //assert( Min_ManCheckCleanValsL(p) ); + assert( Vec_IntSize(&p->vVis) == 0 ); + //p->Random = Abc_Random(0); + Res = Min_LitJustify_rec( p, iLit ); + Min_ManCleanVisitedValL( p ); + if ( Res ) + { + if ( fCheck && Min_LitVerify(p, iLit, &p->vPat) != 1 ) + printf( "Verification FAILED for literal %d.\n", iLit ); + //else + // printf( "Verification succeeded for literal %d.\n", iLit ); + } + //else + // printf( "Could not justify literal %d.\n", iLit ); + return Res; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Min_TargGenerateCexes( Min_Man_t * p, Vec_Int_t * vCoErrs, int nCexes, int nCexesStop, int * pnComputed, int fVerbose ) +{ + abctime clk = Abc_Clock(); + int t, iObj, Count = 0, CountPos = 0, CountPosSat = 0, nRuns[2] = {0}, nCountCexes[2] = {0}; + Vec_Int_t * vPats = Vec_IntAlloc( 1000 ); + Vec_Int_t * vPatBest = Vec_IntAlloc( Min_ManCiNum(p) ); + Hsh_VecMan_t * pHash = Hsh_VecManStart( 10000 ); + Min_ManForEachCo( p, iObj ) if ( Min_ObjLit0(p, iObj) > 1 ) + { + int nCexesGenSim0 = 0; + int nCexesGenSim = 0; + int nCexesGenSat = 0; + if ( vCoErrs && Vec_IntEntry(vCoErrs, Min_ObjCioId(p, iObj)) >= nCexesStop ) + continue; + //printf( "%d ", i ); + for ( t = 0; t < nCexes; t++ ) + { + nRuns[0]++; + if ( Min_LitJustify( p, Min_ObjLit0(p, iObj) ) ) + { + int Before, After; + assert( Vec_IntSize(&p->vPat) > 0 ); + //printf( "%d ", Vec_IntSize(vPat) ); + Vec_IntClear( vPatBest ); + if ( 1 ) // no minimization + Vec_IntAppend( vPatBest, &p->vPat ); + else + { +/* + for ( k = 0; k < 10; k++ ) + { + Vec_IntClear( vPat2 ); + Gia_ManIncrementTravId( p ); + Cexes_MinimizePattern_rec( p, Gia_ObjFanin0(pObj), !Gia_ObjFaninC0(pObj), vPat2 ); + assert( Vec_IntSize(vPat2) <= Vec_IntSize(vPat) ); + if ( Vec_IntSize(vPatBest) == 0 || Vec_IntSize(vPatBest) > Vec_IntSize(vPat2) ) + { + Vec_IntClear( vPatBest ); + Vec_IntAppend( vPatBest, vPat2 ); + } + //printf( "%d ", Vec_IntSize(vPat2) ); + } +*/ + } + + //Gia_CexVerify( p, Gia_ObjFaninId0p(p, pObj), !Gia_ObjFaninC0(pObj), vPatBest ); + //printf( "\n" ); + Before = Hsh_VecSize( pHash ); + Vec_IntSort( vPatBest, 0 ); + Hsh_VecManAdd( pHash, vPatBest ); + After = Hsh_VecSize( pHash ); + if ( Before != After ) + { + Vec_IntPush( vPats, Min_ObjCioId(p, iObj) ); + Vec_IntPush( vPats, Vec_IntSize(vPatBest) ); + Vec_IntAppend( vPats, vPatBest ); + nCexesGenSim++; + } + nCexesGenSim0++; + if ( nCexesGenSim0 > nCexesGenSim*10 ) + { + printf( "**** Skipping output %d (out of %d)\n", Min_ObjCioId(p, iObj), Min_ManCoNum(p) ); + break; + } + } + if ( nCexesGenSim == nCexesStop ) + break; + } + //printf( "(%d %d) ", nCexesGenSim0, nCexesGenSim ); + //printf( "%d ", t/nCexesGenSim ); + + //printf( "The number of CEXes = %d\n", nCexesGen ); + //if ( fVerbose ) + // printf( "%d ", nCexesGen ); + nCountCexes[0] += nCexesGenSim; + nCountCexes[1] += nCexesGenSat; + Count += nCexesGenSim + nCexesGenSat; + CountPos++; + + if ( nCexesGenSim0 == 0 && t == nCexes ) + printf( "#### Output %d (out of %d)\n", Min_ObjCioId(p, iObj), Min_ManCoNum(p) ); + } + //printf( "\n" ); + if ( fVerbose ) + printf( "\n" ); + if ( fVerbose ) + printf( "Got %d unique CEXes using %d sim (%d) and %d SAT (%d) runs (ave size %.1f). PO = %d ErrPO = %d SatPO = %d ", + Count, nRuns[0], nCountCexes[0], nRuns[1], nCountCexes[1], + 1.0*Vec_IntSize(vPats)/Abc_MaxInt(1, Count)-2, Min_ManCoNum(p), CountPos, CountPosSat ); + if ( fVerbose ) + Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); + Hsh_VecManStop( pHash ); + Vec_IntFree( vPatBest ); + *pnComputed = Count; + return vPats; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Min_ManTest3( Gia_Man_t * p, Vec_Int_t * vCoErrs ) +{ + int fXor = 0; + int nComputed; + Vec_Int_t * vPats; + Gia_Man_t * pXor = fXor ? Gia_ManDupMuxes(p, 1) : NULL; + Min_Man_t * pNew = Min_ManFromGia( fXor ? pXor : p, NULL ); + Gia_ManStopP( &pXor ); + Min_ManStartValsL( pNew ); + //Vec_IntFill( vCoErrs, Vec_IntSize(vCoErrs), 0 ); + //vPats = Min_TargGenerateCexes( pNew, vCoErrs, 10000, 10, &nComputed, 1 ); + vPats = Min_TargGenerateCexes( pNew, vCoErrs, 10000, 10, &nComputed, 1 ); + Vec_IntFree( vPats ); + Min_ManStop( pNew ); +} +void Min_ManTest4( Gia_Man_t * p ) +{ + Vec_Int_t * vCoErrs = Vec_IntStartNatural( Gia_ManCoNum(p) ); + Min_ManTest3(p, vCoErrs); + Vec_IntFree( vCoErrs ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupCones2CollectPis_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vMap ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjUpdateTravIdCurrentId(p, iObj) ) + return; + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ManDupCones2CollectPis_rec( p, Gia_ObjFaninId0(pObj, iObj), vMap ); + Gia_ManDupCones2CollectPis_rec( p, Gia_ObjFaninId1(pObj, iObj), vMap ); + } + else if ( Gia_ObjIsCi(pObj) ) + Vec_IntPush( vMap, iObj ); + else assert( 0 ); +} +void Gia_ManDupCones2_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsCi(pObj) || Gia_ObjUpdateTravIdCurrent(p, pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDupCones2_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManDupCones2_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManDupCones2( Gia_Man_t * p, int * pOuts, int nOuts, Vec_Int_t * vMap ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; int i; + Vec_IntClear( vMap ); + Gia_ManIncrementTravId( p ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManDupCones2CollectPis_rec( p, Gia_ManCoDriverId(p, pOuts[i]), vMap ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObjVec( vMap, p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManIncrementTravId( p ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManDupCones2_rec( pNew, p, Gia_ObjFanin0(Gia_ManCo(p, pOuts[i])) ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManCo(p, pOuts[i])) ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Min_ManRemoveItem( Vec_Wec_t * vCexes, int iItem, int iFirst, int iLimit ) +{ + Vec_Int_t * vLevel, * vLevel0 = Vec_WecEntry(vCexes, iItem); int i; + assert( iFirst <= iItem && iItem < iLimit ); + Vec_WecForEachLevelReverseStartStop( vCexes, vLevel, i, iLimit, iFirst ) + if ( Vec_IntSize(vLevel) > 0 ) + break; + assert( iFirst <= i && iItem <= i ); + Vec_IntClear( vLevel0 ); + if ( iItem < i ) + ABC_SWAP( Vec_Int_t, *vLevel0, *vLevel ); + return -1; +} +int Min_ManAccumulate( Vec_Wec_t * vCexes, int iFirst, int iLimit, Vec_Int_t * vCex ) +{ + Vec_Int_t * vLevel; int i, nCommon, nDiff = 0; + Vec_WecForEachLevelStartStop( vCexes, vLevel, i, iFirst, iLimit ) + { + if ( Vec_IntSize(vLevel) == 0 ) + { + Vec_IntAppend(vLevel, vCex); + return nDiff+1; + } + nCommon = Vec_IntTwoCountCommon( vLevel, vCex ); + if ( nCommon == Vec_IntSize(vLevel) ) // ignore vCex + return nDiff; + if ( nCommon == Vec_IntSize(vCex) ) // remove vLevel + nDiff += Min_ManRemoveItem( vCexes, i, iFirst, iLimit ); + } + assert( 0 ); + return ABC_INFINITY; +} +int Min_ManCountSize( Vec_Wec_t * vCexes, int iFirst, int iLimit ) +{ + Vec_Int_t * vLevel; int i, nTotal = 0; + Vec_WecForEachLevelStartStop( vCexes, vLevel, i, iFirst, iLimit ) + nTotal += Vec_IntSize(vLevel) > 0; + return nTotal; +} +Vec_Wec_t * Min_ManComputeCexes( Gia_Man_t * p, Vec_Int_t * vOuts0, int nMaxTries, int nMinCexes, Vec_Int_t * vStats[3], int fUseSim, int fUseSat, int fVerbose ) +{ + Vec_Int_t * vOuts = vOuts0 ? vOuts0 : Vec_IntStartNatural( Gia_ManCoNum(p) ); + Min_Man_t * pNew = Min_ManFromGia( p, vOuts ); + Vec_Wec_t * vCexes = Vec_WecStart( Vec_IntSize(vOuts) * nMinCexes ); + Vec_Int_t * vPatBest = Vec_IntAlloc( 100 ); + Vec_Int_t * vLits = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj; int i, iObj, nOuts = 0, nSimOuts = 0, nSatOuts = 0; + vStats[0] = Vec_IntAlloc( Vec_IntSize(vOuts) ); // total calls + vStats[1] = Vec_IntAlloc( Vec_IntSize(vOuts) ); // successful calls + SAT runs + vStats[2] = Vec_IntAlloc( Vec_IntSize(vOuts) ); // results + Min_ManStartValsL( pNew ); + Min_ManForEachCo( pNew, iObj ) + { + int nAllCalls = 0; + int nGoodCalls = 0; + int nCurrCexes = 0; + if ( fUseSim && Min_ObjLit0(pNew, iObj) >= 2 ) + { + while ( nAllCalls++ < nMaxTries ) + { + if ( Min_LitJustify( pNew, Min_ObjLit0(pNew, iObj) ) ) + { + Vec_IntClearAppend( vLits, &pNew->vPat ); + Vec_IntClearAppend( vPatBest, &pNew->vPat ); + if ( 1 ) // minimization + { + //printf( "%d -> ", Vec_IntSize(vPatBest) ); + for ( i = 0; i < 20; i++ ) + { + Min_LitMinimize( pNew, Min_ObjLit0(pNew, iObj), vLits ); + if ( Vec_IntSize(vPatBest) > Vec_IntSize(&pNew->vPat) ) + Vec_IntClearAppend( vPatBest, &pNew->vPat ); + } + //printf( "%d ", Vec_IntSize(vPatBest) ); + } + assert( Vec_IntSize(vPatBest) > 0 ); + Vec_IntSort( vPatBest, 0 ); + nCurrCexes += Min_ManAccumulate( vCexes, nOuts*nMinCexes, (nOuts+1)*nMinCexes, vPatBest ); + nGoodCalls++; + } + if ( nCurrCexes == nMinCexes || nGoodCalls > 10*nCurrCexes ) + break; + } + nSimOuts++; + } + assert( nCurrCexes <= nMinCexes ); + assert( nCurrCexes == Min_ManCountSize(vCexes, nOuts*nMinCexes, (nOuts+1)*nMinCexes) ); + Vec_IntPush( vStats[0], nAllCalls ); + Vec_IntPush( vStats[1], nGoodCalls ); + Vec_IntPush( vStats[2], nCurrCexes ); + nOuts++; + } + assert( Vec_IntSize(vOuts) == nOuts ); + assert( Vec_IntSize(vOuts) == Vec_IntSize(vStats[0]) ); + assert( Vec_IntSize(vOuts) == Vec_IntSize(vStats[1]) ); + assert( Vec_IntSize(vOuts) == Vec_IntSize(vStats[2]) ); + + if ( fUseSat ) + Gia_ManForEachCoVec( vOuts, p, pObj, i ) + { + if ( Vec_IntEntry(vStats[2], i) >= nMinCexes || Vec_IntEntry(vStats[1], i) > 10*Vec_IntEntry(vStats[2], i) ) + continue; + { + int iObj = Min_ManCo(pNew, i); + int Index = Gia_ObjCioId(pObj); + Vec_Int_t * vMap = Vec_IntAlloc( 100 ); + Gia_Man_t * pCon = Gia_ManDupCones2( p, &Index, 1, vMap ); + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pCon, 8, 0, 0, 0, 0 ); + sat_solver* pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + int Lit = Abc_Var2Lit( 1, 0 ); + int status = sat_solver_addclause( pSat, &Lit, &Lit+1 ); + int nAllCalls = 0; + int nCurrCexes = Vec_IntEntry(vStats[2], i); + //Gia_AigerWrite( pCon, "temp_miter.aig", 0, 0, 0 ); + if ( status == l_True ) + { + nSatOuts++; + //printf( "Running SAT for output %d\n", i ); + if ( Min_ObjLit0(pNew, iObj) >= 2 ) + { + while ( nAllCalls++ < 100 ) + { + int v, iVar = pCnf->nVars - Gia_ManPiNum(pCon), nVars = Gia_ManPiNum(pCon); + sat_solver_randomize( pSat, iVar, nVars ); + status = sat_solver_solve( pSat, NULL, NULL, 0, 0, 0, 0 ); + assert( status == l_True ); + Vec_IntClear( vLits ); + for ( v = 0; v < nVars; v++ ) + Vec_IntPush( vLits, Abc_Var2Lit(Vec_IntEntry(vMap, v), !sat_solver_var_value(pSat, iVar + v)) ); + Min_LitMinimize( pNew, Min_ObjLit0(pNew, iObj), vLits ); + Vec_IntClearAppend( vPatBest, &pNew->vPat ); + if ( 1 ) // minimization + { + //printf( "%d -> ", Vec_IntSize(vPatBest) ); + for ( v = 0; v < 20; v++ ) + { + Min_LitMinimize( pNew, Min_ObjLit0(pNew, iObj), vLits ); + if ( Vec_IntSize(vPatBest) > Vec_IntSize(&pNew->vPat) ) + Vec_IntClearAppend( vPatBest, &pNew->vPat ); + } + //printf( "%d ", Vec_IntSize(vPatBest) ); + } + Vec_IntSort( vPatBest, 0 ); + nCurrCexes += Min_ManAccumulate( vCexes, i*nMinCexes, (i+1)*nMinCexes, vPatBest ); + if ( nCurrCexes == nMinCexes || nAllCalls > 10*nCurrCexes ) + break; + } + } + } + Vec_IntWriteEntry( vStats[0], i, nAllCalls*nMaxTries ); + Vec_IntWriteEntry( vStats[1], i, nAllCalls*nMaxTries ); + Vec_IntWriteEntry( vStats[2], i, nCurrCexes ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + Gia_ManStop( pCon ); + Vec_IntFree( vMap ); + } + } + if ( fVerbose ) + printf( "Used simulation for %d and SAT for %d outputs (out of %d).\n", nSimOuts, nSatOuts, nOuts ); + //Vec_WecPrint( vCexes, 0 ); + if ( vOuts != vOuts0 ) + Vec_IntFreeP( &vOuts ); + Min_ManStop( pNew ); + Vec_IntFree( vPatBest ); + Vec_IntFree( vLits ); + return vCexes; +} + +/**Function************************************************************* + + Synopsis [Bit-packing for selected patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Min_ManBitPackTry( Vec_Wrd_t * vSimsPi, int nWords, int iPat, Vec_Int_t * vLits ) +{ + int i, Lit; + assert( iPat >= 0 && iPat < 64 * nWords ); + Vec_IntForEachEntry( vLits, Lit, i ) + { + word * pInfo = Vec_WrdEntryP( vSimsPi, nWords * Abc_Lit2Var(Lit-2) ); // Lit is based on ObjId + word * pCare = pInfo + Vec_WrdSize(vSimsPi); + if ( Abc_InfoHasBit( (unsigned *)pCare, iPat ) && + Abc_InfoHasBit( (unsigned *)pInfo, iPat ) == Abc_LitIsCompl(Lit) ) // Lit is in ms notation + return 0; + } + Vec_IntForEachEntry( vLits, Lit, i ) + { + word * pInfo = Vec_WrdEntryP( vSimsPi, nWords * Abc_Lit2Var(Lit-2) ); // Lit is based on ObjId + word * pCare = pInfo + Vec_WrdSize(vSimsPi); + Abc_InfoSetBit( (unsigned *)pCare, iPat ); + if ( Abc_InfoHasBit( (unsigned *)pInfo, iPat ) == Abc_LitIsCompl(Lit) ) // Lit is in ms notation + Abc_InfoXorBit( (unsigned *)pInfo, iPat ); + } + return 1; +} +int Min_ManBitPackOne( Vec_Wrd_t * vSimsPi, int iPat0, int nWords, Vec_Int_t * vLits ) +{ + int iPat, nTotal = 64*nWords; + for ( iPat = iPat0 + 1; iPat != iPat0; iPat = (iPat + 1) % nTotal ) + if ( Min_ManBitPackTry( vSimsPi, nWords, iPat, vLits ) ) + break; + return iPat; +} +Vec_Ptr_t * Min_ReloadCexes( Vec_Wec_t * vCexes, int nMinCexes ) +{ + Vec_Ptr_t * vRes = Vec_PtrAlloc( Vec_WecSize(vCexes) ); + int i, c, nOuts = Vec_WecSize(vCexes)/nMinCexes; + for ( i = 0; i < nMinCexes; i++ ) + for ( c = 0; c < nOuts; c++ ) + { + Vec_Int_t * vLevel = Vec_WecEntry( vCexes, c*nMinCexes+i ); + if ( Vec_IntSize(vLevel) ) + Vec_PtrPush( vRes, vLevel ); + } + return vRes; +} + +Vec_Wrd_t * Min_ManBitPack( Gia_Man_t * p, int nWords0, Vec_Wec_t * vCexes, int fRandom, int nMinCexes, Vec_Int_t * vScores, int fVerbose ) +{ + abctime clk = Abc_Clock(); + int fVeryVerbose = 0; + Vec_Wrd_t * vSimsPi = NULL; + Vec_Int_t * vLevel; + int w, nBits, nTotal = 0, fFailed = ABC_INFINITY; + Vec_Int_t * vOrder = NULL; + Vec_Ptr_t * vReload = NULL; + if ( 0 ) + { + vOrder = Vec_IntStartNatural( Vec_WecSize(vCexes)/nMinCexes ); + assert( Vec_IntSize(vOrder) == Vec_IntSize(vScores) ); + assert( Vec_WecSize(vCexes)%nMinCexes == 0 ); + Abc_MergeSortCost2Reverse( Vec_IntArray(vOrder), Vec_IntSize(vOrder), Vec_IntArray(vScores) ); + } + else + vReload = Min_ReloadCexes( vCexes, nMinCexes ); + if ( fVerbose ) + printf( "Packing: " ); + for ( w = nWords0 ? nWords0 : 1; nWords0 ? w <= nWords0 : fFailed > 0; w++ ) + { + int i, iPatUsed, iPat = 0; + //int k, iOut; + Vec_WrdFreeP( &vSimsPi ); + vSimsPi = fRandom ? Vec_WrdStartRandom(2 * Gia_ManCiNum(p) * w) : Vec_WrdStart(2 * Gia_ManCiNum(p) * w); + Vec_WrdShrink( vSimsPi, Vec_WrdSize(vSimsPi)/2 ); + Abc_TtClear( Vec_WrdLimit(vSimsPi), Vec_WrdSize(vSimsPi) ); + fFailed = nTotal = 0; + //Vec_IntForEachEntry( vOrder, iOut, k ) + //Vec_WecForEachLevelStartStop( vCexes, vLevel, i, iOut*nMinCexes, (iOut+1)*nMinCexes ) + Vec_PtrForEachEntry( Vec_Int_t *, vReload, vLevel, i ) + { + //if ( fVeryVerbose && i%nMinCexes == 0 ) + // printf( "\n" ); + if ( Vec_IntSize(vLevel) == 0 ) + continue; + iPatUsed = Min_ManBitPackOne( vSimsPi, iPat, w, vLevel ); + fFailed += iPatUsed == iPat; + iPat = (iPatUsed + 1) % (64*(w-1) - 1); + //if ( fVeryVerbose ) + //printf( "Adding output %3d cex %3d to pattern %3d ", i/nMinCexes, i%nMinCexes, iPatUsed ); + //if ( fVeryVerbose ) + //Vec_IntPrint( vLevel ); + nTotal++; + } + if ( fVerbose ) + printf( "W = %d (F = %d) ", w, fFailed ); +// printf( "Failed patterns = %d\n", fFailed ); + } + if ( fVerbose ) + printf( "Total = %d\n", nTotal ); + if ( fVerbose ) + { + nBits = Abc_TtCountOnesVec( Vec_WrdLimit(vSimsPi), Vec_WrdSize(vSimsPi) ); + printf( "Bit-packing is using %d words and %d bits. Density =%8.4f %%. ", + Vec_WrdSize(vSimsPi)/Gia_ManCiNum(p), nBits, 100.0*nBits/64/Vec_WrdSize(vSimsPi) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + Vec_IntFreeP( &vOrder ); + Vec_PtrFreeP( &vReload ); + return vSimsPi; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Patt_ManOutputErrorCoverage( Vec_Wrd_t * vErrors, int nOuts ) +{ + Vec_Int_t * vCounts = Vec_IntAlloc( nOuts ); + int i, nWords = Vec_WrdSize(vErrors)/nOuts; + assert( Vec_WrdSize(vErrors) == nOuts * nWords ); + for ( i = 0; i < nOuts; i++ ) + Vec_IntPush( vCounts, Abc_TtCountOnesVec(Vec_WrdEntryP(vErrors, nWords * i), nWords) ); + return vCounts; +} +Vec_Wrd_t * Patt_ManTransposeErrors( Vec_Wrd_t * vErrors, int nOuts ) +{ + extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + int nWordsIn = Vec_WrdSize(vErrors) / nOuts; + int nWordsOut = Abc_Bit6WordNum(nOuts); + Vec_Wrd_t * vSims1 = Vec_WrdStart( 64*nWordsIn*nWordsOut ); + Vec_Wrd_t * vSims2 = Vec_WrdStart( 64*nWordsIn*nWordsOut ); + assert( Vec_WrdSize(vErrors) == nWordsIn * nOuts ); + Abc_TtCopy( Vec_WrdArray(vSims1), Vec_WrdArray(vErrors), Vec_WrdSize(vErrors), 0 ); + Extra_BitMatrixTransposeP( vSims1, nWordsIn, vSims2, nWordsOut ); + Vec_WrdFree( vSims1 ); + return vSims2; +} +Vec_Int_t * Patt_ManPatternErrorCoverage( Vec_Wrd_t * vErrors, int nOuts ) +{ + int nWords = Vec_WrdSize(vErrors)/nOuts; + Vec_Wrd_t * vErrors2 = Patt_ManTransposeErrors( vErrors, nOuts ); + Vec_Int_t * vPatErrs = Patt_ManOutputErrorCoverage( vErrors2, 64*nWords ); + Vec_WrdFree( vErrors2 ); + return vPatErrs; +} + +#define ERR_REPT_SIZE 32 +void Patt_ManProfileErrors( Vec_Int_t * vOutErrs, Vec_Int_t * vPatErrs ) +{ + int nOuts = Vec_IntSize(vOutErrs); + int nPats = Vec_IntSize(vPatErrs); + int ErrOuts[ERR_REPT_SIZE+1] = {0}; + int ErrPats[ERR_REPT_SIZE+1] = {0}; + int i, Errs, nErrors1 = 0, nErrors2 = 0; + Vec_IntForEachEntry( vOutErrs, Errs, i ) + { + nErrors1 += Errs; + ErrOuts[Errs < ERR_REPT_SIZE ? Errs : ERR_REPT_SIZE]++; + } + Vec_IntForEachEntry( vPatErrs, Errs, i ) + { + nErrors2 += Errs; + ErrPats[Errs < ERR_REPT_SIZE ? Errs : ERR_REPT_SIZE]++; + } + assert( nErrors1 == nErrors2 ); + // errors/error_outputs/error_patterns + //printf( "\nError statistics:\n" ); + printf( "Errors =%6d ", nErrors1 ); + printf( "ErrPOs =%5d (Ave = %5.2f) ", nOuts-ErrOuts[0], 1.0*nErrors1/Abc_MaxInt(1, nOuts-ErrOuts[0]) ); + printf( "Patterns =%5d (Ave = %5.2f) ", nPats, 1.0*nErrors1/nPats ); + printf( "Density =%8.4f %%\n", 100.0*nErrors1/nPats/Abc_MaxInt(1, nOuts-ErrOuts[0]) ); + // how many times each output fails + printf( "Outputs: " ); + for ( i = 0; i <= ERR_REPT_SIZE; i++ ) + if ( ErrOuts[i] ) + printf( "%s%d=%d ", i == ERR_REPT_SIZE? ">" : "", i, ErrOuts[i] ); + printf( "\n" ); + // how many times each patterns fails an output + printf( "Patterns: " ); + for ( i = 0; i <= ERR_REPT_SIZE; i++ ) + if ( ErrPats[i] ) + printf( "%s%d=%d ", i == ERR_REPT_SIZE? ">" : "", i, ErrPats[i] ); + printf( "\n" ); +} +int Patt_ManProfileErrorsOne( Vec_Wrd_t * vErrors, int nOuts ) +{ + Vec_Int_t * vCoErrs = Patt_ManOutputErrorCoverage( vErrors, nOuts ); + Vec_Int_t * vPatErrs = Patt_ManPatternErrorCoverage( vErrors, nOuts ); + Patt_ManProfileErrors( vCoErrs, vPatErrs ); + Vec_IntFree( vPatErrs ); + Vec_IntFree( vCoErrs ); + return 1; +} + +Vec_Int_t * Min_ManGetUnsolved( Gia_Man_t * p ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + int i, Driver; + Gia_ManForEachCoDriverId( p, Driver, i ) + if ( Driver > 0 ) + Vec_IntPush( vRes, i ); + if ( Vec_IntSize(vRes) == 0 ) + Vec_IntFreeP( &vRes ); + return vRes; +} +Vec_Wrd_t * Min_ManRemapSims( int nInputs, Vec_Int_t * vMap, Vec_Wrd_t * vSimsPi ) +{ + int i, iObj, nWords = Vec_WrdSize(vSimsPi)/Vec_IntSize(vMap); + Vec_Wrd_t * vSimsNew = Vec_WrdStart( 2 * nInputs * nWords ); + //Vec_Wrd_t * vSimsNew = Vec_WrdStartRandom( nInputs * nWords ); + //Vec_WrdFillExtra( vSimsNew, 2 * nInputs * nWords, 0 ); + assert( Vec_WrdSize(vSimsPi)%Vec_IntSize(vMap) == 0 ); + Vec_WrdShrink( vSimsNew, Vec_WrdSize(vSimsNew)/2 ); + Vec_IntForEachEntry( vMap, iObj, i ) + { + Abc_TtCopy( Vec_WrdArray(vSimsNew) + (iObj-1)*nWords, Vec_WrdArray(vSimsPi) + i*nWords, nWords, 0 ); + Abc_TtCopy( Vec_WrdLimit(vSimsNew) + (iObj-1)*nWords, Vec_WrdLimit(vSimsPi) + i*nWords, nWords, 0 ); + } + return vSimsNew; +} +Vec_Wrd_t * Gia_ManCollectSims( Gia_Man_t * pSwp, int nWords, Vec_Int_t * vOuts, int nMaxTries, int nMinCexes, int fUseSim, int fUseSat, int fVerbose, int fVeryVerbose ) +{ + Vec_Int_t * vStats[3] = {0}; int i, iObj; + Vec_Int_t * vMap = Vec_IntAlloc( 100 ); + Gia_Man_t * pSwp2 = Gia_ManDupCones2( pSwp, Vec_IntArray(vOuts), Vec_IntSize(vOuts), vMap ); + Vec_Wec_t * vCexes = Min_ManComputeCexes( pSwp2, NULL, nMaxTries, nMinCexes, vStats, fUseSim, fUseSat, fVerbose ); + Vec_Wrd_t * vSimsPi = Min_ManBitPack( pSwp2, nWords, vCexes, 1, nMinCexes, vStats[0], fVerbose ); + Vec_Wrd_t * vSimsPo = Gia_ManSimPatSimOut( pSwp2, vSimsPi, 1 ); + Vec_Int_t * vCounts = Patt_ManOutputErrorCoverage( vSimsPo, Vec_IntSize(vOuts) ); + if ( fVerbose ) + Patt_ManProfileErrorsOne( vSimsPo, Vec_IntSize(vOuts) ); + if ( fVeryVerbose ) + { + printf( "Unsolved = %4d ", Vec_IntSize(vOuts) ); + Gia_ManPrintStats( pSwp2, NULL ); + Vec_IntForEachEntry( vOuts, iObj, i ) + { + printf( "%4d : ", i ); + printf( "Out = %5d ", Vec_IntEntry(vMap, i) ); + printf( "SimAll =%8d ", Vec_IntEntry(vStats[0], i) ); + printf( "SimGood =%8d ", Vec_IntEntry(vStats[1], i) ); + printf( "PatsAll =%8d ", Vec_IntEntry(vStats[2], i) ); + printf( "Count = %5d ", Vec_IntEntry(vCounts, i) ); + printf( "\n" ); + if ( i == 20 ) + break; + } + } + for ( i = 0; i < 3; i++ ) + Vec_IntFree( vStats[i] ); + Vec_IntFree( vCounts ); + Vec_WrdFree( vSimsPo ); + Vec_WecFree( vCexes ); + Gia_ManStop( pSwp2 ); + //printf( "Compressing inputs: %5d -> %5d\n", Gia_ManCiNum(pSwp), Vec_IntSize(vMap) ); + vSimsPi = Min_ManRemapSims( Gia_ManCiNum(pSwp), vMap, vSimsPo = vSimsPi ); + Vec_WrdFree( vSimsPo ); + Vec_IntFree( vMap ); + return vSimsPi; +} +Vec_Wrd_t * Min_ManCollect( Gia_Man_t * p, int nConf, int nConf2, int nMaxTries, int nMinCexes, int fUseSim, int fUseSat, int fVerbose, int fVeryVerbose ) +{ + abctime clk = Abc_Clock(); + extern Gia_Man_t * Cec4_ManSimulateTest4( Gia_Man_t * p, int nBTLimit, int nBTLimitPo, int fVerbose ); + Gia_Man_t * pSwp = Cec4_ManSimulateTest4( p, nConf, nConf2, 0 ); + abctime clkSweep = Abc_Clock() - clk; + int nArgs = fVerbose ? printf( "Generating patterns: Conf = %d (%d). Tries = %d. Pats = %d. Sim = %d. SAT = %d.\n", + nConf, nConf2, nMaxTries, nMinCexes, fUseSim, fUseSat ) : 0; + Vec_Int_t * vOuts = Min_ManGetUnsolved( pSwp ); + Vec_Wrd_t * vSimsPi = vOuts ? Gia_ManCollectSims( pSwp, 0, vOuts, nMaxTries, nMinCexes, fUseSim, fUseSat, fVerbose, fVeryVerbose ) : NULL; + if ( vOuts == NULL ) + printf( "There is no satisfiable outputs.\n" ); + if ( fVerbose ) + Abc_PrintTime( 1, "Sweep time", clkSweep ); + if ( fVerbose ) + Abc_PrintTime( 1, "Total time", Abc_Clock() - clk ); + Vec_IntFreeP( &vOuts ); + Gia_ManStop( pSwp ); + nArgs = 0; + return vSimsPi; +} +void Min_ManTest2( Gia_Man_t * p ) +{ + Vec_Wrd_t * vSimsPi = Min_ManCollect( p, 100000, 100000, 10000, 20, 1, 0, 1, 1 ); + Vec_WrdFreeP( &vSimsPi ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/gia/giaSim5.c b/src/aig/gia/giaReshape1.c index ab33c218..52b40bdc 100644 --- a/src/aig/gia/giaSim5.c +++ b/src/aig/gia/giaReshape1.c @@ -1,12 +1,12 @@ /**CFile**************************************************************** - FileName [giaSim5.c] + FileName [giaReshape.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] - Synopsis [Simulation engine.] + Synopsis [] Author [Alan Mishchenko] @@ -14,23 +14,19 @@ Date [Ver. 1.0. Started - June 20, 2005.] - Revision [$Id: giaSim5.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" -#include "base/main/main.h" ABC_NAMESPACE_IMPL_START + //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -void Sim_Init( Abc_Frame_t * pAbc ) {} -void Sim_End( Abc_Frame_t * pAbc ) {} -void Gia_DatFree( Gia_Dat_t * p ) {} - //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -40,12 +36,16 @@ void Gia_DatFree( Gia_Dat_t * p ) {} Synopsis [] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ +Gia_Man_t * Gia_ManReshape1( Gia_Man_t * p, int fUseSimple, int fVerbose, int fVeryVerbose ) +{ + return NULL; +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/aig/gia/giaSim4.c b/src/aig/gia/giaReshape2.c index 6ce89cf0..98a4d855 100644 --- a/src/aig/gia/giaSim4.c +++ b/src/aig/gia/giaReshape2.c @@ -1,12 +1,12 @@ /**CFile**************************************************************** - FileName [giaSim4.c] + FileName [giaReshape.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] - Synopsis [Simulation engine.] + Synopsis [] Author [Alan Mishchenko] @@ -14,7 +14,7 @@ Date [Ver. 1.0. Started - June 20, 2005.] - Revision [$Id: giaSim4.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ @@ -35,15 +35,15 @@ ABC_NAMESPACE_IMPL_START Synopsis [] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -int Gia_Sim4Try( char * pFileName0, char * pFileName1, char * pFileName2, int nWords, int nBeam, int LevL, int LevU, int fOrder, int fFancy, int fUseBuf, int fVerbose ) +Gia_Man_t * Gia_ManReshape2( Gia_Man_t * p, int fUseSimple, int fVerbose, int fVeryVerbose ) { - return 0; + return NULL; } //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaResub.c b/src/aig/gia/giaResub.c index b8c0e294..33fd5276 100644 --- a/src/aig/gia/giaResub.c +++ b/src/aig/gia/giaResub.c @@ -22,10 +22,10 @@ #include "misc/vec/vecWec.h" #include "misc/vec/vecQue.h" #include "misc/vec/vecHsh.h" +#include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START - //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// @@ -271,6 +271,520 @@ Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); } + + + +/**Function************************************************************* + + Synopsis [Resubstitution data-structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +typedef struct Gia_ResbMan_t_ Gia_ResbMan_t; +struct Gia_ResbMan_t_ +{ + int nWords; + int nLimit; + int nDivsMax; + int iChoice; + int fUseXor; + int fDebug; + int fVerbose; + int fVeryVerbose; + Vec_Ptr_t * vDivs; + Vec_Int_t * vGates; + Vec_Int_t * vUnateLits[2]; + Vec_Int_t * vNotUnateVars[2]; + Vec_Int_t * vUnatePairs[2]; + Vec_Int_t * vBinateVars; + Vec_Int_t * vUnateLitsW[2]; + Vec_Int_t * vUnatePairsW[2]; + Vec_Wec_t * vSorter; + word * pSets[2]; + word * pDivA; + word * pDivB; + Vec_Wrd_t * vSims; +}; +Gia_ResbMan_t * Gia_ResbAlloc( int nWords ) +{ + Gia_ResbMan_t * p = ABC_CALLOC( Gia_ResbMan_t, 1 ); + p->nWords = nWords; + p->vUnateLits[0] = Vec_IntAlloc( 100 ); + p->vUnateLits[1] = Vec_IntAlloc( 100 ); + p->vNotUnateVars[0] = Vec_IntAlloc( 100 ); + p->vNotUnateVars[1] = Vec_IntAlloc( 100 ); + p->vUnatePairs[0] = Vec_IntAlloc( 100 ); + p->vUnatePairs[1] = Vec_IntAlloc( 100 ); + p->vUnateLitsW[0] = Vec_IntAlloc( 100 ); + p->vUnateLitsW[1] = Vec_IntAlloc( 100 ); + p->vUnatePairsW[0] = Vec_IntAlloc( 100 ); + p->vUnatePairsW[1] = Vec_IntAlloc( 100 ); + p->vSorter = Vec_WecAlloc( nWords*64 ); + p->vBinateVars = Vec_IntAlloc( 100 ); + p->vGates = Vec_IntAlloc( 100 ); + p->vDivs = Vec_PtrAlloc( 100 ); + p->pSets[0] = ABC_CALLOC( word, nWords ); + p->pSets[1] = ABC_CALLOC( word, nWords ); + p->pDivA = ABC_CALLOC( word, nWords ); + p->pDivB = ABC_CALLOC( word, nWords ); + p->vSims = Vec_WrdAlloc( 100 ); + return p; +} +void Gia_ResbInit( Gia_ResbMan_t * p, Vec_Ptr_t * vDivs, int nWords, int nLimit, int nDivsMax, int iChoice, int fUseXor, int fDebug, int fVerbose, int fVeryVerbose ) +{ + assert( p->nWords == nWords ); + p->nLimit = nLimit; + p->nDivsMax = nDivsMax; + p->iChoice = iChoice; + p->fUseXor = fUseXor; + p->fDebug = fDebug; + p->fVerbose = fVerbose; + p->fVeryVerbose = fVeryVerbose; + Abc_TtCopy( p->pSets[0], (word *)Vec_PtrEntry(vDivs, 0), nWords, 0 ); + Abc_TtCopy( p->pSets[1], (word *)Vec_PtrEntry(vDivs, 1), nWords, 0 ); + Vec_PtrClear( p->vDivs ); + Vec_PtrAppend( p->vDivs, vDivs ); + Vec_IntClear( p->vGates ); + Vec_IntClear( p->vUnateLits[0] ); + Vec_IntClear( p->vUnateLits[1] ); + Vec_IntClear( p->vNotUnateVars[0] ); + Vec_IntClear( p->vNotUnateVars[1] ); + Vec_IntClear( p->vUnatePairs[0] ); + Vec_IntClear( p->vUnatePairs[1] ); + Vec_IntClear( p->vUnateLitsW[0] ); + Vec_IntClear( p->vUnateLitsW[1] ); + Vec_IntClear( p->vUnatePairsW[0] ); + Vec_IntClear( p->vUnatePairsW[1] ); + Vec_IntClear( p->vBinateVars ); +} +void Gia_ResbFree( Gia_ResbMan_t * p ) +{ + Vec_IntFree( p->vUnateLits[0] ); + Vec_IntFree( p->vUnateLits[1] ); + Vec_IntFree( p->vNotUnateVars[0] ); + Vec_IntFree( p->vNotUnateVars[1] ); + Vec_IntFree( p->vUnatePairs[0] ); + Vec_IntFree( p->vUnatePairs[1] ); + Vec_IntFree( p->vUnateLitsW[0] ); + Vec_IntFree( p->vUnateLitsW[1] ); + Vec_IntFree( p->vUnatePairsW[0] ); + Vec_IntFree( p->vUnatePairsW[1] ); + Vec_IntFree( p->vBinateVars ); + Vec_IntFree( p->vGates ); + Vec_WrdFree( p->vSims ); + Vec_PtrFree( p->vDivs ); + Vec_WecFree( p->vSorter ); + ABC_FREE( p->pSets[0] ); + ABC_FREE( p->pSets[1] ); + ABC_FREE( p->pDivA ); + ABC_FREE( p->pDivB ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Print resubstitution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManResubPrintNode( Vec_Int_t * vRes, int nVars, int Node, int fCompl ) +{ + extern void Gia_ManResubPrintLit( Vec_Int_t * vRes, int nVars, int iLit ); + int iLit0 = Vec_IntEntry( vRes, 2*Node + 0 ); + int iLit1 = Vec_IntEntry( vRes, 2*Node + 1 ); + assert( iLit0 != iLit1 ); + if ( iLit0 > iLit1 && Abc_LitIsCompl(fCompl) ) // xor + { + printf( "~" ); + fCompl = 0; + } + printf( "(" ); + Gia_ManResubPrintLit( vRes, nVars, Abc_LitNotCond(iLit0, fCompl) ); + printf( " %c ", iLit0 > iLit1 ? '^' : (fCompl ? '|' : '&') ); + Gia_ManResubPrintLit( vRes, nVars, Abc_LitNotCond(iLit1, fCompl) ); + printf( ")" ); +} +void Gia_ManResubPrintLit( Vec_Int_t * vRes, int nVars, int iLit ) +{ + if ( Abc_Lit2Var(iLit) < nVars ) + { + if ( nVars < 26 ) + printf( "%s%c", Abc_LitIsCompl(iLit) ? "~":"", 'a' + Abc_Lit2Var(iLit)-2 ); + else + printf( "%si%d", Abc_LitIsCompl(iLit) ? "~":"", Abc_Lit2Var(iLit)-2 ); + } + else + Gia_ManResubPrintNode( vRes, nVars, Abc_Lit2Var(iLit) - nVars, Abc_LitIsCompl(iLit) ); +} +int Gia_ManResubPrint( Vec_Int_t * vRes, int nVars ) +{ + int iTopLit; + if ( Vec_IntSize(vRes) == 0 ) + return printf( "none" ); + assert( Vec_IntSize(vRes) % 2 == 1 ); + iTopLit = Vec_IntEntryLast(vRes); + if ( iTopLit == 0 ) + return printf( "const0" ); + if ( iTopLit == 1 ) + return printf( "const1" ); + Gia_ManResubPrintLit( vRes, nVars, iTopLit ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Verify resubstitution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManResubVerify( Gia_ResbMan_t * p, word * pFunc ) +{ + int nVars = Vec_PtrSize(p->vDivs); + int iTopLit, RetValue; + word * pDivRes; + if ( Vec_IntSize(p->vGates) == 0 ) + return -1; + iTopLit = Vec_IntEntryLast(p->vGates); + assert( iTopLit >= 0 ); + if ( iTopLit == 0 ) + { + if ( pFunc ) Abc_TtClear( pFunc, p->nWords ); + return Abc_TtIsConst0( p->pSets[1], p->nWords ); + } + if ( iTopLit == 1 ) + { + if ( pFunc ) Abc_TtFill( pFunc, p->nWords ); + return Abc_TtIsConst0( p->pSets[0], p->nWords ); + } + if ( Abc_Lit2Var(iTopLit) < nVars ) + { + assert( Vec_IntSize(p->vGates) == 1 ); + pDivRes = (word *)Vec_PtrEntry( p->vDivs, Abc_Lit2Var(iTopLit) ); + } + else + { + int i, iLit0, iLit1; + assert( Vec_IntSize(p->vGates) > 1 ); + assert( Vec_IntSize(p->vGates) % 2 == 1 ); + assert( Abc_Lit2Var(iTopLit)-nVars == Vec_IntSize(p->vGates)/2-1 ); + Vec_WrdFill( p->vSims, p->nWords * Vec_IntSize(p->vGates)/2, 0 ); + Vec_IntForEachEntryDouble( p->vGates, iLit0, iLit1, i ) + { + int iVar0 = Abc_Lit2Var(iLit0); + int iVar1 = Abc_Lit2Var(iLit1); + word * pDiv0 = iVar0 < nVars ? (word *)Vec_PtrEntry(p->vDivs, iVar0) : Vec_WrdEntryP(p->vSims, p->nWords*(iVar0 - nVars)); + word * pDiv1 = iVar1 < nVars ? (word *)Vec_PtrEntry(p->vDivs, iVar1) : Vec_WrdEntryP(p->vSims, p->nWords*(iVar1 - nVars)); + word * pDiv = Vec_WrdEntryP(p->vSims, p->nWords*i/2); + if ( iVar0 < iVar1 ) + Abc_TtAndCompl( pDiv, pDiv0, Abc_LitIsCompl(iLit0), pDiv1, Abc_LitIsCompl(iLit1), p->nWords ); + else if ( iVar0 > iVar1 ) + { + assert( !Abc_LitIsCompl(iLit0) ); + assert( !Abc_LitIsCompl(iLit1) ); + Abc_TtXor( pDiv, pDiv0, pDiv1, p->nWords, 0 ); + } + else assert( 0 ); + } + pDivRes = Vec_WrdEntryP( p->vSims, p->nWords*(Vec_IntSize(p->vGates)/2-1) ); + } + if ( Abc_LitIsCompl(iTopLit) ) + RetValue = !Abc_TtIntersectOne(p->pSets[1], 0, pDivRes, 0, p->nWords) && !Abc_TtIntersectOne(p->pSets[0], 0, pDivRes, 1, p->nWords); + else + RetValue = !Abc_TtIntersectOne(p->pSets[0], 0, pDivRes, 0, p->nWords) && !Abc_TtIntersectOne(p->pSets[1], 0, pDivRes, 1, p->nWords); + if ( pFunc ) Abc_TtCopy( pFunc, pDivRes, p->nWords, Abc_LitIsCompl(iTopLit) ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Construct AIG manager from gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManConstructFromMap( Gia_Man_t * pNew, Vec_Int_t * vGates, int nVars, Vec_Int_t * vUsed, Vec_Int_t * vCopy, int fHash ) +{ + int i, iLit0, iLit1, iLitRes, iTopLit = Vec_IntEntryLast( vGates ); + assert( Vec_IntSize(vUsed) == nVars ); + assert( Vec_IntSize(vGates) > 1 ); + assert( Vec_IntSize(vGates) % 2 == 1 ); + assert( Abc_Lit2Var(iTopLit)-nVars == Vec_IntSize(vGates)/2-1 ); + Vec_IntClear( vCopy ); + Vec_IntForEachEntryDouble( vGates, iLit0, iLit1, i ) + { + int iVar0 = Abc_Lit2Var(iLit0); + int iVar1 = Abc_Lit2Var(iLit1); + int iRes0 = iVar0 < nVars ? Vec_IntEntry(vUsed, iVar0) : Vec_IntEntry(vCopy, iVar0 - nVars); + int iRes1 = iVar1 < nVars ? Vec_IntEntry(vUsed, iVar1) : Vec_IntEntry(vCopy, iVar1 - nVars); + if ( iVar0 < iVar1 ) + { + if ( fHash ) + iLitRes = Gia_ManHashAnd( pNew, Abc_LitNotCond(iRes0, Abc_LitIsCompl(iLit0)), Abc_LitNotCond(iRes1, Abc_LitIsCompl(iLit1)) ); + else + iLitRes = Gia_ManAppendAnd( pNew, Abc_LitNotCond(iRes0, Abc_LitIsCompl(iLit0)), Abc_LitNotCond(iRes1, Abc_LitIsCompl(iLit1)) ); + } + else if ( iVar0 > iVar1 ) + { + assert( !Abc_LitIsCompl(iLit0) ); + assert( !Abc_LitIsCompl(iLit1) ); + if ( fHash ) + iLitRes = Gia_ManHashXor( pNew, Abc_LitNotCond(iRes0, Abc_LitIsCompl(iLit0)), Abc_LitNotCond(iRes1, Abc_LitIsCompl(iLit1)) ); + else + iLitRes = Gia_ManAppendXor( pNew, Abc_LitNotCond(iRes0, Abc_LitIsCompl(iLit0)), Abc_LitNotCond(iRes1, Abc_LitIsCompl(iLit1)) ); + } + else assert( 0 ); + Vec_IntPush( vCopy, iLitRes ); + } + assert( Vec_IntSize(vCopy) == Vec_IntSize(vGates)/2 ); + iLitRes = Vec_IntEntry( vCopy, Vec_IntSize(vGates)/2-1 ); + return iLitRes; +} +Gia_Man_t * Gia_ManConstructFromGates( Vec_Wec_t * vFuncs, int nDivs ) +{ + Vec_Int_t * vGates; int i, k, iLit; + Vec_Int_t * vCopy = Vec_IntAlloc( 100 ); + Vec_Int_t * vUsed = Vec_IntStartFull( nDivs ); + Gia_Man_t * pNew = Gia_ManStart( 100 ); + pNew->pName = Abc_UtilStrsav( "resub" ); + Vec_WecForEachLevel( vFuncs, vGates, i ) + { + assert( Vec_IntSize(vGates) % 2 == 1 ); + Vec_IntForEachEntry( vGates, iLit, k ) + { + int iVar = Abc_Lit2Var(iLit); + if ( iVar > 0 && iVar < nDivs && Vec_IntEntry(vUsed, iVar) == -1 ) + Vec_IntWriteEntry( vUsed, iVar, Gia_ManAppendCi(pNew) ); + } + } + Vec_WecForEachLevel( vFuncs, vGates, i ) + { + int iLitRes, iTopLit = Vec_IntEntryLast( vGates ); + if ( Abc_Lit2Var(iTopLit) == 0 ) + iLitRes = 0; + else if ( Abc_Lit2Var(iTopLit) < nDivs ) + iLitRes = Vec_IntEntry( vUsed, Abc_Lit2Var(iTopLit) ); + else + iLitRes = Gia_ManConstructFromMap( pNew, vGates, nDivs, vUsed, vCopy, 0 ); + Gia_ManAppendCo( pNew, Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iTopLit) ) ); + } + Vec_IntFree( vCopy ); + Vec_IntFree( vUsed ); + return pNew; +} +Gia_Man_t * Gia_ManConstructFromGates2( Vec_Wec_t * vFuncs, Vec_Wec_t * vDivs, int nObjs, Vec_Int_t ** pvSupp ) +{ + Vec_Int_t * vGates; int i, k, iVar, iLit; + Vec_Int_t * vSupp = Vec_IntAlloc( 100 ); + Vec_Int_t * vCopy = Vec_IntAlloc( 100 ); + Vec_Wec_t * vUseds = Vec_WecStart( Vec_WecSize(vDivs) ); + Vec_Int_t * vMap = Vec_IntStartFull( nObjs ); + Gia_Man_t * pNew = Gia_ManStart( 100 ); + pNew->pName = Abc_UtilStrsav( "resub" ); + assert( Vec_WecSize(vFuncs) == Vec_WecSize(vDivs) ); + Vec_WecForEachLevel( vFuncs, vGates, i ) + { + Vec_Int_t * vDiv = Vec_WecEntry( vDivs, i ); + assert( Vec_IntSize(vGates) % 2 == 1 ); + Vec_IntForEachEntry( vGates, iLit, k ) + { + int iVar = Abc_Lit2Var(iLit); + if ( iVar > 0 && iVar < Vec_IntSize(vDiv) && Vec_IntEntry(vMap, Vec_IntEntry(vDiv, iVar)) == -1 ) + Vec_IntWriteEntry( vMap, Vec_IntPushReturn(vSupp, Vec_IntEntry(vDiv, iVar)), 0 ); + } + } + Vec_IntSort( vSupp, 0 ); + Vec_IntForEachEntry( vSupp, iVar, k ) + Vec_IntWriteEntry( vMap, iVar, Gia_ManAppendCi(pNew) ); + Vec_WecForEachLevel( vFuncs, vGates, i ) + { + Vec_Int_t * vDiv = Vec_WecEntry( vDivs, i ); + Vec_Int_t * vUsed = Vec_WecEntry( vUseds, i ); + Vec_IntFill( vUsed, Vec_IntSize(vDiv), -1 ); + Vec_IntForEachEntry( vGates, iLit, k ) + { + int iVar = Abc_Lit2Var(iLit); + if ( iVar > 0 && iVar < Vec_IntSize(vDiv) ) + { + assert( Vec_IntEntry(vMap, Vec_IntEntry(vDiv, iVar)) > 0 ); + Vec_IntWriteEntry( vUsed, iVar, Vec_IntEntry(vMap, Vec_IntEntry(vDiv, iVar)) ); + } + } + } + Vec_WecForEachLevel( vFuncs, vGates, i ) + { + Vec_Int_t * vDiv = Vec_WecEntry( vDivs, i ); + Vec_Int_t * vUsed = Vec_WecEntry( vUseds, i ); + int iLitRes, iTopLit = Vec_IntEntryLast( vGates ); + if ( Abc_Lit2Var(iTopLit) == 0 ) + iLitRes = 0; + else if ( Abc_Lit2Var(iTopLit) < Vec_IntSize(vDiv) ) + iLitRes = Vec_IntEntry( vUsed, Abc_Lit2Var(iTopLit) ); + else + iLitRes = Gia_ManConstructFromMap( pNew, vGates, Vec_IntSize(vDiv), vUsed, vCopy, 0 ); + Gia_ManAppendCo( pNew, Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iTopLit) ) ); + } + Vec_IntFree( vMap ); + Vec_IntFree( vCopy ); + Vec_WecFree( vUseds ); + if ( pvSupp ) + *pvSupp = vSupp; + else + Vec_IntFree( vSupp ); + return pNew; +} +Vec_Int_t * Gia_ManToGates( Gia_Man_t * p ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( 2*Gia_ManAndNum(p) + 1 ); + Gia_Obj_t * pRoot = Gia_ManCo( p, 0 ); + int iRoot = Gia_ObjFaninId0p(p, pRoot) - 1; + int nVars = Gia_ManCiNum(p); + assert( Gia_ManCoNum(p) == 1 ); + if ( iRoot == -1 ) + Vec_IntPush( vRes, Gia_ObjFaninC0(pRoot) ); + else if ( iRoot < nVars ) + Vec_IntPush( vRes, 4 + Abc_Var2Lit(iRoot, Gia_ObjFaninC0(pRoot)) ); + else + { + Gia_Obj_t * pObj, * pLast = NULL; int i; + Gia_ManForEachCi( p, pObj, i ) + assert( Gia_ObjId(p, pObj) == i+1 ); + Gia_ManForEachAnd( p, pObj, i ) + { + int iLit0 = Abc_Var2Lit( Gia_ObjFaninId0(pObj, i) - 1, Gia_ObjFaninC0(pObj) ); + int iLit1 = Abc_Var2Lit( Gia_ObjFaninId1(pObj, i) - 1, Gia_ObjFaninC1(pObj) ); + if ( iLit0 > iLit1 ) + iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1; + Vec_IntPushTwo( vRes, 4 + iLit0, 4 + iLit1 ); + pLast = pObj; + } + assert( pLast == Gia_ObjFanin0(pRoot) ); + Vec_IntPush( vRes, 4 + Abc_Var2Lit(iRoot, Gia_ObjFaninC0(pRoot)) ); + } + assert( Vec_IntSize(vRes) == 2*Gia_ManAndNum(p) + 1 ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [Construct AIG manager from gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManInsertOrder_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vObjs, Vec_Wec_t * vFuncs, Vec_Int_t * vNodes ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + if ( iObj == 0 ) + return; + if ( pObj->fPhase ) + { + int nVars = Gia_ManObjNum(p); + int k, iLit, Index = Vec_IntFind( vObjs, iObj ); + Vec_Int_t * vGates = Vec_WecEntry( vFuncs, Index ); + assert( Gia_ObjIsCo(pObj) || Gia_ObjIsAnd(pObj) ); + Vec_IntForEachEntry( vGates, iLit, k ) + if ( Abc_Lit2Var(iLit) < nVars ) + Gia_ManInsertOrder_rec( p, Abc_Lit2Var(iLit), vObjs, vFuncs, vNodes ); + } + else if ( Gia_ObjIsCo(pObj) ) + Gia_ManInsertOrder_rec( p, Gia_ObjFaninId0p(p, pObj), vObjs, vFuncs, vNodes ); + else if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ManInsertOrder_rec( p, Gia_ObjFaninId0p(p, pObj), vObjs, vFuncs, vNodes ); + Gia_ManInsertOrder_rec( p, Gia_ObjFaninId1p(p, pObj), vObjs, vFuncs, vNodes ); + } + else assert( Gia_ObjIsCi(pObj) ); + if ( !Gia_ObjIsCi(pObj) ) + Vec_IntPush( vNodes, iObj ); +} +Vec_Int_t * Gia_ManInsertOrder( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wec_t * vFuncs ) +{ + int i, Id; + Vec_Int_t * vNodes = Vec_IntAlloc( Gia_ManObjNum(p) ); + Gia_ManForEachCoId( p, Id, i ) + Gia_ManInsertOrder_rec( p, Id, vObjs, vFuncs, vNodes ); + return vNodes; +} +Gia_Man_t * Gia_ManInsertFromGates( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wec_t * vFuncs ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, nVars = Gia_ManObjNum(p); + Vec_Int_t * vUsed = Vec_IntStartFull( nVars ); + Vec_Int_t * vNodes, * vCopy = Vec_IntAlloc(100); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + pObj->fPhase = 1; + vNodes = Gia_ManInsertOrder( p, vObjs, vFuncs ); + pNew = Gia_ManStart( Gia_ManObjNum(p) + 1000 ); + Gia_ManHashStart( pNew ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + if ( !pObj->fPhase ) + { + if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else assert( 0 ); + } + else + { + int k, iLit, Index = Vec_IntFind( vObjs, Gia_ObjId(p, pObj) ); + Vec_Int_t * vGates = Vec_WecEntry( vFuncs, Index ); + int iLitRes, iTopLit = Vec_IntEntryLast( vGates ); + if ( Abc_Lit2Var(iTopLit) == 0 ) + iLitRes = 0; + else if ( Abc_Lit2Var(iTopLit) < nVars ) + iLitRes = Gia_ManObj(p, Abc_Lit2Var(iTopLit))->Value; + else + { + Vec_IntForEachEntry( vGates, iLit, k ) + Vec_IntWriteEntry( vUsed, Abc_Lit2Var(iLit), Gia_ManObj(p, Abc_Lit2Var(iLit))->Value ); + iLitRes = Gia_ManConstructFromMap( pNew, vGates, nVars, vUsed, vCopy, 1 ); + Vec_IntForEachEntry( vGates, iLit, k ) + Vec_IntWriteEntry( vUsed, Abc_Lit2Var(iLit), -1 ); + } + pObj->Value = Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iTopLit) ); + } + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, pObj->Value ); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + pObj->fPhase = 0; + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vNodes ); + Vec_IntFree( vUsed ); + Vec_IntFree( vCopy ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + /**Function************************************************************* Synopsis [Perform resubstitution.] @@ -282,6 +796,1257 @@ Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); SeeAlso [] ***********************************************************************/ +static inline int Gia_ManFindFirstCommonLit( Vec_Int_t * vArr1, Vec_Int_t * vArr2, int fVerbose ) +{ + int * pBeg1 = vArr1->pArray; + int * pBeg2 = vArr2->pArray; + int * pEnd1 = vArr1->pArray + vArr1->nSize; + int * pEnd2 = vArr2->pArray + vArr2->nSize; + int * pStart1 = vArr1->pArray; + int * pStart2 = vArr2->pArray; + int nRemoved = 0; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( Abc_Lit2Var(*pBeg1) == Abc_Lit2Var(*pBeg2) ) + { + if ( *pBeg1 != *pBeg2 ) + return *pBeg1; + else + pBeg1++, pBeg2++; + nRemoved++; + } + else if ( *pBeg1 < *pBeg2 ) + *pStart1++ = *pBeg1++; + else + *pStart2++ = *pBeg2++; + } + while ( pBeg1 < pEnd1 ) + *pStart1++ = *pBeg1++; + while ( pBeg2 < pEnd2 ) + *pStart2++ = *pBeg2++; + Vec_IntShrink( vArr1, pStart1 - vArr1->pArray ); + Vec_IntShrink( vArr2, pStart2 - vArr2->pArray ); + //if ( fVerbose ) printf( "Removed %d duplicated entries. Array1 = %d. Array2 = %d.\n", nRemoved, Vec_IntSize(vArr1), Vec_IntSize(vArr2) ); + return -1; +} + +void Gia_ManFindOneUnateInt( word * pOff, word * pOn, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits, Vec_Int_t * vNotUnateVars ) +{ + word * pDiv; int i; + Vec_IntClear( vUnateLits ); + Vec_IntClear( vNotUnateVars ); + Vec_PtrForEachEntryStart( word *, vDivs, pDiv, i, 2 ) + if ( !Abc_TtIntersectOne( pOff, 0, pDiv, 0, nWords ) ) + Vec_IntPush( vUnateLits, Abc_Var2Lit(i, 0) ); + else if ( !Abc_TtIntersectOne( pOff, 0, pDiv, 1, nWords ) ) + Vec_IntPush( vUnateLits, Abc_Var2Lit(i, 1) ); + else + Vec_IntPush( vNotUnateVars, i ); +} +int Gia_ManFindOneUnate( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits[2], Vec_Int_t * vNotUnateVars[2], int fVerbose ) +{ + int n; + if ( fVerbose ) printf( " " ); + for ( n = 0; n < 2; n++ ) + { + Gia_ManFindOneUnateInt( pSets[n], pSets[!n], vDivs, nWords, vUnateLits[n], vNotUnateVars[n] ); + if ( fVerbose ) printf( "U%d =%4d ", n, Vec_IntSize(vUnateLits[n]) ); + } + return Gia_ManFindFirstCommonLit( vUnateLits[0], vUnateLits[1], fVerbose ); +} + +static inline int Gia_ManDivCover( word * pOff, word * pOn, word * pDivA, int ComplA, word * pDivB, int ComplB, int nWords ) +{ + //assert( !Abc_TtIntersectOne(pOff, 0, pDivA, ComplA, nWords) ); + //assert( !Abc_TtIntersectOne(pOff, 0, pDivB, ComplB, nWords) ); + return !Abc_TtIntersectTwo( pOn, 0, pDivA, !ComplA, pDivB, !ComplB, nWords ); +} +int Gia_ManFindTwoUnateInt( word * pOff, word * pOn, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits, Vec_Int_t * vUnateLitsW, int * pnPairs ) +{ + int i, k, iDiv0_, iDiv1_, Cover0, Cover1; + int nTotal = Abc_TtCountOnesVec( pOn, nWords ); + (*pnPairs) = 0; + Vec_IntForEachEntryTwo( vUnateLits, vUnateLitsW, iDiv0_, Cover0, i ) + { + if ( 2*Cover0 < nTotal ) + break; + Vec_IntForEachEntryTwoStart( vUnateLits, vUnateLitsW, iDiv1_, Cover1, k, i+1 ) + { + int iDiv0 = Abc_MinInt( iDiv0_, iDiv1_ ); + int iDiv1 = Abc_MaxInt( iDiv0_, iDiv1_ ); + word * pDiv0 = (word *)Vec_PtrEntry(vDivs, Abc_Lit2Var(iDiv0)); + word * pDiv1 = (word *)Vec_PtrEntry(vDivs, Abc_Lit2Var(iDiv1)); + if ( Cover0 + Cover1 < nTotal ) + break; + (*pnPairs)++; + if ( Gia_ManDivCover(pOff, pOn, pDiv1, Abc_LitIsCompl(iDiv1), pDiv0, Abc_LitIsCompl(iDiv0), nWords) ) + return Abc_Var2Lit((Abc_LitNot(iDiv1) << 15) | Abc_LitNot(iDiv0), 1); + } + } + return -1; +} +int Gia_ManFindTwoUnate( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits[2], Vec_Int_t * vUnateLitsW[2], int fVerbose ) +{ + int n, iLit, nPairs; + if ( fVerbose ) printf( " " ); + for ( n = 0; n < 2; n++ ) + { + //int nPairsAll = Vec_IntSize(vUnateLits[n])*(Vec_IntSize(vUnateLits[n])-1)/2; + iLit = Gia_ManFindTwoUnateInt( pSets[n], pSets[!n], vDivs, nWords, vUnateLits[n], vUnateLitsW[n], &nPairs ); + if ( fVerbose ) printf( "UU%d =%5d ", n, nPairs ); + if ( iLit >= 0 ) + return Abc_LitNotCond(iLit, n); + } + return -1; +} + +void Gia_ManFindXorInt( word * pOff, word * pOn, Vec_Int_t * vBinate, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnatePairs ) +{ + int i, k, iDiv0_, iDiv1_; + int Limit2 = Vec_IntSize(vBinate);//Abc_MinInt( Vec_IntSize(vBinate), 100 ); + Vec_IntForEachEntryStop( vBinate, iDiv1_, i, Limit2 ) + Vec_IntForEachEntryStop( vBinate, iDiv0_, k, i ) + { + int iDiv0 = Abc_MinInt( iDiv0_, iDiv1_ ); + int iDiv1 = Abc_MaxInt( iDiv0_, iDiv1_ ); + word * pDiv0 = (word *)Vec_PtrEntry(vDivs, iDiv0); + word * pDiv1 = (word *)Vec_PtrEntry(vDivs, iDiv1); + if ( !Abc_TtIntersectXor( pOff, 0, pDiv0, pDiv1, 0, nWords ) ) + Vec_IntPush( vUnatePairs, Abc_Var2Lit((Abc_Var2Lit(iDiv0, 0) << 15) | Abc_Var2Lit(iDiv1, 0), 0) ); + else if ( !Abc_TtIntersectXor( pOff, 0, pDiv0, pDiv1, 1, nWords ) ) + Vec_IntPush( vUnatePairs, Abc_Var2Lit((Abc_Var2Lit(iDiv0, 0) << 15) | Abc_Var2Lit(iDiv1, 0), 1) ); + } +} +int Gia_ManFindXor( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vBinateVars, Vec_Int_t * vUnatePairs[2], int fVerbose ) +{ + int n; + if ( fVerbose ) printf( " " ); + for ( n = 0; n < 2; n++ ) + { + Vec_IntClear( vUnatePairs[n] ); + Gia_ManFindXorInt( pSets[n], pSets[!n], vBinateVars, vDivs, nWords, vUnatePairs[n] ); + if ( fVerbose ) printf( "UX%d =%5d ", n, Vec_IntSize(vUnatePairs[n]) ); + } + return Gia_ManFindFirstCommonLit( vUnatePairs[0], vUnatePairs[1], fVerbose ); +} + +void Gia_ManFindUnatePairsInt( word * pOff, word * pOn, Vec_Int_t * vBinate, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnatePairs ) +{ + int n, i, k, iDiv0_, iDiv1_; + int Limit2 = Vec_IntSize(vBinate);//Abc_MinInt( Vec_IntSize(vBinate), 100 ); + Vec_IntForEachEntryStop( vBinate, iDiv1_, i, Limit2 ) + Vec_IntForEachEntryStop( vBinate, iDiv0_, k, i ) + { + int iDiv0 = Abc_MinInt( iDiv0_, iDiv1_ ); + int iDiv1 = Abc_MaxInt( iDiv0_, iDiv1_ ); + word * pDiv0 = (word *)Vec_PtrEntry(vDivs, iDiv0); + word * pDiv1 = (word *)Vec_PtrEntry(vDivs, iDiv1); + for ( n = 0; n < 4; n++ ) + { + int iLit0 = Abc_Var2Lit( iDiv0, n&1 ); + int iLit1 = Abc_Var2Lit( iDiv1, n>>1 ); + //if ( !Abc_TtIntersectTwo( pOff, 0, pDiv1, n>>1, pDiv0, n&1, nWords ) ) + if ( !Abc_TtIntersectTwo( pOff, 0, pDiv1, n>>1, pDiv0, n&1, nWords ) && Abc_TtIntersectTwo( pOn, 0, pDiv1, n>>1, pDiv0, n&1, nWords ) ) + Vec_IntPush( vUnatePairs, Abc_Var2Lit((iLit1 << 15) | iLit0, 0) ); + } + } +} +void Gia_ManFindUnatePairs( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vBinateVars, Vec_Int_t * vUnatePairs[2], int fVerbose ) +{ + int n, RetValue; + if ( fVerbose ) printf( " " ); + for ( n = 0; n < 2; n++ ) + { + int nBefore = Vec_IntSize(vUnatePairs[n]); + Gia_ManFindUnatePairsInt( pSets[n], pSets[!n], vBinateVars, vDivs, nWords, vUnatePairs[n] ); + if ( fVerbose ) printf( "UP%d =%5d ", n, Vec_IntSize(vUnatePairs[n])-nBefore ); + } + RetValue = Gia_ManFindFirstCommonLit( vUnatePairs[0], vUnatePairs[1], fVerbose ); + assert( RetValue == -1 ); +} + +void Gia_ManDeriveDivPair( int iDiv, Vec_Ptr_t * vDivs, int nWords, word * pRes ) +{ + int fComp = Abc_LitIsCompl(iDiv); + int iDiv0 = Abc_Lit2Var(iDiv) & 0x7FFF; + int iDiv1 = Abc_Lit2Var(iDiv) >> 15; + word * pDiv0 = (word *)Vec_PtrEntry(vDivs, Abc_Lit2Var(iDiv0)); + word * pDiv1 = (word *)Vec_PtrEntry(vDivs, Abc_Lit2Var(iDiv1)); + if ( iDiv0 < iDiv1 ) + { + assert( !fComp ); + Abc_TtAndCompl( pRes, pDiv0, Abc_LitIsCompl(iDiv0), pDiv1, Abc_LitIsCompl(iDiv1), nWords ); + } + else + { + assert( !Abc_LitIsCompl(iDiv0) ); + assert( !Abc_LitIsCompl(iDiv1) ); + Abc_TtXor( pRes, pDiv0, pDiv1, nWords, 0 ); + } +} +int Gia_ManFindDivGateInt( word * pOff, word * pOn, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits, Vec_Int_t * vUnatePairs, Vec_Int_t * vUnateLitsW, Vec_Int_t * vUnatePairsW, word * pDivTemp ) +{ + int i, k, iDiv0, iDiv1, Cover0, Cover1; + int nTotal = Abc_TtCountOnesVec( pOn, nWords ); + Vec_IntForEachEntryTwo( vUnateLits, vUnateLitsW, iDiv0, Cover0, i ) + { + word * pDiv0 = (word *)Vec_PtrEntry(vDivs, Abc_Lit2Var(iDiv0)); + if ( 2*Cover0 < nTotal ) + break; + Vec_IntForEachEntryTwo( vUnatePairs, vUnatePairsW, iDiv1, Cover1, k ) + { + int fComp1 = Abc_LitIsCompl(iDiv1); + if ( Cover0 + Cover1 < nTotal ) + break; + Gia_ManDeriveDivPair( iDiv1, vDivs, nWords, pDivTemp ); + if ( Gia_ManDivCover(pOff, pOn, pDiv0, Abc_LitIsCompl(iDiv0), pDivTemp, fComp1, nWords) ) + return Abc_Var2Lit((Abc_Var2Lit(k, 1) << 15) | Abc_LitNot(iDiv0), 1); + } + } + return -1; +} +int Gia_ManFindDivGate( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits[2], Vec_Int_t * vUnatePairs[2], Vec_Int_t * vUnateLitsW[2], Vec_Int_t * vUnatePairsW[2], word * pDivTemp ) +{ + int n, iLit; + for ( n = 0; n < 2; n++ ) + { + iLit = Gia_ManFindDivGateInt( pSets[n], pSets[!n], vDivs, nWords, vUnateLits[n], vUnatePairs[n], vUnateLitsW[n], vUnatePairsW[n], pDivTemp ); + if ( iLit >= 0 ) + return Abc_LitNotCond( iLit, n ); + } + return -1; +} + +int Gia_ManFindGateGateInt( word * pOff, word * pOn, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnatePairs, Vec_Int_t * vUnatePairsW, word * pDivTempA, word * pDivTempB ) +{ + int i, k, iDiv0, iDiv1, Cover0, Cover1; + int nTotal = Abc_TtCountOnesVec( pOn, nWords ); + Vec_IntForEachEntryTwo( vUnatePairs, vUnatePairsW, iDiv0, Cover0, k ) + { + int fCompA = Abc_LitIsCompl(iDiv0); + if ( 2*Cover0 < nTotal ) + break; + Gia_ManDeriveDivPair( iDiv0, vDivs, nWords, pDivTempA ); + Vec_IntForEachEntryTwoStart( vUnatePairs, vUnatePairsW, iDiv1, Cover1, i, k+1 ) + { + int fCompB = Abc_LitIsCompl(iDiv1); + if ( Cover0 + Cover1 < nTotal ) + break; + Gia_ManDeriveDivPair( iDiv1, vDivs, nWords, pDivTempB ); + if ( Gia_ManDivCover(pOff, pOn, pDivTempA, fCompA, pDivTempB, fCompB, nWords) ) + return Abc_Var2Lit((Abc_Var2Lit(i, 1) << 15) | Abc_Var2Lit(k, 1), 1); + } + } + return -1; +} +int Gia_ManFindGateGate( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnatePairs[2], Vec_Int_t * vUnatePairsW[2], word * pDivTempA, word * pDivTempB ) +{ + int n, iLit; + for ( n = 0; n < 2; n++ ) + { + iLit = Gia_ManFindGateGateInt( pSets[n], pSets[!n], vDivs, nWords, vUnatePairs[n], vUnatePairsW[n], pDivTempA, pDivTempB ); + if ( iLit >= 0 ) + return Abc_LitNotCond( iLit, n ); + } + return -1; +} + +void Gia_ManSortUnatesInt( word * pOff, word * pOn, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits, Vec_Int_t * vUnateLitsW, Vec_Wec_t * vSorter ) +{ + int i, k, iLit; + Vec_Int_t * vLevel; + Vec_WecInit( vSorter, nWords*64 ); + Vec_IntForEachEntry( vUnateLits, iLit, i ) + { + word * pDiv = (word *)Vec_PtrEntry(vDivs, Abc_Lit2Var(iLit)); + //assert( !Abc_TtIntersectOne( pOff, 0, pDiv, Abc_LitIsCompl(iLit), nWords ) ); + Vec_WecPush( vSorter, Abc_TtCountOnesVecMask(pDiv, pOn, nWords, Abc_LitIsCompl(iLit)), iLit ); + } + Vec_IntClear( vUnateLits ); + Vec_IntClear( vUnateLitsW ); + Vec_WecForEachLevelReverse( vSorter, vLevel, k ) + Vec_IntForEachEntry( vLevel, iLit, i ) + { + Vec_IntPush( vUnateLits, iLit ); + Vec_IntPush( vUnateLitsW, k ); + } + //Vec_IntPrint( Vec_WecEntry(vSorter, 0) ); + Vec_WecClear( vSorter ); +} +void Gia_ManSortUnates( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits[2], Vec_Int_t * vUnateLitsW[2], Vec_Wec_t * vSorter ) +{ + int n; + for ( n = 0; n < 2; n++ ) + Gia_ManSortUnatesInt( pSets[n], pSets[!n], vDivs, nWords, vUnateLits[n], vUnateLitsW[n], vSorter ); +} + +void Gia_ManSortPairsInt( word * pOff, word * pOn, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnatePairs, Vec_Int_t * vUnatePairsW, Vec_Wec_t * vSorter ) +{ + int i, k, iPair; + Vec_Int_t * vLevel; + Vec_WecInit( vSorter, nWords*64 ); + Vec_IntForEachEntry( vUnatePairs, iPair, i ) + { + int fComp = Abc_LitIsCompl(iPair); + int iLit0 = Abc_Lit2Var(iPair) & 0x7FFF; + int iLit1 = Abc_Lit2Var(iPair) >> 15; + word * pDiv0 = (word *)Vec_PtrEntry( vDivs, Abc_Lit2Var(iLit0) ); + word * pDiv1 = (word *)Vec_PtrEntry( vDivs, Abc_Lit2Var(iLit1) ); + if ( iLit0 < iLit1 ) + { + assert( !fComp ); + //assert( !Abc_TtIntersectTwo( pOff, 0, pDiv0, Abc_LitIsCompl(iLit0), pDiv1, Abc_LitIsCompl(iLit1), nWords ) ); + Vec_WecPush( vSorter, Abc_TtCountOnesVecMask2(pDiv0, pDiv1, Abc_LitIsCompl(iLit0), Abc_LitIsCompl(iLit1), pOn, nWords), iPair ); + } + else + { + assert( !Abc_LitIsCompl(iLit0) ); + assert( !Abc_LitIsCompl(iLit1) ); + //assert( !Abc_TtIntersectXor( pOff, 0, pDiv0, pDiv1, fComp, nWords ) ); + Vec_WecPush( vSorter, Abc_TtCountOnesVecXorMask(pDiv0, pDiv1, fComp, pOn, nWords), iPair ); + } + } + Vec_IntClear( vUnatePairs ); + Vec_IntClear( vUnatePairsW ); + Vec_WecForEachLevelReverse( vSorter, vLevel, k ) + Vec_IntForEachEntry( vLevel, iPair, i ) + { + Vec_IntPush( vUnatePairs, iPair ); + Vec_IntPush( vUnatePairsW, k ); + } + //Vec_IntPrint( Vec_WecEntry(vSorter, 0) ); + Vec_WecClear( vSorter ); + +} +void Gia_ManSortPairs( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits[2], Vec_Int_t * vUnateLitsW[2], Vec_Wec_t * vSorter ) +{ + int n; + for ( n = 0; n < 2; n++ ) + Gia_ManSortPairsInt( pSets[n], pSets[!n], vDivs, nWords, vUnateLits[n], vUnateLitsW[n], vSorter ); +} + +void Gia_ManSortBinate( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vBinateVars, Vec_Wec_t * vSorter ) +{ + Vec_Int_t * vLevel; + int nMints[2] = { Abc_TtCountOnesVec(pSets[0], nWords), Abc_TtCountOnesVec(pSets[1], nWords) }; + word * pBig = nMints[0] > nMints[1] ? pSets[0] : pSets[1]; + word * pSmo = nMints[0] > nMints[1] ? pSets[1] : pSets[0]; + int Big = Abc_MaxInt( nMints[0], nMints[1] ); + int Smo = Abc_MinInt( nMints[0], nMints[1] ); + int i, k, iDiv, Gain; + + Vec_WecInit( vSorter, nWords*64 ); + Vec_IntForEachEntry( vBinateVars, iDiv, i ) + { + word * pDiv = (word *)Vec_PtrEntry( vDivs, iDiv ); + int nInter[2] = { Abc_TtCountOnesVecMask(pBig, pDiv, nWords, 0), Abc_TtCountOnesVecMask(pSmo, pDiv, nWords, 0) }; + if ( nInter[0] < Big/2 ) // complement the divisor + { + nInter[0] = Big - nInter[0]; + nInter[1] = Smo - nInter[1]; + } + assert( nInter[0] >= Big/2 ); + Gain = Abc_MaxInt( 0, nInter[0] - Big/2 + Smo/2 - nInter[1] ); + Vec_WecPush( vSorter, Gain, iDiv ); + } + + Vec_IntClear( vBinateVars ); + Vec_WecForEachLevelReverse( vSorter, vLevel, k ) + Vec_IntForEachEntry( vLevel, iDiv, i ) + Vec_IntPush( vBinateVars, iDiv ); + Vec_WecClear( vSorter ); + + if ( Vec_IntSize(vBinateVars) > 2000 ) + Vec_IntShrink( vBinateVars, 2000 ); +} + +/**Function************************************************************* + + Synopsis [Perform resubstitution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManResubFindBestBinate( Gia_ResbMan_t * p ) +{ + int nMintsAll = Abc_TtCountOnesVec(p->pSets[0], p->nWords) + Abc_TtCountOnesVec(p->pSets[1], p->nWords); + int i, iDiv, iLitBest = -1, CostBest = -1; +//Vec_IntPrint( p->vBinateVars ); +//Dau_DsdPrintFromTruth( p->pSets[0], 6 ); +//Dau_DsdPrintFromTruth( p->pSets[1], 6 ); + Vec_IntForEachEntry( p->vBinateVars, iDiv, i ) + { + word * pDiv = (word *)Vec_PtrEntry(p->vDivs, iDiv); + int nMints0 = Abc_TtCountOnesVecMask( pDiv, p->pSets[0], p->nWords, 0 ); + int nMints1 = Abc_TtCountOnesVecMask( pDiv, p->pSets[1], p->nWords, 0 ); + if ( CostBest < nMints0 + nMints1 ) + { + CostBest = nMints0 + nMints1; + iLitBest = Abc_Var2Lit( iDiv, 0 ); + } + if ( CostBest < nMintsAll - nMints0 - nMints1 ) + { + CostBest = nMintsAll - nMints0 - nMints1; + iLitBest = Abc_Var2Lit( iDiv, 1 ); + } + } + return iLitBest; +} +int Gia_ManResubAddNode( Gia_ResbMan_t * p, int iLit0, int iLit1, int Type ) +{ + int iNode = Vec_PtrSize(p->vDivs) + Vec_IntSize(p->vGates)/2; + int fFlip = (Type == 2) ^ (iLit0 > iLit1); + int iFan0 = fFlip ? iLit1 : iLit0; + int iFan1 = fFlip ? iLit0 : iLit1; + assert( iLit0 != iLit1 ); + if ( Type == 2 ) + assert( iFan0 > iFan1 ); + else + assert( iFan0 < iFan1 ); + Vec_IntPushTwo( p->vGates, Abc_LitNotCond(iFan0, Type==1), Abc_LitNotCond(iFan1, Type==1) ); + return Abc_Var2Lit( iNode, Type==1 ); +} +int Gia_ManResubPerformMux_rec( Gia_ResbMan_t * p, int nLimit, int Depth ) +{ + extern int Gia_ManResubPerform_rec( Gia_ResbMan_t * p, int nLimit, int Depth ); + int iDivBest, iResLit0, iResLit1, nNodes; + word * pDiv, * pCopy[2]; + if ( Depth == 0 ) + return -1; + if ( nLimit < 3 ) + return -1; + iDivBest = Gia_ManResubFindBestBinate( p ); + if ( iDivBest == -1 ) + return -1; + pCopy[0] = ABC_CALLOC( word, p->nWords ); + pCopy[1] = ABC_CALLOC( word, p->nWords ); + Abc_TtCopy( pCopy[0], p->pSets[0], p->nWords, 0 ); + Abc_TtCopy( pCopy[1], p->pSets[1], p->nWords, 0 ); + pDiv = (word *)Vec_PtrEntry( p->vDivs, Abc_Lit2Var(iDivBest) ); + Abc_TtAndSharp( p->pSets[0], pCopy[0], pDiv, p->nWords, !Abc_LitIsCompl(iDivBest) ); + Abc_TtAndSharp( p->pSets[1], pCopy[1], pDiv, p->nWords, !Abc_LitIsCompl(iDivBest) ); + nNodes = Vec_IntSize(p->vGates)/2; + //iResLit0 = Gia_ManResubPerform_rec( p, nLimit-3 ); + iResLit0 = Gia_ManResubPerform_rec( p, nLimit, 0 ); + if ( iResLit0 == -1 ) + iResLit0 = Gia_ManResubPerformMux_rec( p, nLimit, Depth-1 ); + if ( iResLit0 == -1 ) + { + ABC_FREE( pCopy[0] ); + ABC_FREE( pCopy[1] ); + return -1; + } + Abc_TtAndSharp( p->pSets[0], pCopy[0], pDiv, p->nWords, Abc_LitIsCompl(iDivBest) ); + Abc_TtAndSharp( p->pSets[1], pCopy[1], pDiv, p->nWords, Abc_LitIsCompl(iDivBest) ); + ABC_FREE( pCopy[0] ); + ABC_FREE( pCopy[1] ); + nNodes = Vec_IntSize(p->vGates)/2 - nNodes; + if ( nLimit-nNodes < 3 ) + return -1; + //iResLit1 = Gia_ManResubPerform_rec( p, nLimit-3-nNodes ); + iResLit1 = Gia_ManResubPerform_rec( p, nLimit, 0 ); + if ( iResLit1 == -1 ) + iResLit1 = Gia_ManResubPerformMux_rec( p, nLimit, Depth-1 ); + if ( iResLit1 == -1 ) + return -1; + else + { + int iLit0 = Gia_ManResubAddNode( p, Abc_LitNot(iDivBest), iResLit0, 0 ); + int iLit1 = Gia_ManResubAddNode( p, iDivBest, iResLit1, 0 ); + return Gia_ManResubAddNode( p, iLit0, iLit1, 1 ); + } +} + +/**Function************************************************************* + + Synopsis [Perform resubstitution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManResubPerform_rec( Gia_ResbMan_t * p, int nLimit, int Depth ) +{ + int TopOneW[2] = {0}, TopTwoW[2] = {0}, Max1, Max2, iResLit, nVars = Vec_PtrSize(p->vDivs); + if ( p->fVerbose ) + { + int nMints[2] = { Abc_TtCountOnesVec(p->pSets[0], p->nWords), Abc_TtCountOnesVec(p->pSets[1], p->nWords) }; + printf( " " ); + printf( "ISF: " ); + printf( "0=%5d (%5.2f %%) ", nMints[0], 100.0*nMints[0]/(64*p->nWords) ); + printf( "1=%5d (%5.2f %%) ", nMints[1], 100.0*nMints[1]/(64*p->nWords) ); + } + if ( Abc_TtIsConst0( p->pSets[1], p->nWords ) ) + return 0; + if ( Abc_TtIsConst0( p->pSets[0], p->nWords ) ) + return 1; + iResLit = Gia_ManFindOneUnate( p->pSets, p->vDivs, p->nWords, p->vUnateLits, p->vNotUnateVars, p->fVerbose ); + if ( iResLit >= 0 ) // buffer + return iResLit; + if ( nLimit == 0 ) + return -1; + Gia_ManSortUnates( p->pSets, p->vDivs, p->nWords, p->vUnateLits, p->vUnateLitsW, p->vSorter ); + iResLit = Gia_ManFindTwoUnate( p->pSets, p->vDivs, p->nWords, p->vUnateLits, p->vUnateLitsW, p->fVerbose ); + if ( iResLit >= 0 ) // and + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + int fComp = Abc_LitIsCompl(iResLit); + int iDiv0 = Abc_Lit2Var(iResLit) & 0x7FFF; + int iDiv1 = Abc_Lit2Var(iResLit) >> 15; + assert( iDiv0 < iDiv1 ); + Vec_IntPushTwo( p->vGates, iDiv0, iDiv1 ); + return Abc_Var2Lit( iNode, fComp ); + } + Vec_IntTwoFindCommon( p->vNotUnateVars[0], p->vNotUnateVars[1], p->vBinateVars ); + if ( Depth ) + return Gia_ManResubPerformMux_rec( p, nLimit, Depth ); + if ( Vec_IntSize(p->vBinateVars) > p->nDivsMax ) + Vec_IntShrink( p->vBinateVars, p->nDivsMax ); + if ( p->fVerbose ) printf( " B = %3d", Vec_IntSize(p->vBinateVars) ); + //Gia_ManSortBinate( p->pSets, p->vDivs, p->nWords, p->vBinateVars, p->vSorter ); + if ( p->fUseXor ) + { + iResLit = Gia_ManFindXor( p->pSets, p->vDivs, p->nWords, p->vBinateVars, p->vUnatePairs, p->fVerbose ); + if ( iResLit >= 0 ) // xor + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + int fComp = Abc_LitIsCompl(iResLit); + int iDiv0 = Abc_Lit2Var(iResLit) & 0x7FFF; + int iDiv1 = Abc_Lit2Var(iResLit) >> 15; + assert( !Abc_LitIsCompl(iDiv0) ); + assert( !Abc_LitIsCompl(iDiv1) ); + assert( iDiv0 > iDiv1 ); + Vec_IntPushTwo( p->vGates, iDiv0, iDiv1 ); + return Abc_Var2Lit( iNode, fComp ); + } + } + if ( nLimit == 1 ) + return -1; + Gia_ManFindUnatePairs( p->pSets, p->vDivs, p->nWords, p->vBinateVars, p->vUnatePairs, p->fVerbose ); + Gia_ManSortPairs( p->pSets, p->vDivs, p->nWords, p->vUnatePairs, p->vUnatePairsW, p->vSorter ); + iResLit = Gia_ManFindDivGate( p->pSets, p->vDivs, p->nWords, p->vUnateLits, p->vUnatePairs, p->vUnateLitsW, p->vUnatePairsW, p->pDivA ); + if ( iResLit >= 0 ) // and(div,pair) + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + + int fComp = Abc_LitIsCompl(iResLit); + int iDiv0 = Abc_Lit2Var(iResLit) & 0x7FFF; // div + int iDiv1 = Abc_Lit2Var(iResLit) >> 15; // pair + + int Div1 = Vec_IntEntry( p->vUnatePairs[!fComp], Abc_Lit2Var(iDiv1) ); + int fComp1 = Abc_LitIsCompl(Div1) ^ Abc_LitIsCompl(iDiv1); + int iDiv10 = Abc_Lit2Var(Div1) & 0x7FFF; + int iDiv11 = Abc_Lit2Var(Div1) >> 15; + + Vec_IntPushTwo( p->vGates, iDiv10, iDiv11 ); + Vec_IntPushTwo( p->vGates, iDiv0, Abc_Var2Lit(iNode, fComp1) ); + return Abc_Var2Lit( iNode+1, fComp ); + } +// if ( nLimit == 2 ) +// return -1; + if ( nLimit >= 3 ) + { + iResLit = Gia_ManFindGateGate( p->pSets, p->vDivs, p->nWords, p->vUnatePairs, p->vUnatePairsW, p->pDivA, p->pDivB ); + if ( iResLit >= 0 ) // and(pair,pair) + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + + int fComp = Abc_LitIsCompl(iResLit); + int iDiv0 = Abc_Lit2Var(iResLit) & 0x7FFF; // pair + int iDiv1 = Abc_Lit2Var(iResLit) >> 15; // pair + + int Div0 = Vec_IntEntry( p->vUnatePairs[!fComp], Abc_Lit2Var(iDiv0) ); + int fComp0 = Abc_LitIsCompl(Div0) ^ Abc_LitIsCompl(iDiv0); + int iDiv00 = Abc_Lit2Var(Div0) & 0x7FFF; + int iDiv01 = Abc_Lit2Var(Div0) >> 15; + + int Div1 = Vec_IntEntry( p->vUnatePairs[!fComp], Abc_Lit2Var(iDiv1) ); + int fComp1 = Abc_LitIsCompl(Div1) ^ Abc_LitIsCompl(iDiv1); + int iDiv10 = Abc_Lit2Var(Div1) & 0x7FFF; + int iDiv11 = Abc_Lit2Var(Div1) >> 15; + + Vec_IntPushTwo( p->vGates, iDiv00, iDiv01 ); + Vec_IntPushTwo( p->vGates, iDiv10, iDiv11 ); + Vec_IntPushTwo( p->vGates, Abc_Var2Lit(iNode, fComp0), Abc_Var2Lit(iNode+1, fComp1) ); + return Abc_Var2Lit( iNode+2, fComp ); + } + } +// if ( nLimit == 3 ) +// return -1; + if ( Vec_IntSize(p->vUnateLits[0]) + Vec_IntSize(p->vUnateLits[1]) + Vec_IntSize(p->vUnatePairs[0]) + Vec_IntSize(p->vUnatePairs[1]) == 0 ) + return -1; + + TopOneW[0] = Vec_IntSize(p->vUnateLitsW[0]) ? Vec_IntEntry(p->vUnateLitsW[0], 0) : 0; + TopOneW[1] = Vec_IntSize(p->vUnateLitsW[1]) ? Vec_IntEntry(p->vUnateLitsW[1], 0) : 0; + + TopTwoW[0] = Vec_IntSize(p->vUnatePairsW[0]) ? Vec_IntEntry(p->vUnatePairsW[0], 0) : 0; + TopTwoW[1] = Vec_IntSize(p->vUnatePairsW[1]) ? Vec_IntEntry(p->vUnatePairsW[1], 0) : 0; + + Max1 = Abc_MaxInt(TopOneW[0], TopOneW[1]); + Max2 = Abc_MaxInt(TopTwoW[0], TopTwoW[1]); + if ( Abc_MaxInt(Max1, Max2) == 0 ) + return -1; + + if ( Max1 > Max2/2 ) + { + if ( nLimit >= 2 && (Max1 == TopOneW[0] || Max1 == TopOneW[1]) ) + { + int fUseOr = Max1 == TopOneW[0]; + int iDiv = Vec_IntEntry( p->vUnateLits[!fUseOr], 0 ); + int fComp = Abc_LitIsCompl(iDiv); + word * pDiv = (word *)Vec_PtrEntry( p->vDivs, Abc_Lit2Var(iDiv) ); + Abc_TtAndSharp( p->pSets[fUseOr], p->pSets[fUseOr], pDiv, p->nWords, !fComp ); + if ( p->fVerbose ) + printf( "\n" ); + iResLit = Gia_ManResubPerform_rec( p, nLimit-1, Depth ); + if ( iResLit >= 0 ) + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + if ( iDiv < iResLit ) + Vec_IntPushTwo( p->vGates, Abc_LitNot(iDiv), Abc_LitNotCond(iResLit, fUseOr) ); + else + Vec_IntPushTwo( p->vGates, Abc_LitNotCond(iResLit, fUseOr), Abc_LitNot(iDiv) ); + return Abc_Var2Lit( iNode, fUseOr ); + } + } + if ( Max2 == 0 ) + return -1; +/* + if ( Max2 == TopTwoW[0] || Max2 == TopTwoW[1] ) + { + int fUseOr = Max2 == TopTwoW[0]; + int iDiv = Vec_IntEntry( p->vUnatePairs[!fUseOr], 0 ); + int fComp = Abc_LitIsCompl(iDiv); + Gia_ManDeriveDivPair( iDiv, p->vDivs, p->nWords, p->pDivA ); + Abc_TtAndSharp( p->pSets[fUseOr], p->pSets[fUseOr], p->pDivA, p->nWords, !fComp ); + if ( p->fVerbose ) + printf( "\n " ); + iResLit = Gia_ManResubPerform_rec( p, nLimit-2 ); + if ( iResLit >= 0 ) + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + int iDiv0 = Abc_Lit2Var(iDiv) & 0x7FFF; + int iDiv1 = Abc_Lit2Var(iDiv) >> 15; + Vec_IntPushTwo( p->vGates, iDiv0, iDiv1 ); + Vec_IntPushTwo( p->vGates, Abc_LitNotCond(iResLit, fUseOr), Abc_Var2Lit(iNode, !fComp) ); + return Abc_Var2Lit( iNode+1, fUseOr ); + } + } +*/ + } + else + { + if ( nLimit >= 3 && (Max2 == TopTwoW[0] || Max2 == TopTwoW[1]) ) + { + int fUseOr = Max2 == TopTwoW[0]; + int iDiv = Vec_IntEntry( p->vUnatePairs[!fUseOr], 0 ); + int fComp = Abc_LitIsCompl(iDiv); + Gia_ManDeriveDivPair( iDiv, p->vDivs, p->nWords, p->pDivA ); + Abc_TtAndSharp( p->pSets[fUseOr], p->pSets[fUseOr], p->pDivA, p->nWords, !fComp ); + if ( p->fVerbose ) + printf( "\n" ); + iResLit = Gia_ManResubPerform_rec( p, nLimit-2, Depth ); + if ( iResLit >= 0 ) + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + int iDiv0 = Abc_Lit2Var(iDiv) & 0x7FFF; + int iDiv1 = Abc_Lit2Var(iDiv) >> 15; + Vec_IntPushTwo( p->vGates, iDiv0, iDiv1 ); + Vec_IntPushTwo( p->vGates, Abc_LitNotCond(iResLit, fUseOr), Abc_Var2Lit(iNode, !fComp) ); + return Abc_Var2Lit( iNode+1, fUseOr ); + } + } + if ( Max1 == 0 ) + return -1; +/* + if ( Max1 == TopOneW[0] || Max1 == TopOneW[1] ) + { + int fUseOr = Max1 == TopOneW[0]; + int iDiv = Vec_IntEntry( p->vUnateLits[!fUseOr], 0 ); + int fComp = Abc_LitIsCompl(iDiv); + word * pDiv = (word *)Vec_PtrEntry( p->vDivs, Abc_Lit2Var(iDiv) ); + Abc_TtAndSharp( p->pSets[fUseOr], p->pSets[fUseOr], pDiv, p->nWords, !fComp ); + if ( p->fVerbose ) + printf( "\n " ); + iResLit = Gia_ManResubPerform_rec( p, nLimit-1 ); + if ( iResLit >= 0 ) + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + Vec_IntPushTwo( p->vGates, Abc_LitNot(iDiv), Abc_LitNotCond(iResLit, fUseOr) ); + return Abc_Var2Lit( iNode, fUseOr ); + } + } +*/ + } + return -1; +} +void Gia_ManResubPerform( Gia_ResbMan_t * p, Vec_Ptr_t * vDivs, int nWords, int nLimit, int nDivsMax, int iChoice, int fUseXor, int fDebug, int fVerbose, int Depth ) +{ + int Res; + Gia_ResbInit( p, vDivs, nWords, nLimit, nDivsMax, iChoice, fUseXor, fDebug, fVerbose, fVerbose ); + Res = Gia_ManResubPerform_rec( p, nLimit, Depth ); + if ( Res >= 0 ) + Vec_IntPush( p->vGates, Res ); + else + Vec_IntClear( p->vGates ); + if ( fVerbose ) + printf( "\n" ); +} +Vec_Int_t * Gia_ManResubOne( Vec_Ptr_t * vDivs, int nWords, int nLimit, int nDivsMax, int iChoice, int fUseXor, int fDebug, int fVerbose, word * pFunc, int Depth ) +{ + Vec_Int_t * vRes; + Gia_ResbMan_t * p = Gia_ResbAlloc( nWords ); + Gia_ManResubPerform( p, vDivs, nWords, nLimit, nDivsMax, iChoice, fUseXor, fDebug, fVerbose, Depth ); + if ( fVerbose ) + Gia_ManResubPrint( p->vGates, Vec_PtrSize(vDivs) ); + //if ( fVerbose ) + // printf( "\n" ); + if ( !Gia_ManResubVerify(p, pFunc) ) + { + Gia_ManResubPrint( p->vGates, Vec_PtrSize(vDivs) ); + printf( "Verification FAILED.\n" ); + } + else if ( fDebug && fVerbose ) + printf( "Verification succeeded." ); + if ( fVerbose ) + printf( "\n" ); + vRes = Vec_IntDup( p->vGates ); + Gia_ResbFree( p ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [Top level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Gia_ResbMan_t * s_pResbMan = NULL; + +void Abc_ResubPrepareManager( int nWords ) +{ + if ( s_pResbMan != NULL ) + Gia_ResbFree( s_pResbMan ); + s_pResbMan = NULL; + if ( nWords > 0 ) + s_pResbMan = Gia_ResbAlloc( nWords ); +} + +int Abc_ResubComputeFunction( void ** ppDivs, int nDivs, int nWords, int nLimit, int nDivsMax, int iChoice, int fUseXor, int fDebug, int fVerbose, int ** ppArray ) +{ + Vec_Ptr_t Divs = { nDivs, nDivs, ppDivs }; + assert( s_pResbMan != NULL ); // first call Abc_ResubPrepareManager() + Gia_ManResubPerform( s_pResbMan, &Divs, nWords, nLimit, nDivsMax, iChoice, fUseXor, fDebug, fVerbose==2, 0 ); + if ( fVerbose ) + { + int nGates = Vec_IntSize(s_pResbMan->vGates)/2; + if ( nGates ) + { + printf( " Gain = %2d Gates = %2d __________ F = ", nLimit+1-nGates, nGates ); + Gia_ManResubPrint( s_pResbMan->vGates, nDivs ); + printf( "\n" ); + } + } + if ( fDebug ) + { + if ( !Gia_ManResubVerify(s_pResbMan, NULL) ) + { + Gia_ManResubPrint( s_pResbMan->vGates, nDivs ); + printf( "Verification FAILED.\n" ); + } + //else + // printf( "Verification succeeded.\n" ); + } + *ppArray = Vec_IntArray(s_pResbMan->vGates); + assert( Vec_IntSize(s_pResbMan->vGates)/2 <= nLimit ); + return Vec_IntSize(s_pResbMan->vGates); +} + +void Abc_ResubDumpProblem( char * pFileName, void ** ppDivs, int nDivs, int nWords ) +{ + Vec_Wrd_t * vSims = Vec_WrdAlloc( nDivs * nWords ); + word ** pDivs = (word **)ppDivs; + int d, w; + for ( d = 0; d < nDivs; d++ ) + for ( w = 0; w < nWords; w++ ) + Vec_WrdPush( vSims, pDivs[d][w] ); + Vec_WrdDumpHex( pFileName, vSims, nWords, 1 ); + Vec_WrdFree( vSims ); +} + +/**Function************************************************************* + + Synopsis [Top level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +extern void Extra_PrintHex( FILE * pFile, unsigned * pTruth, int nVars ); +extern void Dau_DsdPrintFromTruth2( word * pTruth, int nVarsInit ); + +void Gia_ManResubTest3() +{ + int nVars = 4; + int fVerbose = 1; + word Divs[6] = { 0, 0, + ABC_CONST(0xAAAAAAAAAAAAAAAA), + ABC_CONST(0xCCCCCCCCCCCCCCCC), + ABC_CONST(0xF0F0F0F0F0F0F0F0), + ABC_CONST(0xFF00FF00FF00FF00) + }; + Vec_Ptr_t * vDivs = Vec_PtrAlloc( 6 ); + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + int i, k, ArraySize, * pArray; + for ( i = 0; i < 6; i++ ) + Vec_PtrPush( vDivs, Divs+i ); + Abc_ResubPrepareManager( 1 ); + for ( i = 0; i < (1<<(1<<nVars)); i++ ) //if ( i == 0xCA ) + { + word Truth = Abc_Tt6Stretch( i, nVars ); + Divs[0] = ~Truth; + Divs[1] = Truth; + printf( "%3d : ", i ); + Extra_PrintHex( stdout, (unsigned*)&Truth, nVars ); + printf( " " ); + Dau_DsdPrintFromTruth2( &Truth, nVars ); + printf( " " ); + + //Abc_ResubDumpProblem( "temp.resub", (void **)Vec_PtrArray(vDivs), Vec_PtrSize(vDivs), 1 ); + ArraySize = Abc_ResubComputeFunction( (void **)Vec_PtrArray(vDivs), Vec_PtrSize(vDivs), 1, 16, 50, 0, 0, 1, fVerbose, &pArray ); + printf( "\n" ); + + Vec_IntClear( vRes ); + for ( k = 0; k < ArraySize; k++ ) + Vec_IntPush( vRes, pArray[k] ); + + if ( i == 1000 ) + break; + } + Abc_ResubPrepareManager( 0 ); + Vec_IntFree( vRes ); + Vec_PtrFree( vDivs ); +} +void Gia_ManResubTest3_() +{ + Gia_ResbMan_t * p = Gia_ResbAlloc( 1 ); + word Divs[6] = { 0, 0, + ABC_CONST(0xAAAAAAAAAAAAAAAA), + ABC_CONST(0xCCCCCCCCCCCCCCCC), + ABC_CONST(0xF0F0F0F0F0F0F0F0), + ABC_CONST(0xFF00FF00FF00FF00) + }; + Vec_Ptr_t * vDivs = Vec_PtrAlloc( 6 ); + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + int i; + for ( i = 0; i < 6; i++ ) + Vec_PtrPush( vDivs, Divs+i ); + + { + word Truth = (Divs[2] | Divs[3]) & (Divs[4] & Divs[5]); +// word Truth = (~Divs[2] | Divs[3]) | ~Divs[4]; + Divs[0] = ~Truth; + Divs[1] = Truth; + Extra_PrintHex( stdout, (unsigned*)&Truth, 6 ); + printf( " " ); + Dau_DsdPrintFromTruth2( &Truth, 6 ); + printf( " " ); + Gia_ManResubPerform( p, vDivs, 1, 100, 0, 50, 1, 1, 0, 0 ); + } + Gia_ResbFree( p ); + Vec_IntFree( vRes ); + Vec_PtrFree( vDivs ); +} + +/**Function************************************************************* + + Synopsis [Top level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManResubPair( Vec_Wrd_t * vOn, Vec_Wrd_t * vOff, int nWords, int nIns ) +{ + Gia_ResbMan_t * p = Gia_ResbAlloc( nWords*2 ); + Vec_Ptr_t * vDivs = Vec_PtrAllocSimInfo( nIns+2, nWords*2 ); + word * pSim; int i; + Vec_PtrForEachEntry( word *, vDivs, pSim, i ) + { + if ( i == 0 ) + { + memset( pSim, 0x00, sizeof(word)*nWords ); + memset( pSim+nWords, 0xFF, sizeof(word)*nWords ); + } + else if ( i == 1 ) + { + memset( pSim, 0xFF, sizeof(word)*nWords ); + memset( pSim+nWords, 0x00, sizeof(word)*nWords ); + } + else + { + memmove( pSim, Vec_WrdEntryP(vOn, (i-2)*nWords), sizeof(word)*nWords ); + memmove( pSim+nWords, Vec_WrdEntryP(vOff, (i-2)*nWords), sizeof(word)*nWords ); + } + } + Gia_ManResubPerform( p, vDivs, nWords*2, 100, 0, 50, 1, 1, 0, 0 ); + Gia_ManResubPrint( p->vGates, Vec_PtrSize(vDivs) ); + printf( "\n" ); + //Vec_PtrFree( vDivs ); + Gia_ResbFree( p ); +} + +/**Function************************************************************* + + Synopsis [Top level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCheckResub( Vec_Ptr_t * vDivs, int nWords ) +{ + //int i, nVars = 6, pVarSet[10] = { 2, 189, 2127, 2125, 177, 178 }; + int i, nVars = 3, pVarSet[10] = { 2, 3, 4 }; + word * pOff = (word *)Vec_PtrEntry( vDivs, 0 ); + word * pOn = (word *)Vec_PtrEntry( vDivs, 1 ); + Vec_Int_t * vValue = Vec_IntStartFull( 1 << 6 ); + printf( "Verifying resub:\n" ); + for ( i = 0; i < 64*nWords; i++ ) + { + int v, Mint = 0, Value = Abc_TtGetBit(pOn, i); + if ( !Abc_TtGetBit(pOff, i) && !Value ) + continue; + for ( v = 0; v < nVars; v++ ) + if ( Abc_TtGetBit((word *)Vec_PtrEntry(vDivs, pVarSet[v]), i) ) + Mint |= 1 << v; + if ( Vec_IntEntry(vValue, Mint) == -1 ) + Vec_IntWriteEntry(vValue, Mint, Value); + else if ( Vec_IntEntry(vValue, Mint) != Value ) + printf( "Mismatch in pattern %d\n", i ); + } + printf( "Finished verifying resub.\n" ); + Vec_IntFree( vValue ); +} +Vec_Ptr_t * Gia_ManDeriveDivs( Vec_Wrd_t * vSims, int nWords ) +{ + int i, nDivs = Vec_WrdSize(vSims)/nWords; + Vec_Ptr_t * vDivs = Vec_PtrAlloc( nDivs ); + for ( i = 0; i < nDivs; i++ ) + Vec_PtrPush( vDivs, Vec_WrdEntryP(vSims, nWords*i) ); + return vDivs; +} +Gia_Man_t * Gia_ManResub2( Gia_Man_t * pGia, int nNodes, int nSupp, int nDivs, int iChoice, int fUseXor, int fVerbose, int fVeryVerbose ) +{ + return NULL; +} +Gia_Man_t * Gia_ManResub1( char * pFileName, int nNodes, int nSupp, int nDivs, int iChoice, int fUseXor, int fVerbose, int fVeryVerbose ) +{ + int nWords = 0; + Gia_Man_t * pMan = NULL; + Vec_Wrd_t * vSims = Vec_WrdReadHex( pFileName, &nWords, 1 ); + Vec_Ptr_t * vDivs = vSims ? Gia_ManDeriveDivs( vSims, nWords ) : NULL; + Gia_ResbMan_t * p = Gia_ResbAlloc( nWords ); + //Gia_ManCheckResub( vDivs, nWords ); + if ( Vec_PtrSize(vDivs) >= (1<<14) ) + { + printf( "Reducing all divs from %d to %d.\n", Vec_PtrSize(vDivs), (1<<14)-1 ); + Vec_PtrShrink( vDivs, (1<<14)-1 ); + } + assert( Vec_PtrSize(vDivs) < (1<<14) ); + Gia_ManResubPerform( p, vDivs, nWords, 100, 50, iChoice, fUseXor, 1, 1, 0 ); + if ( Vec_IntSize(p->vGates) ) + { + Vec_Wec_t * vGates = Vec_WecStart(1); + Vec_IntAppend( Vec_WecEntry(vGates, 0), p->vGates ); + pMan = Gia_ManConstructFromGates( vGates, Vec_PtrSize(vDivs) ); + Vec_WecFree( vGates ); + } + else + printf( "Decomposition did not succeed.\n" ); + Gia_ResbFree( p ); + Vec_PtrFree( vDivs ); + Vec_WrdFree( vSims ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManUnivTfo_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vNodes, Vec_Int_t * vPos ) +{ + int i, iFan, Count = 1; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return 0; + Gia_ObjSetTravIdCurrentId(p, iObj); + if ( vNodes && Gia_ObjIsCo(Gia_ManObj(p, iObj)) ) + Vec_IntPush( vNodes, iObj ); + if ( vPos && Gia_ObjIsCo(Gia_ManObj(p, iObj)) ) + Vec_IntPush( vPos, iObj ); + Gia_ObjForEachFanoutStaticId( p, iObj, iFan, i ) + Count += Gia_ManUnivTfo_rec( p, iFan, vNodes, vPos ); + return Count; +} +int Gia_ManUnivTfo( Gia_Man_t * p, int * pObjs, int nObjs, Vec_Int_t ** pvNodes, Vec_Int_t ** pvPos ) +{ + int i, Count = 0; + if ( pvNodes ) + { + if ( *pvNodes ) + Vec_IntClear( *pvNodes ); + else + *pvNodes = Vec_IntAlloc( 100 ); + } + if ( pvPos ) + { + if ( *pvPos ) + Vec_IntClear( *pvPos ); + else + *pvPos = Vec_IntAlloc( 100 ); + } + Gia_ManIncrementTravId( p ); + for ( i = 0; i < nObjs; i++ ) + Count += Gia_ManUnivTfo_rec( p, pObjs[i], pvNodes ? *pvNodes : NULL, pvPos ? *pvPos : NULL ); + if ( pvNodes ) + Vec_IntSort( *pvNodes, 0 ); + if ( pvPos ) + Vec_IntSort( *pvPos, 0 ); + return Count; +} + +/**Function************************************************************* + + Synopsis [Tuning resub.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTryResub( Gia_Man_t * p ) +{ + int nLimit = 20; + int nDivsMax = 200; + int iChoice = 0; + int fUseXor = 1; + int fDebug = 1; + int fVerbose = 0; + abctime clk, clkResub = 0, clkStart = Abc_Clock(); + Vec_Ptr_t * vvSims = Vec_PtrAlloc( 100 ); + Vec_Wrd_t * vSims; + word * pSets[2], * pFunc; + Gia_Obj_t * pObj, * pObj2; + int i, i2, nWords, nNonDec = 0, nTotal = 0; + assert( Gia_ManCiNum(p) < 16 ); + Vec_WrdFreeP( &p->vSimsPi ); + p->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + //Vec_WrdPrintHex( p->vSimsPi, nWords ); + pSets[0] = ABC_CALLOC( word, nWords ); + pSets[1] = ABC_CALLOC( word, nWords ); + vSims = Gia_ManSimPatSim( p ); + Gia_ManLevelNum(p); + Gia_ManCreateRefs(p); + Abc_ResubPrepareManager( nWords ); + Gia_ManStaticFanoutStart( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + Vec_Int_t vGates; + int * pArray, nArray, nTfo, iObj = Gia_ObjId(p, pObj); + int Level = Gia_ObjLevel(p, pObj); + int nMffc = Gia_NodeMffcSizeMark(p, pObj); + pFunc = Vec_WrdEntryP( vSims, nWords*iObj ); + Abc_TtCopy( pSets[0], pFunc, nWords, 1 ); + Abc_TtCopy( pSets[1], pFunc, nWords, 0 ); + Vec_PtrClear( vvSims ); + Vec_PtrPushTwo( vvSims, pSets[0], pSets[1] ); + nTfo = Gia_ManUnivTfo( p, &iObj, 1, NULL, NULL ); + Gia_ManForEachCi( p, pObj2, i2 ) + Vec_PtrPush( vvSims, Vec_WrdEntryP(vSims, nWords*Gia_ObjId(p, pObj2)) ); + Gia_ManForEachAnd( p, pObj2, i2 ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj2) && !Gia_ObjIsTravIdPrevious(p, pObj2) && Gia_ObjLevel(p, pObj2) <= Level ) + Vec_PtrPush( vvSims, Vec_WrdEntryP(vSims, nWords*Gia_ObjId(p, pObj2)) ); + if ( fVerbose ) + printf( "%3d : Lev = %2d Mffc = %2d Divs = %3d Tfo = %3d\n", iObj, Level, nMffc, Vec_PtrSize(vvSims)-2, nTfo ); + clk = Abc_Clock(); + nArray = Abc_ResubComputeFunction( (void **)Vec_PtrArray(vvSims), Vec_PtrSize(vvSims), nWords, Abc_MinInt(nMffc-1, nLimit), nDivsMax, iChoice, fUseXor, fDebug, fVerbose, &pArray ); + clkResub += Abc_Clock() - clk; + vGates.nSize = vGates.nCap = nArray; + vGates.pArray = pArray; + assert( nMffc > Vec_IntSize(&vGates)/2 ); + if ( Vec_IntSize(&vGates) > 0 ) + nTotal += nMffc - Vec_IntSize(&vGates)/2; + nNonDec += Vec_IntSize(&vGates) == 0; + } + printf( "Total nodes = %5d. Non-realizable = %5d. Gain = %6d. ", Gia_ManAndNum(p), nNonDec, nTotal ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + Abc_PrintTime( 1, "Pure resub time", clkResub ); + Abc_ResubPrepareManager( 0 ); + Gia_ManStaticFanoutStop( p ); + Vec_PtrFree( vvSims ); + Vec_WrdFree( vSims ); + ABC_FREE( pSets[0] ); + ABC_FREE( pSets[1] ); +} + + +/**Function************************************************************* + + Synopsis [Deriving a subset.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManDeriveShrink( Vec_Wrd_t * vFuncs, int nWords ) +{ + int i, k = 0, nFuncs = Vec_WrdSize(vFuncs) / nWords / 2; + assert( 2 * nFuncs * nWords == Vec_WrdSize(vFuncs) ); + for ( i = 0; i < nFuncs; i++ ) + { + word * pFunc0 = Vec_WrdEntryP(vFuncs, (2*i+0)*nWords); + word * pFunc1 = Vec_WrdEntryP(vFuncs, (2*i+1)*nWords); + if ( Abc_TtIsConst0(pFunc0, nWords) || Abc_TtIsConst0(pFunc1, nWords) ) + continue; + if ( k < i ) Abc_TtCopy( Vec_WrdEntryP(vFuncs, (2*k+0)*nWords), pFunc0, nWords, 0 ); + if ( k < i ) Abc_TtCopy( Vec_WrdEntryP(vFuncs, (2*k+1)*nWords), pFunc1, nWords, 0 ); + k++; + } + Vec_WrdShrink( vFuncs, 2*k*nWords ); + return k; +} +void Gia_ManDeriveCounts( Vec_Wrd_t * vFuncs, int nWords, Vec_Int_t * vCounts ) +{ + int i, nFuncs = Vec_WrdSize(vFuncs) / nWords / 2; + assert( 2 * nFuncs * nWords == Vec_WrdSize(vFuncs) ); + Vec_IntClear( vCounts ); + for ( i = 0; i < 2*nFuncs; i++ ) + Vec_IntPush( vCounts, Abc_TtCountOnesVec(Vec_WrdEntryP(vFuncs, i*nWords), nWords) ); +} +int Gia_ManDeriveCost( Vec_Wrd_t * vFuncs, int nWords, word * pMask, Vec_Int_t * vCounts ) +{ + int i, Res = 0, nFuncs = Vec_WrdSize(vFuncs) / nWords / 2; + assert( 2 * nFuncs * nWords == Vec_WrdSize(vFuncs) ); + assert( Vec_IntSize(vCounts) * nWords == Vec_WrdSize(vFuncs) ); + for ( i = 0; i < nFuncs; i++ ) + { + int Total[2] = { Vec_IntEntry(vCounts, 2*i+0), Vec_IntEntry(vCounts, 2*i+1) }; + int This[2] = { Abc_TtCountOnesVecMask(Vec_WrdEntryP(vFuncs, (2*i+0)*nWords), pMask, nWords, 0), + Abc_TtCountOnesVecMask(Vec_WrdEntryP(vFuncs, (2*i+1)*nWords), pMask, nWords, 0) }; + assert( Total[0] >= This[0] && Total[1] >= This[1] ); + Res += This[0] * This[1] + (Total[0] - This[0]) * (Total[1] - This[1]); + } + return Res; +} +int Gia_ManDeriveSimpleCost( Vec_Int_t * vCounts ) +{ + int i, Ent1, Ent2, Res = 0; + Vec_IntForEachEntryDouble( vCounts, Ent1, Ent2, i ) + Res += Ent1*Ent2; + return Res; +} +void Gia_ManDeriveNext( Vec_Wrd_t * vFuncs, int nWords, word * pMask ) +{ + int i, iStop = Vec_WrdSize(vFuncs); word Data; + int nFuncs = Vec_WrdSize(vFuncs) / nWords / 2; + assert( 2 * nFuncs * nWords == Vec_WrdSize(vFuncs) ); + Vec_WrdForEachEntryStop( vFuncs, Data, i, iStop ) + Vec_WrdPush( vFuncs, Data ); + for ( i = 0; i < nFuncs; i++ ) + { + word * pFunc0n = Vec_WrdEntryP(vFuncs, (2*i+0)*nWords); + word * pFunc1n = Vec_WrdEntryP(vFuncs, (2*i+1)*nWords); + word * pFunc0p = Vec_WrdEntryP(vFuncs, (2*i+0)*nWords + iStop); + word * pFunc1p = Vec_WrdEntryP(vFuncs, (2*i+1)*nWords + iStop); + Abc_TtAnd( pFunc0p, pFunc0n, pMask, nWords, 0 ); + Abc_TtAnd( pFunc1p, pFunc1n, pMask, nWords, 0 ); + Abc_TtSharp( pFunc0n, pFunc0n, pMask, nWords ); + Abc_TtSharp( pFunc1n, pFunc1n, pMask, nWords ); + } +} +Vec_Int_t * Gia_ManDeriveSubset( Gia_Man_t * p, Vec_Wrd_t * vFuncs, Vec_Int_t * vObjs, Vec_Wrd_t * vSims, int nWords, int fVerbose ) +{ + int i, k, iObj, CostBestPrev, nFuncs = Vec_WrdSize(vFuncs) / nWords; + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + Vec_Int_t * vCounts = Vec_IntAlloc( nFuncs * 2 ); + Vec_Wrd_t * vFSims = Vec_WrdDup( vFuncs ); + assert( nFuncs * nWords == Vec_WrdSize(vFuncs) ); + assert( Gia_ManObjNum(p) * nWords == Vec_WrdSize(vSims) ); + assert( Vec_IntSize(vObjs) <= Gia_ManCandNum(p) ); + nFuncs = Gia_ManDeriveShrink( vFSims, nWords ); + Gia_ManDeriveCounts( vFSims, nWords, vCounts ); + assert( Vec_IntSize(vCounts) * nWords == Vec_WrdSize(vFSims) ); + CostBestPrev = Gia_ManDeriveSimpleCost( vCounts ); + if ( fVerbose ) + printf( "Processing %d functions and %d objects with cost %d\n", nFuncs, Vec_IntSize(vObjs), CostBestPrev ); + for ( i = 0; nFuncs > 0; i++ ) + { + int iObjBest = -1, CountThis, Count0 = ABC_INFINITY, CountBest = ABC_INFINITY; + Vec_IntForEachEntry( vObjs, iObj, k ) + { + if ( Vec_IntFind(vRes, iObj) >= 0 ) + continue; + CountThis = Gia_ManDeriveCost( vFSims, nWords, Vec_WrdEntryP(vSims, iObj*nWords), vCounts ); + if ( CountBest > CountThis ) + { + CountBest = CountThis; + iObjBest = iObj; + } + if ( !k ) Count0 = CountThis; + } + if ( Count0 < CostBestPrev ) + { + CountBest = Count0; + iObjBest = Vec_IntEntry(vObjs, 0); + } + Gia_ManDeriveNext( vFSims, nWords, Vec_WrdEntryP(vSims, iObjBest*nWords) ); + nFuncs = Gia_ManDeriveShrink( vFSims, nWords ); + Gia_ManDeriveCounts( vFSims, nWords, vCounts ); + assert( CountBest == Gia_ManDeriveSimpleCost(vCounts) ); + Vec_IntPush( vRes, iObjBest ); + CostBestPrev = CountBest; + if ( fVerbose ) + printf( "Iter %2d : Funcs = %6d. Object %6d. Cost %6d.\n", i, nFuncs, iObjBest, CountBest ); + } + Vec_IntFree( vCounts ); + Vec_WrdFree( vFSims ); + return vRes; +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/aig/gia/giaResub2.c b/src/aig/gia/giaResub2.c new file mode 100644 index 00000000..1219526f --- /dev/null +++ b/src/aig/gia/giaResub2.c @@ -0,0 +1,1558 @@ +/**CFile**************************************************************** + + FileName [giaResub2.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaResub2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/util/utilTruth.h" +#include "misc/vec/vecHsh.h" +#include "opt/dau/dau.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Gia_Rsb2Man_t_ Gia_Rsb2Man_t; +struct Gia_Rsb2Man_t_ +{ + // hyper-parameters + int nDivsMax; + int nLevelIncrease; + int fUseXor; + int fUseZeroCost; + int fDebug; + int fVerbose; + // input AIG + int nObjs; + int nPis; + int nNodes; + int nPos; + int iFirstPo; + int Level; + int nMffc; + // intermediate data + Vec_Int_t vObjs; + Vec_Wrd_t vSims; + Vec_Ptr_t vpDivs; + Vec_Int_t vDivs; + Vec_Int_t vLevels; + Vec_Int_t vRefs; + Vec_Int_t vCopies; + Vec_Int_t vTried; + word Truth0; + word Truth1; + word CareSet; +}; + +extern void Abc_ResubPrepareManager( int nWords ); +extern int Abc_ResubComputeFunction( void ** ppDivs, int nDivs, int nWords, int nLimit, int nDivsMax, int iChoice, int fUseXor, int fDebug, int fVerbose, int ** ppArray ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Rsb2Man_t * Gia_Rsb2ManAlloc() +{ + Gia_Rsb2Man_t * p = ABC_CALLOC( Gia_Rsb2Man_t, 1 ); + return p; +} +void Gia_Rsb2ManFree( Gia_Rsb2Man_t * p ) +{ + Vec_IntErase( &p->vObjs ); + Vec_WrdErase( &p->vSims ); + Vec_PtrErase( &p->vpDivs ); + Vec_IntErase( &p->vDivs ); + Vec_IntErase( &p->vLevels ); + Vec_IntErase( &p->vRefs ); + Vec_IntErase( &p->vCopies ); + Vec_IntErase( &p->vTried ); + ABC_FREE( p ); +} +void Gia_Rsb2ManStart( Gia_Rsb2Man_t * p, int * pObjs, int nObjs, int nDivsMax, int nLevelIncrease, int fUseXor, int fUseZeroCost, int fDebug, int fVerbose ) +{ + int i; + // hyper-parameters + p->nDivsMax = nDivsMax; + p->nLevelIncrease = nLevelIncrease; + p->fUseXor = fUseXor; + p->fUseZeroCost = fUseZeroCost; + p->fDebug = fDebug; + p->fVerbose = fVerbose; + // user data + Vec_IntClear( &p->vObjs ); + Vec_IntPushArray( &p->vObjs, pObjs, 2*nObjs ); + assert( pObjs[0] == 0 ); + assert( pObjs[1] == 0 ); + p->nObjs = nObjs; + p->nPis = 0; + p->nNodes = 0; + p->nPos = 0; + p->iFirstPo = 0; + for ( i = 1; i < nObjs; i++ ) + { + if ( pObjs[2*i+0] == 0 && pObjs[2*i+1] == 0 ) + p->nPis++; + else if ( pObjs[2*i+0] == pObjs[2*i+1] ) + p->nPos++; + else + p->nNodes++; + } + assert( nObjs == 1 + p->nPis + p->nNodes + p->nPos ); + p->iFirstPo = nObjs - p->nPos; + Vec_WrdClear( &p->vSims ); + Vec_WrdGrow( &p->vSims, 2*nObjs ); + Vec_WrdPush( &p->vSims, 0 ); + Vec_WrdPush( &p->vSims, 0 ); + for ( i = 0; i < p->nPis; i++ ) + { + Vec_WrdPush( &p->vSims, s_Truths6[i] ); + Vec_WrdPush( &p->vSims, ~s_Truths6[i] ); + } + p->vSims.nSize = 2*p->nObjs; + Vec_IntClear( &p->vDivs ); + Vec_IntClear( &p->vLevels ); + Vec_IntClear( &p->vRefs ); + Vec_IntClear( &p->vCopies ); + Vec_IntClear( &p->vTried ); + Vec_PtrClear( &p->vpDivs ); + Vec_IntGrow( &p->vDivs, nObjs ); + Vec_IntGrow( &p->vLevels, nObjs ); + Vec_IntGrow( &p->vRefs, nObjs ); + Vec_IntGrow( &p->vCopies, nObjs ); + Vec_IntGrow( &p->vTried, nObjs ); + Vec_PtrGrow( &p->vpDivs, nObjs ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_Rsb2ManPrint( Gia_Rsb2Man_t * p ) +{ + int i, * pObjs = Vec_IntArray( &p->vObjs ); + printf( "PI = %d. PO = %d. Obj = %d.\n", p->nPis, p->nPos, p->nObjs ); + for ( i = p->nPis + 1; i < p->iFirstPo; i++ ) + printf( "%2d = %c%2d & %c%2d;\n", i, + Abc_LitIsCompl(pObjs[2*i+0]) ? '!' : ' ', Abc_Lit2Var(pObjs[2*i+0]), + Abc_LitIsCompl(pObjs[2*i+1]) ? '!' : ' ', Abc_Lit2Var(pObjs[2*i+1]) ); + for ( i = p->iFirstPo; i < p->nObjs; i++ ) + printf( "%2d = %c%2d;\n", i, + Abc_LitIsCompl(pObjs[2*i+0]) ? '!' : ' ', Abc_Lit2Var(pObjs[2*i+0]) ); +} + +int Gia_Rsb2ManLevel( Gia_Rsb2Man_t * p ) +{ + int i, * pLevs, Level = 0; + Vec_IntClear( &p->vLevels ); + Vec_IntGrow( &p->vLevels, p->nObjs ); + pLevs = Vec_IntArray( &p->vLevels ); + for ( i = p->nPis + 1; i < p->iFirstPo; i++ ) + pLevs[i] = 1 + Abc_MaxInt( pLevs[2*i+0]/2, pLevs[2*i+1]/2 ); + for ( i = p->iFirstPo; i < p->nObjs; i++ ) + Level = Abc_MaxInt( Level, pLevs[i] = pLevs[2*i+0]/2 ); + return Level; +} +word Gia_Rsb2ManOdcs( Gia_Rsb2Man_t * p, int iNode ) +{ + int i; word Res = 0; + int * pObjs = Vec_IntArray( &p->vObjs ); + word * pSims = Vec_WrdArray( &p->vSims ); + for ( i = p->nPis + 1; i < p->iFirstPo; i++ ) + { + if ( pObjs[2*i+0] < pObjs[2*i+1] ) + pSims[2*i+0] = pSims[pObjs[2*i+0]] & pSims[pObjs[2*i+1]]; + else if ( pObjs[2*i+0] > pObjs[2*i+1] ) + pSims[2*i+0] = pSims[pObjs[2*i+0]] ^ pSims[pObjs[2*i+1]]; + else assert( 0 ); + pSims[2*i+1] = ~pSims[2*i+0]; + } + for ( i = p->iFirstPo; i < p->nObjs; i++ ) + pSims[2*i+0] = pSims[pObjs[2*i+0]]; + ABC_SWAP( word, pSims[2*iNode+0], pSims[2*iNode+1] ); + for ( i = iNode + 1; i < p->iFirstPo; i++ ) + { + if ( pObjs[2*i+0] < pObjs[2*i+1] ) + pSims[2*i+0] = pSims[pObjs[2*i+0]] & pSims[pObjs[2*i+1]]; + else if ( pObjs[2*i+0] < pObjs[2*i+1] ) + pSims[2*i+0] = pSims[pObjs[2*i+0]] ^ pSims[pObjs[2*i+1]]; + else assert( 0 ); + pSims[2*i+1] = ~pSims[2*i+0]; + } + for ( i = p->iFirstPo; i < p->nObjs; i++ ) + Res |= pSims[2*i+0] ^ pSims[pObjs[2*i+0]]; + ABC_SWAP( word, pSims[2*iNode+0], pSims[2*iNode+1] ); + return Res; +} +// marks MFFC and returns its size +int Gia_Rsb2ManDeref_rec( Gia_Rsb2Man_t * p, int * pObjs, int * pRefs, int iNode ) +{ + int Counter = 1; + if ( iNode <= p->nPis ) + return 0; + if ( --pRefs[Abc_Lit2Var(pObjs[2*iNode+0])] == 0 ) + Counter += Gia_Rsb2ManDeref_rec( p, pObjs, pRefs, Abc_Lit2Var(pObjs[2*iNode+0]) ); + if ( --pRefs[Abc_Lit2Var(pObjs[2*iNode+1])] == 0 ) + Counter += Gia_Rsb2ManDeref_rec( p, pObjs, pRefs, Abc_Lit2Var(pObjs[2*iNode+1]) ); + return Counter; +} +int Gia_Rsb2ManMffc( Gia_Rsb2Man_t * p, int iNode ) +{ + int i, * pRefs, * pObjs; + Vec_IntFill( &p->vRefs, p->nObjs, 0 ); + pRefs = Vec_IntArray( &p->vRefs ); + pObjs = Vec_IntArray( &p->vObjs ); + assert( pObjs[2*iNode+0] != pObjs[2*iNode+1] ); + for ( i = p->nPis + 1; i < p->iFirstPo; i++ ) + pRefs[Abc_Lit2Var(pObjs[2*i+0])]++, + pRefs[Abc_Lit2Var(pObjs[2*i+1])]++; + for ( i = p->iFirstPo; i < p->nObjs; i++ ) + pRefs[Abc_Lit2Var(pObjs[2*i+0])]++; + for ( i = p->nPis + 1; i < p->iFirstPo; i++ ) + assert( pRefs[i] ); + pRefs[iNode] = 0; + for ( i = iNode + 1; i < p->iFirstPo; i++ ) + if ( !pRefs[Abc_Lit2Var(pObjs[2*i+0])] || !pRefs[Abc_Lit2Var(pObjs[2*i+1])] ) + pRefs[i] = 0; + return Gia_Rsb2ManDeref_rec( p, pObjs, pRefs, iNode ); +} +// collects divisors and maps them into nodes +// assumes MFFC is already marked +int Gia_Rsb2ManDivs( Gia_Rsb2Man_t * p, int iNode ) +{ + int i, iNodeLevel = 0; + int * pRefs = Vec_IntArray( &p->vRefs ); + p->CareSet = Gia_Rsb2ManOdcs( p, iNode ); + p->Truth1 = p->CareSet & Vec_WrdEntry(&p->vSims, 2*iNode); + p->Truth0 = p->CareSet & ~p->Truth1; + Vec_PtrClear( &p->vpDivs ); + Vec_PtrPush( &p->vpDivs, &p->Truth0 ); + Vec_PtrPush( &p->vpDivs, &p->Truth1 ); + Vec_IntClear( &p->vDivs ); + Vec_IntPushTwo( &p->vDivs, -1, -1 ); + for ( i = 1; i <= p->nPis; i++ ) + { + Vec_PtrPush( &p->vpDivs, Vec_WrdEntryP(&p->vSims, 2*i) ); + Vec_IntPush( &p->vDivs, i ); + } + p->nMffc = Gia_Rsb2ManMffc( p, iNode ); + if ( p->nLevelIncrease >= 0 ) + { + p->Level = Gia_Rsb2ManLevel(p); + iNodeLevel = Vec_IntEntry(&p->vLevels, iNode); + } + for ( i = p->nPis + 1; i < p->iFirstPo; i++ ) + { + if ( !pRefs[i] || (p->nLevelIncrease >= 0 && Vec_IntEntry(&p->vLevels, i) > iNodeLevel + p->nLevelIncrease) ) + continue; + Vec_PtrPush( &p->vpDivs, Vec_WrdEntryP(&p->vSims, 2*i) ); + Vec_IntPush( &p->vDivs, i ); + } + assert( Vec_IntSize(&p->vDivs) == Vec_PtrSize(&p->vpDivs) ); + return Vec_IntSize(&p->vDivs); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_Rsb2AddNode( Vec_Int_t * vRes, int iLit0, int iLit1, int iRes0, int iRes1 ) +{ + int iLitMin = iRes0 < iRes1 ? Abc_LitNotCond(iRes0, Abc_LitIsCompl(iLit0)) : Abc_LitNotCond(iRes1, Abc_LitIsCompl(iLit1)); + int iLitMax = iRes0 < iRes1 ? Abc_LitNotCond(iRes1, Abc_LitIsCompl(iLit1)) : Abc_LitNotCond(iRes0, Abc_LitIsCompl(iLit0)); + int iLitRes = Vec_IntSize(vRes); + if ( iLit0 < iLit1 ) // and + { + if ( iLitMin == 0 ) + return 0; + if ( iLitMin == 1 ) + return iLitMax; + if ( iLitMin == Abc_LitNot(iLitMax) ) + return 0; + } + else if ( iLit0 > iLit1 ) // xor + { + if ( iLitMin == 0 ) + return iLitMax; + if ( iLitMin == 1 ) + return Abc_LitNot(iLitMax); + if ( iLitMin == Abc_LitNot(iLitMax) ) + return 1; + } + else assert( 0 ); + assert( iLitMin >= 2 && iLitMax >= 2 ); + if ( iLit0 < iLit1 ) // and + Vec_IntPushTwo( vRes, iLitMin, iLitMax ); + else if ( iLit0 > iLit1 ) // xor + { + assert( !Abc_LitIsCompl(iLit0) ); + assert( !Abc_LitIsCompl(iLit1) ); + Vec_IntPushTwo( vRes, iLitMax, iLitMin ); + } + else assert( 0 ); + return iLitRes; +} +int Gia_Rsb2ManInsert_rec( Vec_Int_t * vRes, int nPis, Vec_Int_t * vObjs, int iNode, Vec_Int_t * vResub, Vec_Int_t * vDivs, Vec_Int_t * vCopies, int iObj ) +{ + if ( Vec_IntEntry(vCopies, iObj) >= 0 ) + return Vec_IntEntry(vCopies, iObj); + assert( iObj > nPis ); + if ( iObj == iNode ) + { + int nVars = Vec_IntSize(vDivs); + int iLitRes = -1, iTopLit = Vec_IntEntryLast( vResub ); + if ( Abc_Lit2Var(iTopLit) == 0 ) + iLitRes = 0; + else if ( Abc_Lit2Var(iTopLit) < nVars ) + iLitRes = Gia_Rsb2ManInsert_rec( vRes, nPis, vObjs, -1, vResub, vDivs, vCopies, Vec_IntEntry(vDivs, Abc_Lit2Var(iTopLit)) ); + else + { + Vec_Int_t * vCopy = Vec_IntAlloc( 10 ); + int k, iLit, iLit0, iLit1; + Vec_IntForEachEntryStop( vResub, iLit, k, Vec_IntSize(vResub)-1 ) + if ( Abc_Lit2Var(iLit) < nVars ) + Gia_Rsb2ManInsert_rec( vRes, nPis, vObjs, -1, vResub, vDivs, vCopies, Vec_IntEntry(vDivs, Abc_Lit2Var(iLit)) ); + Vec_IntForEachEntryDouble( vResub, iLit0, iLit1, k ) + { + int iVar0 = Abc_Lit2Var(iLit0); + int iVar1 = Abc_Lit2Var(iLit1); + int iRes0 = iVar0 < nVars ? Vec_IntEntry(vCopies, Vec_IntEntry(vDivs, iVar0)) : Vec_IntEntry(vCopy, iVar0 - nVars); + int iRes1 = iVar1 < nVars ? Vec_IntEntry(vCopies, Vec_IntEntry(vDivs, iVar1)) : Vec_IntEntry(vCopy, iVar1 - nVars); + iLitRes = Gia_Rsb2AddNode( vRes, iLit0, iLit1, iRes0, iRes1 ); + Vec_IntPush( vCopy, iLitRes ); + } + Vec_IntFree( vCopy ); + } + iLitRes = Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iTopLit) ); + Vec_IntWriteEntry( vCopies, iObj, iLitRes ); + return iLitRes; + } + else + { + int iLit0 = Vec_IntEntry( vObjs, 2*iObj+0 ); + int iLit1 = Vec_IntEntry( vObjs, 2*iObj+1 ); + int iRes0 = Gia_Rsb2ManInsert_rec( vRes, nPis, vObjs, iNode, vResub, vDivs, vCopies, Abc_Lit2Var(iLit0) ); + int iRes1 = Gia_Rsb2ManInsert_rec( vRes, nPis, vObjs, iNode, vResub, vDivs, vCopies, Abc_Lit2Var(iLit1) ); + int iLitRes = Gia_Rsb2AddNode( vRes, iLit0, iLit1, iRes0, iRes1 ); + Vec_IntWriteEntry( vCopies, iObj, iLitRes ); + return iLitRes; + } +} +Vec_Int_t * Gia_Rsb2ManInsert( int nPis, int nPos, Vec_Int_t * vObjs, int iNode, Vec_Int_t * vResub, Vec_Int_t * vDivs, Vec_Int_t * vCopies ) +{ + int i, nObjs = Vec_IntSize(vObjs)/2, iFirstPo = nObjs - nPos; + Vec_Int_t * vRes = Vec_IntAlloc( Vec_IntSize(vObjs) ); +//Vec_IntPrint( vDivs ); +//Vec_IntPrint( vResub ); + Vec_IntFill( vCopies, Vec_IntSize(vObjs), -1 ); + Vec_IntFill( vRes, 2*(nPis + 1), 0 ); + for ( i = 0; i <= nPis; i++ ) + Vec_IntWriteEntry( vCopies, i, 2*i ); + for ( i = iFirstPo; i < nObjs; i++ ) + Gia_Rsb2ManInsert_rec( vRes, nPis, vObjs, iNode, vResub, vDivs, vCopies, Abc_Lit2Var( Vec_IntEntry(vObjs, 2*i) ) ); + for ( i = iFirstPo; i < nObjs; i++ ) + { + int iLitNew = Abc_Lit2LitL( Vec_IntArray(vCopies), Vec_IntEntry(vObjs, 2*i) ); + Vec_IntPushTwo( vRes, iLitNew, iLitNew ); + } + return vRes; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ResubPrintDivs( void ** ppDivs, int nDivs ) +{ + word ** pDivs = (word **)ppDivs; + int i; + for ( i = 0; i < nDivs; i++ ) + { + printf( "Div %2d : ", i ); + Dau_DsdPrintFromTruth( pDivs[i], 6 ); + } +} +int Abc_ResubNodeToTry( Vec_Int_t * vTried, int iFirst, int iLast ) +{ + int iNode; + //for ( iNode = iFirst; iNode < iLast; iNode++ ) + for ( iNode = iLast - 1; iNode >= iFirst; iNode-- ) + if ( Vec_IntFind(vTried, iNode) == -1 ) + return iNode; + return -1; +} +int Abc_ResubComputeWindow( int * pObjs, int nObjs, int nDivsMax, int nLevelIncrease, int fUseXor, int fUseZeroCost, int fDebug, int fVerbose, int ** ppArray, int * pnResubs ) +{ + int iNode, nChanges = 0, RetValue = 0; + Gia_Rsb2Man_t * p = Gia_Rsb2ManAlloc(); + Gia_Rsb2ManStart( p, pObjs, nObjs, nDivsMax, nLevelIncrease, fUseXor, fUseZeroCost, fDebug, fVerbose ); + *ppArray = NULL; + while ( (iNode = Abc_ResubNodeToTry(&p->vTried, p->nPis+1, p->iFirstPo)) > 0 ) + { + int nDivs = Gia_Rsb2ManDivs( p, iNode ); + int * pResub, nResub = Abc_ResubComputeFunction( Vec_PtrArray(&p->vpDivs), nDivs, 1, p->nMffc-1, nDivsMax, 0, fUseXor, fDebug, fVerbose, &pResub ); + if ( nResub == 0 ) + Vec_IntPush( &p->vTried, iNode ); + else + { + int i, k = 0, iTried; + Vec_Int_t vResub = { nResub, nResub, pResub }; + Vec_Int_t * vRes = Gia_Rsb2ManInsert( p->nPis, p->nPos, &p->vObjs, iNode, &vResub, &p->vDivs, &p->vCopies ); + //printf( "\nResubing node %d:\n", iNode ); + //Gia_Rsb2ManPrint( p ); + p->nObjs = Vec_IntSize(vRes)/2; + p->iFirstPo = p->nObjs - p->nPos; + Vec_IntClear( &p->vObjs ); + Vec_IntAppend( &p->vObjs, vRes ); + Vec_IntFree( vRes ); + Vec_IntForEachEntry( &p->vTried, iTried, i ) + if ( Vec_IntEntry(&p->vCopies, iTried) > Abc_Var2Lit(p->nPis, 0) ) // internal node + Vec_IntWriteEntry( &p->vTried, k++, Abc_Lit2Var(Vec_IntEntry(&p->vCopies, iTried)) ); + Vec_IntShrink( &p->vTried, k ); + nChanges++; + //Gia_Rsb2ManPrint( p ); + } + } + if ( nChanges ) + { + RetValue = p->nObjs; + *ppArray = p->vObjs.pArray; + Vec_IntZero( &p->vObjs ); + } + Gia_Rsb2ManFree( p ); + if ( pnResubs ) + *pnResubs = nChanges; + return RetValue; +} +int Abc_ResubComputeWindow2( int * pObjs, int nObjs, int nDivsMax, int nLevelIncrease, int fUseXor, int fUseZeroCost, int fDebug, int fVerbose, int ** ppArray, int * pnResubs ) +{ + *ppArray = ABC_ALLOC( int, 2*nObjs ); + memmove( *ppArray, pObjs, 2*nObjs * sizeof(int) ); + if ( pnResubs ) + *pnResubs = 0; + return nObjs; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Gia_ManToResub( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, * pObjs = ABC_CALLOC( int, 2*Gia_ManObjNum(p) ); + assert( Gia_ManIsNormalized(p) ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + continue; + pObjs[2*i+0] = Gia_ObjFaninLit0(Gia_ManObj(p, i), i); + if ( Gia_ObjIsCo(pObj) ) + pObjs[2*i+1] = pObjs[2*i+0]; + else if ( Gia_ObjIsAnd(pObj) ) + pObjs[2*i+1] = Gia_ObjFaninLit1(Gia_ManObj(p, i), i); + else assert( 0 ); + } + return pObjs; +} +Gia_Man_t * Gia_ManFromResub( int * pObjs, int nObjs, int nIns ) +{ + Gia_Man_t * pNew = Gia_ManStart( nObjs ); + int i; + for ( i = 1; i < nObjs; i++ ) + { + if ( pObjs[2*i] == 0 && i <= nIns ) // pi + Gia_ManAppendCi( pNew ); + else if ( pObjs[2*i] == pObjs[2*i+1] ) // po + Gia_ManAppendCo( pNew, pObjs[2*i] ); + else if ( pObjs[2*i] < pObjs[2*i+1] ) + Gia_ManAppendAnd( pNew, pObjs[2*i], pObjs[2*i+1] ); + else if ( pObjs[2*i] > pObjs[2*i+1] ) + Gia_ManAppendXor( pNew, pObjs[2*i], pObjs[2*i+1] ); + else assert( 0 ); + } + return pNew; +} +Gia_Man_t * Gia_ManResub2Test( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + int nResubs, nObjsNew, * pObjsNew, * pObjs = Gia_ManToResub( p ); +//Gia_ManPrint( p ); + Abc_ResubPrepareManager( 1 ); + nObjsNew = Abc_ResubComputeWindow( pObjs, Gia_ManObjNum(p), 1000, -1, 0, 0, 0, 0, &pObjsNew, &nResubs ); + //printf( "Performed resub %d times. Reduced %d nodes.\n", nResubs, nObjsNew ? Gia_ManObjNum(p) - nObjsNew : 0 ); + Abc_ResubPrepareManager( 0 ); + if ( nObjsNew ) + { + pNew = Gia_ManFromResub( pObjsNew, nObjsNew, Gia_ManCiNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + } + else + pNew = Gia_ManDup( p ); + ABC_FREE( pObjs ); + ABC_FREE( pObjsNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Creating a window with support composed of primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +// returns the number of nodes added to the window when is iPivot is added +// the window nodes in vNodes are labeled with the current traversal ID +// the new node iPivot and its fanout are temporarily labeled and then unlabeled +int Gia_WinTryAddingNode( Gia_Man_t * p, int iPivot, int iPivot2, Vec_Wec_t * vLevels, Vec_Int_t * vNodes ) +{ + Vec_Int_t * vLevel; + Gia_Obj_t * pObj, * pFanout; + int k, i, f, Count = 0; + // precondition: the levelized structure is empty + assert( Vec_WecSizeSize(vLevels) == 0 ); + // precondition: the new object to be added (iPivot) is not in the window + assert( !Gia_ObjIsTravIdCurrentId(p, iPivot) ); + // add the object to the window and to the levelized structure + Gia_ObjSetTravIdCurrentId( p, iPivot ); + Vec_WecPush( vLevels, Gia_ObjLevelId(p, iPivot), iPivot ); + // the same about the second node if it is given + if ( iPivot2 != -1 ) + { + // precondition: the new object to be added (iPivot2) is not in the window + assert( !Gia_ObjIsTravIdCurrentId(p, iPivot2) ); + // add the object to the window and to the levelized structure + Gia_ObjSetTravIdCurrentId( p, iPivot2 ); + Vec_WecPush( vLevels, Gia_ObjLevelId(p, iPivot2), iPivot2 ); + } + // iterate through all objects and explore their fanouts + Vec_WecForEachLevel( vLevels, vLevel, k ) + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + Gia_ObjForEachFanoutStatic( p, pObj, pFanout, f ) + { + if ( f == 5 ) // explore first 5 fanouts of the node + break; + if ( Gia_ObjIsAnd(pFanout) && // internal node + !Gia_ObjIsTravIdCurrent(p, pFanout) && // not in the window + Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pFanout)) && // but fanins are + Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pFanout)) ) // in the window + { + // add fanout to the window and to the levelized structure + Gia_ObjSetTravIdCurrent( p, pFanout ); + Vec_WecPush( vLevels, Gia_ObjLevel(p, pFanout), Gia_ObjId(p, pFanout) ); + // count the number of nodes in the structure + Count++; + } + } + // iterate through the nodes in the levelized structure + Vec_WecForEachLevel( vLevels, vLevel, k ) + { + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + if ( vNodes == NULL ) // it was a test run - unmark the node + Gia_ObjSetTravIdPrevious( p, pObj ); + else // it was a real run - permanently add to the node to the window + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + // clean the levelized structure + Vec_IntClear( vLevel ); + } + // return the number of nodes to be added + return Count; +} +// find the first PI to add based on the fanout count +int Gia_WinAddCiWithMaxFanouts( Gia_Man_t * p ) +{ + int i, Id, nMaxFan = -1, iMaxFan = -1; + Gia_ManForEachCiId( p, Id, i ) + if ( nMaxFan < Gia_ObjFanoutNumId(p, Id) ) + { + nMaxFan = Gia_ObjFanoutNumId(p, Id); + iMaxFan = Id; + } + assert( iMaxFan >= 0 ); + return iMaxFan; +} +// find the next PI to add based on how many nodes will be added to the window +int Gia_WinAddCiWithMaxDivisors( Gia_Man_t * p, Vec_Wec_t * vLevels ) +{ + int i, Id, nCurFan, nMaxFan = -1, iMaxFan = -1; + Gia_ManForEachCiId( p, Id, i ) + { + if ( Gia_ObjIsTravIdCurrentId( p, Id ) ) + continue; + nCurFan = Gia_WinTryAddingNode( p, Id, -1, vLevels, NULL ); + if ( nMaxFan < nCurFan ) + { + nMaxFan = nCurFan; + iMaxFan = Id; + } + } + assert( iMaxFan >= 0 ); + return iMaxFan; +} +// check if the node has unmarked fanouts +int Gia_WinNodeHasUnmarkedFanouts( Gia_Man_t * p, int iPivot ) +{ + int f, iFan; + Gia_ObjForEachFanoutStaticId( p, iPivot, iFan, f ) + if ( !Gia_ObjIsTravIdCurrentId(p, iFan) ) + return 1; + return 0; +} +// this is a translation procedure, which converts the array of node IDs (vObjs) +// into the internal represnetation for the resub engine, which is returned +// (this procedure is not needed when we simply construct a window) +Vec_Int_t * Gia_RsbCiTranslate( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Int_t * vMap ) +{ + int i, iObj, Lit0, Lit1, Fan0, Fan1; + Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); + assert( Vec_IntSize(vMap) == Gia_ManObjNum(p) ); + Vec_IntPushTwo( vNodes, 0, 0 ); // const0 node + Vec_IntForEachEntry( vObjs, iObj, i ) + { + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); + assert( Gia_ObjIsTravIdCurrentId(p, iObj) ); + Fan0 = Gia_ObjIsCi(pObj) ? 0 : Vec_IntEntry(vMap, Gia_ObjFaninId0(pObj, iObj)); + Fan1 = Gia_ObjIsCi(pObj) ? 0 : Vec_IntEntry(vMap, Gia_ObjFaninId1(pObj, iObj)); + Lit0 = Gia_ObjIsCi(pObj) ? 0 : Abc_LitNotCond( Fan0, Gia_ObjFaninC0(pObj) ); + Lit1 = Gia_ObjIsCi(pObj) ? 0 : Abc_LitNotCond( Fan1, Gia_ObjFaninC1(pObj) ); + Vec_IntWriteEntry( vMap, iObj, Vec_IntSize(vNodes) ); + Vec_IntPushTwo( vNodes, Lit0, Lit1 ); + } + Vec_IntForEachEntry( vObjs, iObj, i ) + if ( Gia_WinNodeHasUnmarkedFanouts( p, iObj ) ) + Vec_IntPushTwo( vNodes, Vec_IntEntry(vMap, iObj), Vec_IntEntry(vMap, iObj) ); + return vNodes; +} +// construct a high-volume window support by the given number (nPis) of primary inputs +Vec_Int_t * Gia_RsbCiWindow( Gia_Man_t * p, int nPis ) +{ + Vec_Int_t * vRes; int i, iMaxFan; + Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); + Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_Wec_t * vLevels = Vec_WecStart( Gia_ManLevelNum(p)+1 ); + Gia_ManStaticFanoutStart( p ); + Gia_ManIncrementTravId(p); + // add the first one + iMaxFan = Gia_WinAddCiWithMaxFanouts( p ); + Gia_ObjSetTravIdCurrentId( p, iMaxFan ); + Vec_IntPush( vNodes, iMaxFan ); + // add remaining ones + for ( i = 1; i < nPis; i++ ) + { + iMaxFan = Gia_WinAddCiWithMaxDivisors( p, vLevels ); + Gia_WinTryAddingNode( p, iMaxFan, -1, vLevels, vNodes ); + } + Vec_IntSort( vNodes, 0 ); + vRes = Gia_RsbCiTranslate( p, vNodes, vMap ); + Gia_ManStaticFanoutStop( p ); + Vec_WecFree( vLevels ); + Vec_IntFree( vMap ); +//Vec_IntPrint( vNodes ); + Vec_IntFree( vNodes ); + return vRes; +} +void Gia_RsbCiWindowTest( Gia_Man_t * p ) +{ + Vec_Int_t * vWin = Gia_RsbCiWindow( p, 6 ); + //Vec_IntPrint( vWin ); + Vec_IntFree( vWin ); +} + + + + +/**Function************************************************************* + + Synopsis [Return initial window for the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ObjFaninId( Gia_Obj_t * pObj, int iObj, int n ) { return n ? Gia_ObjFaninId1(pObj, iObj) : Gia_ObjFaninId0(pObj, iObj); } + +static inline int Gia_ObjTravIsTopTwo( Gia_Man_t * p, int iNodeA ) { return (p->pTravIds[iNodeA] >= p->nTravIds - 1); } +static inline int Gia_ObjTravIsSame( Gia_Man_t * p, int iNodeA, int iNodeB ) { return (p->pTravIds[iNodeA] == p->pTravIds[iNodeB]); } +static inline void Gia_ObjTravSetSame( Gia_Man_t * p, int iNodeA, int iNodeB ) { p->pTravIds[iNodeA] = p->pTravIds[iNodeB]; } + +// collect nodes on the path from the meeting point to the root node, excluding the meeting point +void Gia_RsbWindowGather( Gia_Man_t * p, Vec_Int_t * vPaths, int iNode, Vec_Int_t * vVisited ) +{ + int iPrev; + if ( iNode == 0 ) + return; + Vec_IntPush( vVisited, iNode ); + iPrev = Vec_IntEntry( vPaths, iNode ); + if ( iPrev == 0 ) + return; + assert( Gia_ObjTravIsSame(p, iPrev, iNode) ); + Gia_RsbWindowGather( p, vPaths, iPrev, vVisited ); +} +// explore the frontier of nodes in the breadth-first traversal +int Gia_RsbWindowExplore( Gia_Man_t * p, Vec_Int_t * vVisited, int iStart, Vec_Int_t * vPaths, int * piMeet, int * piNode ) +{ + int i, n, iObj, iLimit = Vec_IntSize( vVisited ); + *piMeet = *piNode = 0; + Vec_IntForEachEntryStartStop( vVisited, iObj, i, iStart, iLimit ) + { + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + if ( !Gia_ObjIsAnd(pObj) ) + continue; + for ( n = 0; n < 2; n++ ) + { + int iFan = Gia_ObjFaninId( pObj, iObj, n ); + // if the node was visited on the paths to both fanins, collect it + if ( Gia_ObjTravIsTopTwo(p, iObj) && Gia_ObjTravIsTopTwo(p, iFan) && !Gia_ObjTravIsSame(p, iObj, iFan) ) + { + *piMeet = iFan; + *piNode = iObj; + return 1; + } + // if the node was visited already on this path, skip it + if ( Gia_ObjTravIsTopTwo(p, iFan) ) + { + assert( Gia_ObjTravIsSame(p, iObj, iFan) ); + continue; + } + // label the node as visited + Gia_ObjTravSetSame( p, iFan, iObj ); + Vec_IntWriteEntry( vPaths, iFan, iObj ); + Vec_IntPush( vVisited, iFan ); + } + } + return 0; +} +Vec_Int_t * Gia_RsbWindowInit( Gia_Man_t * p, Vec_Int_t * vPaths, int iPivot, int nIter ) +{ + Vec_Int_t * vVisited = Vec_IntAlloc( 100 ); + Gia_Obj_t * pPivot = Gia_ManObj( p, iPivot ); + int i, n, iStart = 0; + assert( Gia_ObjIsAnd(pPivot) ); + // start paths for both fanins of the pivot node + for ( n = 0; n < 2; n++ ) + { + int iFan = Gia_ObjFaninId( pPivot, iPivot, n ); + Gia_ManIncrementTravId(p); + Vec_IntPush( vVisited, iFan ); + Vec_IntWriteEntry( vPaths, iFan, 0 ); + Gia_ObjSetTravIdCurrentId( p, iFan ); + } + // perform several iterations of breadth-first search + for ( i = 0; i < nIter; i++ ) + { + int iMeet, iNode, iNext = Vec_IntSize(vVisited); + if ( Gia_RsbWindowExplore( p, vVisited, iStart, vPaths, &iMeet, &iNode ) ) + { + // found the shared path + if ( Gia_ObjIsTravIdCurrentId(p, iMeet) ) + assert( Gia_ObjIsTravIdPreviousId(p, iNode) ); + else if ( Gia_ObjIsTravIdPreviousId(p, iMeet) ) + assert( Gia_ObjIsTravIdCurrentId(p, iNode) ); + else assert( 0 ); + // collect the initial window + Vec_IntClear( vVisited ); + Gia_RsbWindowGather( p, vPaths, Vec_IntEntry(vPaths, iMeet), vVisited ); + Gia_RsbWindowGather( p, vPaths, iNode, vVisited ); + Vec_IntPush( vVisited, iPivot ); + break; + } + iStart = iNext; + } + // if no meeting point is found, make sure to return NULL + if ( i == nIter ) + Vec_IntFreeP( &vVisited ); + return vVisited; +} +Vec_Int_t * Gia_RsbCreateWindowInputs( Gia_Man_t * p, Vec_Int_t * vWin ) +{ + Vec_Int_t * vInputs = Vec_IntAlloc(10); + Gia_Obj_t * pObj; int i, n, iObj; + Gia_ManIncrementTravId(p); + Gia_ManForEachObjVec( vWin, p, pObj, i ) + Gia_ObjSetTravIdCurrent(p, pObj); + Gia_ManForEachObjVec( vWin, p, pObj, i ) + { + assert( Gia_ObjIsAnd(pObj) ); + for ( n = 0; n < 2; n++ ) + { + int iFan = n ? Gia_ObjFaninId1p(p, pObj) : Gia_ObjFaninId0p(p, pObj); + if ( !Gia_ObjIsTravIdCurrentId(p, iFan) ) + Vec_IntPushUnique( vInputs, iFan ); + } + } + Vec_IntForEachEntry( vInputs, iObj, i ) + { + Gia_ObjSetTravIdCurrentId( p, iObj ); + Vec_IntPush( vWin, iObj ); + } + return vInputs; +} + +/**Function************************************************************* + + Synopsis [Grow window for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_RsbAddSideInputs( Gia_Man_t * p, Vec_Wec_t * vLevels, Vec_Int_t * vWin ) +{ + Vec_Int_t * vLevel; + Gia_Obj_t * pObj, * pFanout; + int k, i, f, iObj; + // precondition: the levelized structure is empty + assert( Vec_WecSizeSize(vLevels) == 0 ); + // precondition: window nodes are labeled with the current ID + Vec_IntForEachEntry( vWin, iObj, i ) + { + assert( Gia_ObjIsTravIdCurrentId(p, iObj) ); + Vec_WecPush( vLevels, Gia_ObjLevelId(p, iObj), iObj ); + } + // iterate through all objects and explore their fanouts + Vec_WecForEachLevel( vLevels, vLevel, k ) + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + Gia_ObjForEachFanoutStatic( p, pObj, pFanout, f ) + { + if ( f == 5 ) // explore first 5 fanouts of the node + break; + if ( Gia_ObjIsAnd(pFanout) && // internal node + !Gia_ObjIsTravIdCurrent(p, pFanout) && // not in the window + Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pFanout)) && // but fanins are + Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pFanout)) ) // in the window + { + // add fanout to the window and to the levelized structure + Gia_ObjSetTravIdCurrent( p, pFanout ); + Vec_WecPush( vLevels, Gia_ObjLevel(p, pFanout), Gia_ObjId(p, pFanout) ); + Vec_IntPush( vWin, Gia_ObjId(p, pFanout) ); + } + } + // iterate through the nodes in the levelized structure + Vec_WecForEachLevel( vLevels, vLevel, k ) + Vec_IntClear( vLevel ); +} +// expland inputs until saturation while adding the side-fanouts +void Gia_RsbExpandInputs( Gia_Man_t * p, Vec_Wec_t * vLevels, Vec_Int_t * vWin, Vec_Int_t * vInputs ) +{ + Gia_Obj_t * pObj; + int i, n, iFans[2], fChange = 1; + while ( fChange ) + { + fChange = 0; + Gia_ManForEachObjVec( vInputs, p, pObj, i ) + { + if ( !Gia_ObjIsAnd(pObj) ) + continue; + iFans[0] = Gia_ObjFaninId0p(p, pObj); + iFans[1] = Gia_ObjFaninId1p(p, pObj); + if ( !Gia_ObjIsTravIdCurrentId(p, iFans[0]) && !Gia_ObjIsTravIdCurrentId(p, iFans[1]) ) + continue; + Vec_IntRemove( vInputs, Gia_ObjId(p, pObj) ); + assert( Vec_IntFind(vWin, Gia_ObjId(p, pObj)) >= 0 ); + for ( n = 0; n < 2; n++ ) + { + if ( Gia_ObjIsTravIdCurrentId(p, iFans[n]) ) + continue; + assert( Vec_IntFind(vInputs, iFans[n]) == -1 ); + Vec_IntPush( vInputs, iFans[n] ); + Gia_WinTryAddingNode( p, iFans[n], -1, vLevels, vWin ); + assert( Gia_ObjIsTravIdCurrentId(p, iFans[n]) ); + } + fChange = 1; + } + } +} +// select the best input to expand, based on its contribution to the window size +int Gia_RsbSelectOneInput( Gia_Man_t * p, Vec_Wec_t * vLevels, Vec_Int_t * vIns ) +{ + int i, iNode = 0, WeightThis, WeightBest = -1; + Gia_Obj_t * pObj; + Gia_ManForEachObjVec( vIns, p, pObj, i ) + if ( Gia_ObjIsAnd(pObj) ) + { + int iFan0 = Gia_ObjFaninId0p(p, pObj); + int iFan1 = Gia_ObjFaninId1p(p, pObj); + assert( !Gia_ObjIsTravIdCurrentId(p, iFan0) && !Gia_ObjIsTravIdCurrentId(p, iFan1) ); + WeightThis = Gia_WinTryAddingNode( p, iFan0, iFan1, vLevels, NULL ); + if ( WeightBest < WeightThis ) + { + WeightBest = WeightThis; + iNode = Gia_ObjId(p, pObj); + } + } + return iNode; +} +// grow the initial window as long as it fits the input count limit +void Gia_RsbWindowGrow( Gia_Man_t * p, Vec_Wec_t * vLevels, Vec_Int_t * vWin, Vec_Int_t * vIns, int nInputsMax ) +{ + int iNode; + Gia_RsbAddSideInputs( p, vLevels, vWin ); + Gia_RsbExpandInputs( p, vLevels, vWin, vIns ); + while ( Vec_IntSize(vIns) < nInputsMax && (iNode = Gia_RsbSelectOneInput(p, vLevels, vIns)) ) + { + int iFan0 = Gia_ObjFaninId0p(p, Gia_ManObj(p, iNode)); + int iFan1 = Gia_ObjFaninId1p(p, Gia_ManObj(p, iNode)); + assert( !Gia_ObjIsTravIdCurrentId(p, iFan0) && !Gia_ObjIsTravIdCurrentId(p, iFan1) ); + Gia_WinTryAddingNode( p, iFan0, iFan1, vLevels, vWin ); + assert( Gia_ObjIsTravIdCurrentId(p, iFan0) && Gia_ObjIsTravIdCurrentId(p, iFan1) ); + Vec_IntRemove( vIns, iNode ); + Vec_IntPushTwo( vIns, iFan0, iFan1 ); + Gia_RsbExpandInputs( p, vLevels, vWin, vIns ); + } +} + +/**Function************************************************************* + + Synopsis [Grow window for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_WinCreateFromCut_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vWin ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + assert( Gia_ObjIsAnd(pObj) ); + Gia_WinCreateFromCut_rec( p, Gia_ObjFaninId0(pObj, iObj), vWin ); + Gia_WinCreateFromCut_rec( p, Gia_ObjFaninId1(pObj, iObj), vWin ); + Vec_IntPush( vWin, iObj ); +} +// uses levelized structure (vLevels) to collect in array vWin divisors supported by the cut (vIn) +void Gia_WinCreateFromCut( Gia_Man_t * p, int iPivot, Vec_Int_t * vIn, Vec_Wec_t * vLevels, Vec_Int_t * vWin ) +{ + Vec_Int_t * vLevel; + Gia_Obj_t * pObj, * pFanout; + int k, i, f, iObj, Level; + Vec_Int_t * vUsed = Vec_IntAlloc( 100 ); + // precondition: the levelized structure is empty + assert( Vec_WecSizeSize(vLevels) == 0 ); + // clean the resulting array + Vec_IntClear( vWin ); + // collect leaves + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vIn, iObj, i ) + { + Gia_ObjSetTravIdCurrentId( p, iObj ); + Vec_IntPush( vWin, iObj ); + } + // collect internal cone + Gia_WinCreateFromCut_rec( p, iPivot, vWin ); + // add nodes to the levelized structure + Vec_IntForEachEntry( vWin, iObj, i ) + { + Vec_WecPush( vLevels, Gia_ObjLevelId(p, iObj), iObj ); + Vec_IntPushUniqueOrder( vUsed, Gia_ObjLevelId(p, iObj) ); + } + // iterate through all objects and explore their fanouts + //Vec_WecForEachLevel( vLevels, vLevel, k ) + Vec_IntForEachEntry( vUsed, Level, k ) + { + vLevel = Vec_WecEntry( vLevels, Level ); + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + Gia_ObjForEachFanoutStatic( p, pObj, pFanout, f ) + { + if ( f == 5 ) // explore first 5 fanouts of the node + break; + if ( Gia_ObjIsAnd(pFanout) && // internal node + !Gia_ObjIsTravIdCurrent(p, pFanout) && // not in the window + Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pFanout)) && // but fanins are + Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pFanout)) ) // in the window + { + // add fanout to the window and to the levelized structure + Gia_ObjSetTravIdCurrent( p, pFanout ); + Vec_WecPush( vLevels, Gia_ObjLevel(p, pFanout), Gia_ObjId(p, pFanout) ); + Vec_IntPush( vWin, Gia_ObjId(p, pFanout) ); + Vec_IntPushUniqueOrder( vUsed, Gia_ObjLevel(p, pFanout) ); + } + } + Vec_IntClear( vLevel ); + } + Vec_IntSort( vWin, 0 ); + Vec_IntFree( vUsed ); +} +// update the cut until both fanins of AND nodes are not in the cut +int Gia_RsbExpandCut( Gia_Man_t * p, Vec_Int_t * vIns ) +{ + int fOnlyPis = 0, fChange = 1, nSize = Vec_IntSize(vIns); + while ( fChange ) + { + Gia_Obj_t * pObj; + int i, iFan0, iFan1, fHave0, fHave1; + fOnlyPis = 1; + fChange = 0; + // check if some nodes can be expanded without increasing cut size + Gia_ManForEachObjVec( vIns, p, pObj, i ) + { + assert( Gia_ObjIsTravIdCurrent(p, pObj) ); + if ( !Gia_ObjIsAnd(pObj) ) + continue; + fOnlyPis = 0; + iFan0 = Gia_ObjFaninId0p(p, pObj); + iFan1 = Gia_ObjFaninId1p(p, pObj); + fHave0 = Gia_ObjIsTravIdCurrentId(p, iFan0); + fHave1 = Gia_ObjIsTravIdCurrentId(p, iFan1); + if ( !fHave0 && !fHave1 ) + continue; + // can expand because one of the fanins is already in the cut + // remove current cut node + Vec_IntDrop( vIns, i ); + // add missing fanin + if ( !fHave0 ) + { + Vec_IntPush( vIns, iFan0 ); + Gia_ObjSetTravIdCurrentId( p, iFan0 ); + } + if ( !fHave1 ) + { + Vec_IntPush( vIns, iFan1 ); + Gia_ObjSetTravIdCurrentId( p, iFan1 ); + } + fChange = 1; + break; + } + } + assert( Vec_IntSize(vIns) <= nSize ); + return fOnlyPis; +} +int Gia_RsbFindFaninAdd( int iFan, int pFanins[32], int pFaninCounts[32], int nFanins ) +{ + int i; + for ( i = 0; i < nFanins; i++ ) + if ( pFanins[i] == iFan ) + break; + pFanins[i] = iFan; + pFaninCounts[i]++; + return nFanins + (i == nFanins); +} +int Gia_RsbFindFaninToAddToCut( Gia_Man_t * p, Vec_Int_t * vIns ) +{ + Gia_Obj_t * pObj; + int nFanins = 0, pFanins[64] = {0}, pFaninCounts[64] = {0}; + int i, iFan0, iFan1, iFanMax = -1, CountMax = 0; + Gia_ManForEachObjVec( vIns, p, pObj, i ) + { + if ( !Gia_ObjIsAnd(pObj) ) + continue; + iFan0 = Gia_ObjFaninId0p(p, pObj); + iFan1 = Gia_ObjFaninId1p(p, pObj); + assert( !Gia_ObjIsTravIdCurrentId(p, iFan0) ); + assert( !Gia_ObjIsTravIdCurrentId(p, iFan1) ); + nFanins = Gia_RsbFindFaninAdd( iFan0, pFanins, pFaninCounts, nFanins ); + nFanins = Gia_RsbFindFaninAdd( iFan1, pFanins, pFaninCounts, nFanins ); + assert( nFanins < 64 ); + } + // find fanin with the highest count + if ( p->vFanoutNums != NULL ) + { + for ( i = 0; i < nFanins; i++ ) + if ( CountMax < pFaninCounts[i] || (CountMax == pFaninCounts[i] && (Gia_ObjFanoutNumId(p, iFanMax) < Gia_ObjFanoutNumId(p, pFanins[i]))) ) + { + CountMax = pFaninCounts[i]; + iFanMax = pFanins[i]; + } + } + else + { + for ( i = 0; i < nFanins; i++ ) + if ( CountMax < pFaninCounts[i] || (CountMax == pFaninCounts[i] && (Gia_ObjRefNumId(p, iFanMax) < Gia_ObjRefNumId(p, pFanins[i]))) ) + { + CountMax = pFaninCounts[i]; + iFanMax = pFanins[i]; + } + } + return iFanMax; +} +// precondition: nodes in vWin and in vIns are marked with the current ID +void Gia_RsbWindowGrow2( Gia_Man_t * p, int iObj, Vec_Wec_t * vLevels, Vec_Int_t * vWin, Vec_Int_t * vIns, int nInputsMax ) +{ + // window will be recomputed later + Vec_IntClear( vWin ); + // expand the cut without increasing its cost + if ( !Gia_RsbExpandCut( p, vIns ) ) + { + // save it as the best cut + Vec_Int_t * vBest = Vec_IntSize(vIns) <= nInputsMax ? Vec_IntDup(vIns) : NULL; + int fOnlyPis = 0, Iter = 0; + // iterate expansion until + // (1) the cut cannot be expanded because all leaves are PIs + // (2) the cut size exceeded the limit for 5 consecutive iterations + while ( !fOnlyPis && (Vec_IntSize(vIns) <= nInputsMax || Iter < 5) ) + { + int iFanBest = Gia_RsbFindFaninToAddToCut( p, vIns ); + Vec_IntPush( vIns, iFanBest ); + Gia_ObjSetTravIdCurrentId( p, iFanBest ); + fOnlyPis = Gia_RsbExpandCut( p, vIns ); + if ( Vec_IntSize(vIns) > nInputsMax ) + Iter++; + else + Iter = 0; + if ( Vec_IntSize(vIns) <= nInputsMax && (!vBest || Vec_IntSize(vBest) <= Vec_IntSize(vIns)) ) + { + if ( vBest ) + Vec_IntClear(vBest); + else + vBest = Vec_IntAlloc( 10 ); + Vec_IntAppend( vBest, vIns ); + } + } + if ( vBest ) + { + Vec_IntClear( vIns ); + Vec_IntAppend( vIns, vBest ); + Vec_IntFree( vBest ); + } + else + assert( Vec_IntSize(vIns) > nInputsMax ); + } + if ( vLevels && Vec_IntSize(vIns) <= nInputsMax ) + { + Vec_IntSort( vIns, 0 ); + Gia_WinCreateFromCut( p, iObj, vIns, vLevels, vWin ); + } +} + +/**Function************************************************************* + + Synopsis [Create window for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_RsbWindowCompute( Gia_Man_t * p, int iObj, int nInputsMax, int nLevelsMax, Vec_Wec_t * vLevels, Vec_Int_t * vPaths, Vec_Int_t ** pvWin, Vec_Int_t ** pvIns ) +{ + Vec_Int_t * vWin, * vIns; + *pvWin = *pvIns = NULL; + vWin = Gia_RsbWindowInit( p, vPaths, iObj, nLevelsMax ); + if ( vWin == NULL ) + return 0; + vIns = Gia_RsbCreateWindowInputs( p, vWin ); + // vWin and vIns are labeled with the current trav ID + //Vec_IntPrint( vWin ); + //Vec_IntPrint( vIns ); + if ( Vec_IntSize(vIns) <= nInputsMax + 3 ) // consider windows, which initially has a larger input space + Gia_RsbWindowGrow2( p, iObj, vLevels, vWin, vIns, nInputsMax ); + if ( Vec_IntSize(vIns) <= nInputsMax ) + { + Vec_IntSort( vWin, 0 ); + Vec_IntSort( vIns, 0 ); + *pvWin = vWin; + *pvIns = vIns; + return 1; + } + else + { + Vec_IntFree( vWin ); + Vec_IntFree( vIns ); + return 0; + } +} + +/**Function************************************************************* + + Synopsis [Derive GIA from the window] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_RsbFindOutputs( Gia_Man_t * p, Vec_Int_t * vWin, Vec_Int_t * vIns, Vec_Int_t * vRefs ) +{ + Vec_Int_t * vOuts = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj; int i; + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vIns, p, pObj, i ) + Gia_ObjSetTravIdCurrent( p, pObj ); + Gia_ManForEachObjVec( vWin, p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj) && Gia_ObjIsAnd(pObj) ) + { + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId0p(p, pObj), 1 ); + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId1p(p, pObj), 1 ); + } + Gia_ManForEachObjVec( vWin, p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj) && Gia_ObjFanoutNum(p, pObj) != Vec_IntEntry(vRefs, Gia_ObjId(p, pObj)) ) + Vec_IntPush( vOuts, Gia_ObjId(p, pObj) ); + Gia_ManForEachObjVec( vWin, p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj) && Gia_ObjIsAnd(pObj) ) + { + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId0p(p, pObj), -1 ); + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId1p(p, pObj), -1 ); + } + return vOuts; +} + +Gia_Man_t * Gia_RsbDeriveGiaFromWindows( Gia_Man_t * p, Vec_Int_t * vWin, Vec_Int_t * vIns, Vec_Int_t * vOuts ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObjVec( vIns, p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObjVec( vWin, p, pObj, i ) + if ( !~pObj->Value ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + Gia_ManAppendCo( pNew, pObj->Value ); + Gia_ManHashStop( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Naive truth-table-based verification.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word Gia_LutComputeTruth66_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + word Truth0, Truth1; + if ( Gia_ObjIsCi(pObj) ) + return s_Truths6[Gia_ObjCioId(pObj)]; + if ( Gia_ObjIsConst0(pObj) ) + return 0; + assert( Gia_ObjIsAnd(pObj) ); + Truth0 = Gia_LutComputeTruth66_rec( p, Gia_ObjFanin0(pObj) ); + Truth1 = Gia_LutComputeTruth66_rec( p, Gia_ObjFanin1(pObj) ); + if ( Gia_ObjFaninC0(pObj) ) + Truth0 = ~Truth0; + if ( Gia_ObjFaninC1(pObj) ) + Truth1 = ~Truth1; + return Truth0 & Truth1; +} +int Gia_ManVerifyTwoTruths( Gia_Man_t * p1, Gia_Man_t * p2 ) +{ + int i, fFailed = 0; + assert( Gia_ManCoNum(p1) == Gia_ManCoNum(p2) ); + for ( i = 0; i < Gia_ManCoNum(p1); i++ ) + { + Gia_Obj_t * pPo1 = Gia_ManCo(p1, i); + Gia_Obj_t * pPo2 = Gia_ManCo(p2, i); + word word1 = Gia_LutComputeTruth66_rec( p1, Gia_ObjFanin0(pPo1) ); + word word2 = Gia_LutComputeTruth66_rec( p2, Gia_ObjFanin0(pPo2) ); + if ( Gia_ObjFaninC0(pPo1) ) + word1 = ~word1; + if ( Gia_ObjFaninC0(pPo2) ) + word2 = ~word2; + if ( word1 != word2 ) + { + //Dau_DsdPrintFromTruth( &word1, 6 ); + //Dau_DsdPrintFromTruth( &word2, 6 ); + printf( "Verification failed for output %d (out of %d).\n", i, Gia_ManCoNum(p1) ); + fFailed = 1; + } + } +// if ( !fFailed ) +// printf( "Verification succeeded for %d outputs.\n", Gia_ManCoNum(p1) ); + return !fFailed; +} + + + +/**Function************************************************************* + + Synopsis [Enumerate windows of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_RsbEnumerateWindows( Gia_Man_t * p, int nInputsMax, int nLevelsMax ) +{ + int fVerbose = 0; + int fUseHash = 0; + int i, nWins = 0, nWinSize = 0, nInsSize = 0, nOutSize = 0, nNodeGain = 0; + Vec_Wec_t * vLevels = Vec_WecStart( Gia_ManLevelNum(p)+1 ); + Vec_Int_t * vPaths = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_Int_t * vRefs = Vec_IntStart( Gia_ManObjNum(p) ); + Hsh_VecMan_t * pHash = Hsh_VecManStart( 1000 ); + Gia_Obj_t * pObj; + Gia_Man_t * pIn, * pOut; + abctime clk = Abc_Clock(); + Gia_ManStaticFanoutStart( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + Vec_Int_t * vWin, * vIns, * vOuts; + if ( !Gia_RsbWindowCompute( p, i, nInputsMax, nLevelsMax, vLevels, vPaths, &vWin, &vIns ) ) + continue; + vOuts = Gia_RsbFindOutputs( p, vWin, vIns, vRefs ); + nWins++; + nWinSize += Vec_IntSize(vWin); + nInsSize += Vec_IntSize(vIns); + nOutSize += Vec_IntSize(vOuts); + + + if ( fVerbose ) + { + printf( "\n\nObj %d\n", i ); + Vec_IntPrint( vWin ); + Vec_IntPrint( vIns ); + Vec_IntPrint( vOuts ); + printf( "\n" ); + } + else if ( Vec_IntSize(vWin) > 1000 ) + printf( "Obj %d. Window: Ins = %d. Ands = %d. Outs = %d.\n", + i, Vec_IntSize(vIns), Vec_IntSize(vWin)-Vec_IntSize(vIns), Vec_IntSize(vOuts) ); + + if ( fUseHash ) + { + int nEntries = Hsh_VecSize(pHash); + Hsh_VecManAdd( pHash, vWin ); + if ( nEntries == Hsh_VecSize(pHash) ) + { + Vec_IntFree( vWin ); + Vec_IntFree( vIns ); + Vec_IntFree( vOuts ); + continue; + } + } + + pIn = Gia_RsbDeriveGiaFromWindows( p, vWin, vIns, vOuts ); + pOut = Gia_ManResub2Test( pIn ); + //pOut = Gia_ManDup( pIn ); + if ( !Gia_ManVerifyTwoTruths( pIn, pOut ) ) + { + Gia_ManPrint( pIn ); + Gia_ManPrint( pOut ); + pOut = pOut; + } + + nNodeGain += Gia_ManAndNum(pIn) - Gia_ManAndNum(pOut); + Gia_ManStop( pIn ); + Gia_ManStop( pOut ); + + Vec_IntFree( vWin ); + Vec_IntFree( vIns ); + Vec_IntFree( vOuts ); + } + Gia_ManStaticFanoutStop( p ); + Vec_WecFree( vLevels ); + Vec_IntFree( vPaths ); + Vec_IntFree( vRefs ); + printf( "Computed windows for %d nodes (out of %d). Unique = %d. Ave inputs = %.2f. Ave outputs = %.2f. Ave volume = %.2f. Gain = %d. ", + nWins, Gia_ManAndNum(p), Hsh_VecSize(pHash), 1.0*nInsSize/Abc_MaxInt(1,nWins), + 1.0*nOutSize/Abc_MaxInt(1,nWins), 1.0*nWinSize/Abc_MaxInt(1,nWins), nNodeGain ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Hsh_VecManStop( pHash ); +} + +/**Function************************************************************* + + Synopsis [Apply k-resub to one AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_RsbTryOneWindow( Gia_Man_t * p ) +{ + return Gia_ManResub2Test( p ); +} + +/**Function************************************************************* + + Synopsis [Apply k-resub to one AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_RsbTestArray() +{ + int Array[1000] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 3, 7, 15, 17, 8, 19, + 5, 20, 5, 12, 8, 24, 4, 12, 9, 28, 27, 31, 23, 32, 4, 13, 8, 36, 5, + 13, 18, 40, 9, 18, 5, 44, 19, 36, 9, 48, 47, 51, 10, 18, 40, 54, 8, + 56, 25, 37, 44, 61, 59, 63, 8, 28, 8, 18, 25, 68, 66, 70, 64, 73, 11, + 19, 8, 13, 76, 78, 10, 19, 40, 82, 9, 84, 81, 87, 20, 61, 19, 28, 30, + 92, 91, 95, 88, 96, 74, 98, 9, 40, 49, 103, 27, 104, 10, 107, 8, 40, + 9, 24, 111, 113, 11, 115, 109, 117, 11, 66, 51, 121, 118, 122, 18, 36, + 18, 110, 93, 127, 10, 131, 129, 133, 11, 38, 32, 137, 103, 138, 19, 141, + 134, 143, 28, 76, 9, 146, 11, 110, 19, 150, 149, 153, 87, 95, 9, 19, 10, + 159, 61, 160, 18, 30, 61, 158, 9, 12, 25, 169, 19, 171, 111, 173, 10, 175, + 167, 177, 18, 102, 4, 20, 18, 171, 183, 185, 11, 187, 181, 189, 178, 190, + 24, 44, 11, 194, 8, 54, 4, 198, 197, 201, 45, 49, 10, 39, 9, 126, 73, 209, + 11, 211, 54, 168, 213, 215, 43, 167, 67, 218, 10, 221, 26, 54, 18, 18, 34, + 34, 38, 38, 40, 40, 42, 42, 52, 52, 100, 100, 124, 124, 126, 126, 144, 144, + 148, 148, 154, 154, 156, 156, 162, 162, 164, 164, 192, 192, 70, 70, 202, + 202, 204, 204, 206, 206, 216, 216, 222, 222, 224, 224 + }; + int i, iFan0, iFan1, nResubs; + int * pRes; + // create the internal array + Vec_Int_t * vArray = Vec_IntAlloc( 100 ); + for ( i = 0; i < 50 || Array[i] > 0; i++ ) + Vec_IntPush( vArray, Array[i] ); + Vec_IntPrint( vArray ); + // check the nodes + printf( "Constant0 and primary inputs:\n" ); + Vec_IntForEachEntryDouble( vArray, iFan0, iFan1, i ) + { + if ( iFan0 != iFan1 ) + break; + printf( "%2d = %c%2d & %c%2d;\n", i, + Abc_LitIsCompl(iFan0) ? '!' : ' ', Abc_Lit2Var(iFan0), + Abc_LitIsCompl(iFan1) ? '!' : ' ', Abc_Lit2Var(iFan1) ); + } + printf( "Primary outputs:\n" ); + Vec_IntForEachEntryDoubleStart( vArray, iFan0, iFan1, i, 14 ) + { + if ( iFan0 != iFan1 ) + continue; + printf( "%2d = %c%2d & %c%2d;\n", i, + Abc_LitIsCompl(iFan0) ? '!' : ' ', Abc_Lit2Var(iFan0), + Abc_LitIsCompl(iFan1) ? '!' : ' ', Abc_Lit2Var(iFan1) ); + } + // run the resub + Abc_ResubPrepareManager( 1 ); + Abc_ResubComputeWindow( Vec_IntArray(vArray), Vec_IntSize(vArray)/2, 10, -1, 0, 0, 1, 1, &pRes, &nResubs ); + Abc_ResubPrepareManager( 0 ); + Vec_IntFree( vArray ); +} + +/**Function************************************************************* + + Synopsis [Computing cuts of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManExtractCuts2( Gia_Man_t * p, int nCutSize, int nCuts, int fVerbose ) +{ + int c, nLevelMax = 8; + abctime clk = Abc_Clock(); + Vec_Wec_t * vCuts = Vec_WecStart( nCuts ); + Vec_Int_t * vPaths = Vec_IntStart( Gia_ManObjNum(p) ); + srand( time(NULL) ); + for ( c = 0; c < nCuts; ) + { + Vec_Int_t * vCut, * vWin = NULL; + while ( vWin == NULL ) + { + int iPivot = 1 + Gia_ManCiNum(p) + rand() % Gia_ManAndNum(p); + assert( Gia_ObjIsAnd(Gia_ManObj(p, iPivot)) ); + vWin = Gia_RsbWindowInit( p, vPaths, iPivot, nLevelMax ); + } + vCut = Gia_RsbCreateWindowInputs( p, vWin ); + if ( Vec_IntSize(vCut) >= nCutSize - 2 && Vec_IntSize(vCut) <= nCutSize ) + { + Vec_IntPush( Vec_WecEntry(vCuts, c), Vec_IntSize(vCut) ); + Vec_IntAppend( Vec_WecEntry(vCuts, c++), vCut ); + } + Vec_IntFree( vCut ); + Vec_IntFree( vWin ); + } + Vec_IntFree( vPaths ); + Abc_PrintTime( 0, "Computing cuts ", Abc_Clock() - clk ); + return vCuts; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/gia/giaResub3.c b/src/aig/gia/giaResub3.c new file mode 100644 index 00000000..71e182d1 --- /dev/null +++ b/src/aig/gia/giaResub3.c @@ -0,0 +1,54 @@ +/**CFile**************************************************************** + + FileName [giaResub3.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Resubstitution computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaResub3.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManPerformNewResub( Gia_Man_t * p, int nWinCount, int nCutSize, int nProcs, int fVerbose ) +{ + return NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/gia/giaScript.c b/src/aig/gia/giaScript.c index 334b1ee9..b52288a9 100644 --- a/src/aig/gia/giaScript.c +++ b/src/aig/gia/giaScript.c @@ -88,7 +88,12 @@ Gia_Man_t * Gia_ManAigSyn2( Gia_Man_t * pInit, int fOldAlgo, int fCoarsen, int f p = Gia_ManDup( pInit ); Gia_ManTransferTiming( p, pInit ); if ( Gia_ManAndNum(p) == 0 ) - return p; + { + pNew = Gia_ManDup(p); + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( p ); + return pNew; + } // delay optimization if ( fDelayMin && p->pManTime == NULL ) { @@ -157,7 +162,12 @@ Gia_Man_t * Gia_ManAigSyn3( Gia_Man_t * p, int fVerbose, int fVeryVerbose ) pPars->nRelaxRatio = 40; if ( fVerbose ) Gia_ManPrintStats( p, NULL ); if ( Gia_ManAndNum(p) == 0 ) - return Gia_ManDup(p); + { + pNew = Gia_ManDup(p); + Gia_ManTransferTiming( pNew, p ); + //Gia_ManStop( p ); + return pNew; + } // perform balancing pNew = Gia_ManAreaBalance( p, 0, ABC_INFINITY, fVeryVerbose, 0 ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); @@ -189,7 +199,12 @@ Gia_Man_t * Gia_ManAigSyn4( Gia_Man_t * p, int fVerbose, int fVeryVerbose ) pPars->nRelaxRatio = 40; if ( fVerbose ) Gia_ManPrintStats( p, NULL ); if ( Gia_ManAndNum(p) == 0 ) - return Gia_ManDup(p); + { + pNew = Gia_ManDup(p); + Gia_ManTransferTiming( pNew, p ); + //Gia_ManStop( p ); + return pNew; + } //Gia_ManAigPrintPiLevels( p ); // perform balancing pNew = Gia_ManAreaBalance( p, 0, ABC_INFINITY, fVeryVerbose, 0 ); diff --git a/src/aig/gia/giaSim.c b/src/aig/gia/giaSim.c index 001bd8ac..ecad182f 100644 --- a/src/aig/gia/giaSim.c +++ b/src/aig/gia/giaSim.c @@ -1222,6 +1222,172 @@ int Gia_ManIncrSimCheckEqual( Gia_Man_t * p, int iLit0, int iLit1 ) } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimOneBit( Gia_Man_t * p, Vec_Int_t * vValues ) +{ + Gia_Obj_t * pObj; int k; + assert( Vec_IntSize(vValues) == Gia_ManCiNum(p) ); + + Gia_ManConst0(p)->fMark0 = 0; + Gia_ManForEachCi( p, pObj, k ) + pObj->fMark0 = Vec_IntEntry(vValues, k); + Gia_ManForEachAnd( p, pObj, k ) + pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); + Gia_ManForEachCo( p, pObj, k ) + pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); + + Gia_ManForEachCi( p, pObj, k ) + printf( "%d", k % 10 ); + printf( "\n" ); + Gia_ManForEachCi( p, pObj, k ) + printf( "%d", Vec_IntEntry(vValues, k) ); + printf( "\n" ); + + Gia_ManForEachCo( p, pObj, k ) + printf( "%d", k % 10 ); + printf( "\n" ); + Gia_ManForEachCo( p, pObj, k ) + printf( "%d", pObj->fMark0 ); + printf( "\n" ); + printf( "\n" ); +} +void Gia_ManSimOneBitTest2( Gia_Man_t * p ) +{ + Vec_Int_t * vValues = Vec_IntStart( Gia_ManCiNum(p) ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Vec_IntWriteEntry( vValues, 1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2+2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Vec_IntWriteEntry( vValues, 1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntFill( vValues, Vec_IntSize(vValues)/2, 1 ); + Vec_IntFillExtra( vValues, Gia_ManCiNum(p), 0 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Gia_ManCiNum(p), 0 ); + + Vec_IntFill( vValues, Gia_ManCiNum(p), 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Gia_ManCiNum(p), 0 ); + + Vec_IntFill( vValues, Gia_ManCiNum(p), 1 ); + Vec_IntWriteEntry( vValues, 127, 1 ); + Vec_IntWriteEntry( vValues, 255, 0 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Gia_ManCiNum(p), 0 ); + + Vec_IntFill( vValues, Gia_ManCiNum(p), 1 ); + Vec_IntWriteEntry( vValues, 127, 0 ); + Vec_IntWriteEntry( vValues, 255, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Gia_ManCiNum(p), 0 ); + + Vec_IntFill( vValues, Gia_ManCiNum(p), 1 ); + Vec_IntWriteEntry( vValues, 127, 0 ); + Vec_IntWriteEntry( vValues, 255, 0 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Gia_ManCiNum(p), 0 ); + + Vec_IntFree( vValues ); +} +void Gia_ManSimOneBitTest3( Gia_Man_t * p ) +{ + Vec_Int_t * vValues = Vec_IntStart( Gia_ManCiNum(p) ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Vec_IntWriteEntry( vValues, 1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2+2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -1, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-2, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-2, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-2, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-3, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -2, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -3, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-2, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-3, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -2, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -3, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntFill( vValues, Vec_IntSize(vValues), 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntFree( vValues ); +} + + +void Gia_ManSimOneBitTest( Gia_Man_t * p ) +{ + Vec_Int_t * vValues = Vec_IntStart( Gia_ManCiNum(p) ); + int i, k; + for ( i = 0; i < 10; i++ ) + { + for ( k = 0; k < Vec_IntSize(vValues); k++ ) + Vec_IntWriteEntry( vValues, k, Vec_IntEntry(vValues, k) ^ (rand()&1) ); + + printf( "Values = %d ", Vec_IntSum(vValues) ); + Gia_ManSimOneBit( p, vValues ); + } +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/aig/gia/giaSimBase.c b/src/aig/gia/giaSimBase.c index c53c1db8..c31064fe 100644 --- a/src/aig/gia/giaSimBase.c +++ b/src/aig/gia/giaSimBase.c @@ -21,6 +21,7 @@ #include "gia.h" #include "misc/util/utilTruth.h" #include "misc/extra/extra.h" +//#include <immintrin.h> ABC_NAMESPACE_IMPL_START @@ -112,7 +113,13 @@ static inline void Gia_ManSimPatSimPo( Gia_Man_t * p, int i, Gia_Obj_t * pObj, i word * pSims0 = pSims + nWords*Gia_ObjFaninId0(pObj, i); word * pSims2 = pSims + nWords*i; int w; for ( w = 0; w < nWords; w++ ) - pSims2[w] = (pSims0[w] ^ Diff0); + pSims2[w] = (pSims0[w] ^ Diff0); +} +static inline void Gia_ManSimPatSimNot( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims ) +{ + word * pSims = Vec_WrdArray(vSims) + nWords*i; int w; + for ( w = 0; w < nWords; w++ ) + pSims[w] = ~pSims[w]; } Vec_Wrd_t * Gia_ManSimPatSim( Gia_Man_t * pGia ) { @@ -127,6 +134,427 @@ Vec_Wrd_t * Gia_ManSimPatSim( Gia_Man_t * pGia ) Gia_ManSimPatSimPo( pGia, Gia_ObjId(pGia, pObj), pObj, nWords, vSims ); return vSims; } +Vec_Wrd_t * Gia_ManSimPatSimOut( Gia_Man_t * pGia, Vec_Wrd_t * vSimsPi, int fOuts ) +{ + Gia_Obj_t * pObj; + int i, nWords = Vec_WrdSize(vSimsPi) / Gia_ManCiNum(pGia); + Vec_Wrd_t * vSimsCo = fOuts ? Vec_WrdStart( Gia_ManCoNum(pGia) * nWords ) : NULL; + Vec_Wrd_t * vSims = Vec_WrdStart( Gia_ManObjNum(pGia) * nWords ); + assert( Vec_WrdSize(vSimsPi) % Gia_ManCiNum(pGia) == 0 ); + Gia_ManSimPatAssignInputs( pGia, nWords, vSims, vSimsPi ); + Gia_ManForEachAnd( pGia, pObj, i ) + Gia_ManSimPatSimAnd( pGia, i, pObj, nWords, vSims ); + Gia_ManForEachCo( pGia, pObj, i ) + Gia_ManSimPatSimPo( pGia, Gia_ObjId(pGia, pObj), pObj, nWords, vSims ); + if ( !fOuts ) + return vSims; + Gia_ManForEachCo( pGia, pObj, i ) + memcpy( Vec_WrdEntryP(vSimsCo, i*nWords), Vec_WrdEntryP(vSims, Gia_ObjId(pGia, pObj)*nWords), sizeof(word)*nWords ); + Vec_WrdFree( vSims ); + return vSimsCo; +} +static inline void Gia_ManSimPatSimAnd3( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsC ) +{ + word pComps[2] = { ~(word)0, 0 }; + word Diff0 = pComps[Gia_ObjFaninC0(pObj)]; + word Diff1 = pComps[Gia_ObjFaninC1(pObj)]; + word * pSims0 = Vec_WrdArray(vSims) + nWords*Gia_ObjFaninId0(pObj, i); + word * pSims1 = Vec_WrdArray(vSims) + nWords*Gia_ObjFaninId1(pObj, i); + word * pSims2 = Vec_WrdArray(vSims) + nWords*i; + word * pSimsC0 = Vec_WrdArray(vSimsC) + nWords*Gia_ObjFaninId0(pObj, i); + word * pSimsC1 = Vec_WrdArray(vSimsC) + nWords*Gia_ObjFaninId1(pObj, i); + word * pSimsC2 = Vec_WrdArray(vSimsC) + nWords*i; int w; + if ( Gia_ObjIsXor(pObj) ) + for ( w = 0; w < nWords; w++ ) + { + pSimsC0[w] |= pSimsC2[w]; + pSimsC1[w] |= pSimsC2[w]; + } + else + for ( w = 0; w < nWords; w++ ) + { + pSimsC0[w] |= (pSims2[w] | (pSims0[w] ^ Diff0)) & pSimsC2[w]; + pSimsC1[w] |= (pSims2[w] | (pSims1[w] ^ Diff1)) & pSimsC2[w]; + } +} +Vec_Wrd_t * Gia_ManSimPatSimIn( Gia_Man_t * pGia, Vec_Wrd_t * vSims, int fIns, Vec_Int_t * vAnds ) +{ + Gia_Obj_t * pObj; + int i, Id, nWords = Vec_WrdSize(vSims) / Gia_ManObjNum(pGia); + Vec_Wrd_t * vSimsCi = fIns ? Vec_WrdStart( Gia_ManCiNum(pGia) * nWords ) : NULL; + Vec_Wrd_t * vSimsC = Vec_WrdStart( Vec_WrdSize(vSims) ); + assert( Vec_WrdSize(vSims) % Gia_ManObjNum(pGia) == 0 ); + if ( vAnds ) + Vec_IntForEachEntry( vAnds, Id, i ) + memset( Vec_WrdEntryP(vSimsC, Id*nWords), 0xFF, sizeof(word)*nWords ); + else + Gia_ManForEachCoDriverId( pGia, Id, i ) + memset( Vec_WrdEntryP(vSimsC, Id*nWords), 0xFF, sizeof(word)*nWords ); + Gia_ManForEachAndReverse( pGia, pObj, i ) + Gia_ManSimPatSimAnd3( pGia, i, pObj, nWords, vSims, vSimsC ); + if ( !fIns ) + return vSimsC; + Gia_ManForEachCi( pGia, pObj, i ) + memcpy( Vec_WrdEntryP(vSimsCi, i*nWords), Vec_WrdEntryP(vSimsC, Gia_ObjId(pGia, pObj)*nWords), sizeof(word)*nWords ); + Vec_WrdFree( vSimsC ); + return vSimsCi; +} +void Gia_ManSimPatSimInTest( Gia_Man_t * pGia ) +{ + int nWords = 10; + Vec_Wrd_t * vSimsCi = Vec_WrdStartRandom( Gia_ManCiNum(pGia) * nWords ); + Vec_Wrd_t * vSims = Gia_ManSimPatSimOut( pGia, vSimsCi, 0 ); + Vec_Wrd_t * vSims2 = Gia_ManSimPatSimIn( pGia, vSims, 0, NULL ); + int nOnes = Abc_TtCountOnesVec( Vec_WrdArray(vSims2), Vec_WrdSize(vSims2) ); + int nTotal = 64*nWords*Gia_ManCandNum(pGia); + printf( "Ratio = %6.2f %%\n", 100.0*nOnes/nTotal ); + Vec_WrdFree( vSims ); + Vec_WrdFree( vSims2 ); + Vec_WrdFree( vSimsCi ); +} +static inline void Gia_ManSimPatSimAnd4( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsC ) +{ + word pComps[2] = { ~(word)0, 0 }; + word Diff0 = pComps[Gia_ObjFaninC0(pObj)]; + word Diff1 = pComps[Gia_ObjFaninC1(pObj)]; + word * pSims0 = Vec_WrdArray(vSims) + nWords*Gia_ObjFaninId0(pObj, i); + word * pSims1 = Vec_WrdArray(vSims) + nWords*Gia_ObjFaninId1(pObj, i); + word * pSimsC0 = Vec_WrdArray(vSimsC) + nWords*Gia_ObjFaninId0(pObj, i); + word * pSimsC1 = Vec_WrdArray(vSimsC) + nWords*Gia_ObjFaninId1(pObj, i); + word * pSimsC2 = Vec_WrdArray(vSimsC) + nWords*i; int w; + if ( Gia_ObjIsXor(pObj) ) + for ( w = 0; w < nWords; w++ ) + pSimsC2[w] = pSimsC0[w] & pSimsC1[w]; + else + for ( w = 0; w < nWords; w++ ) + pSimsC2[w] = (pSimsC0[w] & pSimsC1[w]) | ((pSims0[w] ^ Diff0) & pSimsC0[w]) | ((pSims1[w] ^ Diff1) & pSimsC1[w]); +} +Vec_Wrd_t * Gia_ManSimPatSimC( Gia_Man_t * pGia, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsCiC ) +{ + Gia_Obj_t * pObj; + int i, Id, nWords = Vec_WrdSize(vSims) / Gia_ManObjNum(pGia); + Vec_Wrd_t * vSimsC = Vec_WrdStart( Vec_WrdSize(vSims) ); + assert( Vec_WrdSize(vSims) % Gia_ManObjNum(pGia) == 0 ); + memset( Vec_WrdEntryP(vSimsC, 0), 0xFF, sizeof(word)*nWords ); + Gia_ManForEachCiId( pGia, Id, i ) + memmove( Vec_WrdEntryP(vSimsC, Id*nWords), Vec_WrdEntryP(vSimsCiC, i*nWords), sizeof(word)*nWords ); + Gia_ManForEachAnd( pGia, pObj, i ) + Gia_ManSimPatSimAnd4( pGia, i, pObj, nWords, vSims, vSimsC ); + return vSimsC; +} +void Gia_ManSimPatSimCTest( Gia_Man_t * pGia ) +{ + int nWords = 10; + Vec_Wrd_t * vSimsCi = Vec_WrdStartRandom( Gia_ManCiNum(pGia) * nWords ); + Vec_Wrd_t * vSims = Gia_ManSimPatSimOut( pGia, vSimsCi, 0 ); + Vec_Wrd_t * vSims2 = Gia_ManSimPatSimIn( pGia, vSims, 0, NULL ); + Vec_Wrd_t * vSimsCi2 = Gia_ManSimPatSimIn( pGia, vSims, 1, NULL ); + Vec_Wrd_t * vSims3 = Gia_ManSimPatSimC( pGia, vSims, vSimsCi2 ); + int nOnes2 = Abc_TtCountOnesVec( Vec_WrdArray(vSims2), Vec_WrdSize(vSims2) ); + int nOnes3 = Abc_TtCountOnesVec( Vec_WrdArray(vSims3), Vec_WrdSize(vSims3) ); + int nTotal = 64*nWords*Gia_ManCandNum(pGia); + printf( "Ratio = %6.2f %% Ratio = %6.2f %%\n", 100.0*nOnes2/nTotal, 100.0*nOnes3/nTotal ); + Vec_WrdFree( vSims ); + Vec_WrdFree( vSims2 ); + Vec_WrdFree( vSims3 ); + Vec_WrdFree( vSimsCi ); + Vec_WrdFree( vSimsCi2 ); +} +void Gia_ManSimPatResim( Gia_Man_t * pGia, Vec_Int_t * vObjs, int nWords, Vec_Wrd_t * vSims ) +{ + Gia_Obj_t * pObj; int i; + Gia_ManForEachObjVec( vObjs, pGia, pObj, i ) + if ( i == 0 ) + Gia_ManSimPatSimNot( pGia, Gia_ObjId(pGia, pObj), pObj, nWords, vSims ); + else if ( Gia_ObjIsAnd(pObj) ) + Gia_ManSimPatSimAnd( pGia, Gia_ObjId(pGia, pObj), pObj, nWords, vSims ); + else if ( !Gia_ObjIsCo(pObj) ) assert(0); +} +void Gia_ManSimPatWrite( char * pFileName, Vec_Wrd_t * vSimsIn, int nWords ) +{ + Vec_WrdDumpHex( pFileName, vSimsIn, nWords, 0 ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word * Gia_ManDeriveFuncs( Gia_Man_t * p ) +{ + int nVars2 = (Gia_ManCiNum(p) + 6)/2; + int nVars3 = Gia_ManCiNum(p) - nVars2; + int nWords = Abc_Truth6WordNum( Gia_ManCiNum(p) ); + int nWords2 = Abc_Truth6WordNum( nVars2 ); + word * pRes = ABC_ALLOC( word, Gia_ManCoNum(p) * nWords ); + Vec_Wrd_t * vSims = Vec_WrdStart( nWords2 * Gia_ManObjNum(p) ); + Vec_Ptr_t * vTruths = Vec_PtrAllocTruthTables( nVars2 ); + Gia_Obj_t * pObj; int i, v, m; + Gia_ManForEachCi( p, pObj, i ) + assert( Gia_ObjId(p, pObj) == i+1 ); + for ( i = 0; i < nVars2; i++ ) + Abc_TtCopy( Vec_WrdEntryP(vSims, nWords2*(i+1)), (word *)Vec_PtrEntry(vTruths, i), nWords2, 0 ); + Vec_PtrFree( vTruths ); + for ( m = 0; m < (1 << nVars3); m++ ) + { + for ( v = 0; v < nVars3; v++ ) + Abc_TtConst( Vec_WrdEntryP(vSims, nWords2*(nVars2+v+1)), nWords2, (m >> v) & 1 ); + Gia_ManForEachAnd( p, pObj, i ) + Gia_ManSimPatSimAnd( p, i, pObj, nWords2, vSims ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManSimPatSimPo( p, Gia_ObjId(p, pObj), pObj, nWords2, vSims ); + Gia_ManForEachCo( p, pObj, i ) + Abc_TtCopy( pRes + i*nWords + m*nWords2, Vec_WrdEntryP(vSims, nWords2*Gia_ObjId(p, pObj)), nWords2, 0 ); + } + Vec_WrdFree( vSims ); + return pRes; +} +Gia_Man_t * Gia_ManPerformMuxDec( Gia_Man_t * p ) +{ + extern int Gia_ManFindMuxTree_rec( Gia_Man_t * pNew, int * pCtrl, int nCtrl, Vec_Int_t * vData, int Shift ); + extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); + int nWords = Abc_Truth6WordNum( Gia_ManCiNum(p) ); + int nCofs = 1 << (Gia_ManCiNum(p) - 6); + word * pRes = Gia_ManDeriveFuncs( p ); + Vec_Int_t * vMemory = Vec_IntAlloc( 1 << 16 ); + Vec_Int_t * vLeaves = Vec_IntAlloc( 6 ); + Vec_Int_t * vCtrls = Vec_IntAlloc( nCofs ); + Vec_Int_t * vDatas = Vec_IntAlloc( Gia_ManCoNum(p) ); + Gia_Man_t * pNew, * pTemp; int i, o; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + Vec_IntPush( i < 6 ? vLeaves : vCtrls, Gia_ManAppendCi(pNew) ); + Gia_ManHashAlloc( pNew ); + for ( o = 0; o < Gia_ManCoNum(p); o++ ) + { + Vec_IntClear( vDatas ); + for ( i = 0; i < nWords; i++ ) + Vec_IntPush( vDatas, Kit_TruthToGia(pNew, (unsigned *)(pRes+o*nWords+i), 6, vMemory, vLeaves, 1) ); + Gia_ManAppendCo( pNew, Gia_ManFindMuxTree_rec(pNew, Vec_IntArray(vCtrls), Vec_IntSize(vCtrls), vDatas, 0) ); + } + Gia_ManHashStop( pNew ); + ABC_FREE( pRes ); + Vec_IntFree( vMemory ); + Vec_IntFree( vLeaves ); + Vec_IntFree( vCtrls ); + Vec_IntFree( vDatas ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Gia_ManTransferTiming( pNew, p ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManComputeTfos_rec( Gia_Man_t * p, int iObj, int iRoot, Vec_Int_t * vNode ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdPreviousId(p, iObj) ) + return 1; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return 0; + pObj = Gia_ManObj( p, iObj ); + if ( !Gia_ObjIsAnd(pObj) ) + return 0; + if ( Gia_ManComputeTfos_rec( p, Gia_ObjFaninId0(pObj, iObj), iRoot, vNode ) | + Gia_ManComputeTfos_rec( p, Gia_ObjFaninId1(pObj, iObj), iRoot, vNode ) ) + { + Gia_ObjSetTravIdPreviousId(p, iObj); + Vec_IntPush( vNode, iObj ); + return 1; + } + Gia_ObjSetTravIdCurrentId(p, iObj); + return 0; +} +Vec_Wec_t * Gia_ManComputeTfos( Gia_Man_t * p ) +{ + Vec_Wec_t * vNodes = Vec_WecStart( Gia_ManCiNum(p) ); + Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); + int i, o, IdCi, IdCo; + Gia_ManForEachCiId( p, IdCi, i ) + { + Vec_Int_t * vNode = Vec_WecEntry( vNodes, i ); + Gia_ManIncrementTravId( p ); + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdPreviousId(p, IdCi); + Vec_IntPush( vNode, IdCi ); + Vec_IntClear( vTemp ); + Gia_ManForEachCoId( p, IdCo, o ) + if ( Gia_ManComputeTfos_rec( p, Gia_ObjFaninId0(Gia_ManObj(p, IdCo), IdCo), IdCi, vNode ) ) + Vec_IntPush( vTemp, Gia_ManObjNum(p) + (o >> 1) ); + Vec_IntUniqify( vTemp ); + Vec_IntAppend( vNode, vTemp ); + } + Vec_IntFree( vTemp ); + Vec_WecSort( vNodes, 1 ); + //Vec_WecPrint( vNodes, 0 ); + //Gia_AigerWrite( p, "dump.aig", 0, 0, 0 ); + return vNodes; +} +int Gia_ManFindDividerVar( Gia_Man_t * p, int fVerbose ) +{ + int iVar, Target = 1 << 28; + for ( iVar = 6; iVar < Gia_ManCiNum(p); iVar++ ) + if ( (1 << (iVar-3)) * Gia_ManObjNum(p) > Target ) + break; + if ( iVar == Gia_ManCiNum(p) ) + iVar = Gia_ManCiNum(p) - 1; + if ( fVerbose ) + printf( "Split var = %d. Rounds = %d. Bytes per node = %d. Total = %.2f MB.\n", iVar, 1 << (Gia_ManCiNum(p) - iVar), 1 << (iVar-3), 1.0*(1 << (iVar-3)) * Gia_ManObjNum(p)/(1<<20) ); + return iVar; +} +int Gia_ManComparePair( Gia_Man_t * p, Vec_Wrd_t * vSims, int iOut, int nWords2 ) +{ + Gia_Obj_t * pObj0 = Gia_ManCo( p, 2*iOut+0 ); + Gia_Obj_t * pObj1 = Gia_ManCo( p, 2*iOut+1 ); + word * pSim0 = Vec_WrdEntryP( vSims, nWords2*Gia_ObjId(p, pObj0) ); + word * pSim1 = Vec_WrdEntryP( vSims, nWords2*Gia_ObjId(p, pObj1) ); + Gia_ManSimPatSimPo( p, Gia_ObjId(p, pObj0), pObj0, nWords2, vSims ); + Gia_ManSimPatSimPo( p, Gia_ObjId(p, pObj1), pObj1, nWords2, vSims ); + return Abc_TtEqual( pSim0, pSim1, nWords2 ); +} +int Gia_ManCheckSimEquiv( Gia_Man_t * p, int fVerbose ) +{ + abctime clk = Abc_Clock(); int fWarning = 0; + //int nVars2 = (Gia_ManCiNum(p) + 6)/2; + int nVars2 = Gia_ManFindDividerVar( p, fVerbose ); + int nVars3 = Gia_ManCiNum(p) - nVars2; + int nWords2 = Abc_Truth6WordNum( nVars2 ); + Vec_Wrd_t * vSims = Vec_WrdStart( nWords2 * Gia_ManObjNum(p) ); + Vec_Wec_t * vNodes = Gia_ManComputeTfos( p ); + Vec_Ptr_t * vTruths = Vec_PtrAllocTruthTables( nVars2 ); + Gia_Obj_t * pObj; Vec_Int_t * vNode; int i, m, iObj; + Vec_WecForEachLevelStop( vNodes, vNode, i, nVars2 ) + Abc_TtCopy( Vec_WrdEntryP(vSims, nWords2*Vec_IntEntry(vNode,0)), (word *)Vec_PtrEntry(vTruths, i), nWords2, 0 ); + Vec_PtrFree( vTruths ); + Gia_ManForEachAnd( p, pObj, i ) + Gia_ManSimPatSimAnd( p, i, pObj, nWords2, vSims ); + for ( i = 0; i < Gia_ManCoNum(p)/2; i++ ) + { + if ( !Gia_ManComparePair( p, vSims, i, nWords2 ) ) + { + printf( "Miter is asserted for output %d.\n", i ); + Vec_WecFree( vNodes ); + Vec_WrdFree( vSims ); + return 0; + } + } + for ( m = 0; m < (1 << nVars3); m++ ) + { + int iVar = m ? Abc_TtSuppFindFirst( m ^ (m >> 1) ^ (m-1) ^ ((m-1) >> 1) ) : 0; + vNode = Vec_WecEntry( vNodes, nVars2+iVar ); + Abc_TtNot( Vec_WrdEntryP(vSims, nWords2*Vec_IntEntry(vNode,0)), nWords2 ); + Vec_IntForEachEntryStart( vNode, iObj, i, 1 ) + { + if ( iObj < Gia_ManObjNum(p) ) + { + pObj = Gia_ManObj( p, iObj ); + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManSimPatSimAnd( p, iObj, pObj, nWords2, vSims ); + } + else if ( !Gia_ManComparePair( p, vSims, iObj - Gia_ManObjNum(p), nWords2 ) ) + { + printf( "Miter is asserted for output %d.\n", iObj - Gia_ManObjNum(p) ); + Vec_WecFree( vNodes ); + Vec_WrdFree( vSims ); + return 0; + } + } + //for ( i = 0; i < Gia_ManObjNum(p); i++ ) + // printf( "%3d : ", i), Extra_PrintHex2( stdout, (unsigned *)Vec_WrdEntryP(vSims, i), 6 ), printf( "\n" ); + if ( !fWarning && Abc_Clock() > clk + 5*CLOCKS_PER_SEC ) + printf( "The computation is expected to take about %.2f sec.\n", 5.0*(1 << nVars3)/m ), fWarning = 1; + //if ( (m & 0x3F) == 0x3F ) + if ( fVerbose && (m & 0xFF) == 0xFF ) + printf( "Finished %6d (out of %6d)...\n", m, 1 << nVars3 ); + } + Vec_WecFree( vNodes ); + Vec_WrdFree( vSims ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimPatAssignInputs2( Gia_Man_t * p, int nWords, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsIn ) +{ + int i, Id; + assert( Vec_WrdSize(vSims) == 2 * nWords * Gia_ManObjNum(p) ); + assert( Vec_WrdSize(vSimsIn) == nWords * Gia_ManCiNum(p) ); + Gia_ManForEachCiId( p, Id, i ) + { + Abc_TtCopy( Vec_WrdEntryP(vSims, 2*Id*nWords+0), Vec_WrdEntryP(vSimsIn, i*nWords), nWords, 0 ); + Abc_TtCopy( Vec_WrdEntryP(vSims, 2*Id*nWords+1), Vec_WrdEntryP(vSimsIn, i*nWords), nWords, 1 ); + } +} +static inline void Gia_ManSimPatSimAnd2( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims ) +{ + word * pSims = Vec_WrdArray(vSims); + word * pSims0 = pSims + nWords*Gia_ObjFaninLit0(pObj, i); + word * pSims1 = pSims + nWords*Gia_ObjFaninLit1(pObj, i); + word * pSims2 = pSims + nWords*(2*i+0); + word * pSims3 = pSims + nWords*(2*i+1); int w; + assert( !Gia_ObjIsXor(pObj) ); +// if ( Gia_ObjIsXor(pObj) ) +// for ( w = 0; w < nWords; w++ ) +// pSims2[w] = pSims0[w] ^ pSims1[w]; +// else + for ( w = 0; w < nWords; w++ ) + { + pSims2[w] = pSims0[w] & pSims1[w]; + pSims3[w] = ~pSims2[w]; + } + //_mm256_storeu_ps( (float *)pSims2, _mm256_and_ps(_mm256_loadu_ps((float *)pSims0), _mm256_loadu_ps((float *)pSims1)) ); +} +static inline void Gia_ManSimPatSimPo2( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims ) +{ + word * pSims = Vec_WrdArray(vSims); + word * pSims0 = pSims + nWords*Gia_ObjFaninLit0(pObj, i); + word * pSims2 = pSims + nWords*i; int w; + for ( w = 0; w < nWords; w++ ) + pSims2[w] = pSims0[w]; +} +Vec_Wrd_t * Gia_ManSimPatSim2( Gia_Man_t * pGia ) +{ + Gia_Obj_t * pObj; + int i, nWords = Vec_WrdSize(pGia->vSimsPi) / Gia_ManCiNum(pGia); + Vec_Wrd_t * vSims = Vec_WrdStart( Gia_ManObjNum(pGia) * nWords * 2 ); + assert( Vec_WrdSize(pGia->vSimsPi) % Gia_ManCiNum(pGia) == 0 ); + Gia_ManSimPatAssignInputs2( pGia, nWords, vSims, pGia->vSimsPi ); + Gia_ManForEachAnd( pGia, pObj, i ) + Gia_ManSimPatSimAnd2( pGia, i, pObj, nWords, vSims ); + Gia_ManForEachCo( pGia, pObj, i ) + Gia_ManSimPatSimPo2( pGia, Gia_ObjId(pGia, pObj), pObj, nWords, vSims ); + return vSims; +} /**Function************************************************************* @@ -248,7 +676,6 @@ Vec_Wrd_t * Gia_ManSimBitPacking( Gia_Man_t * p, Vec_Int_t * vCexStore, int nCex return vSimsRes; } - /**Function************************************************************* Synopsis [] @@ -306,87 +733,6 @@ Gia_Man_t * Gia_ManSimPatGenMiter( Gia_Man_t * p, Vec_Wrd_t * vSims ) } -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Gia_ManSimPatWriteOne( FILE * pFile, word * pSim, int nWords ) -{ - int k, Digit, nDigits = nWords*16; - for ( k = 0; k < nDigits; k++ ) - { - Digit = (int)((pSim[k/16] >> ((k%16) * 4)) & 15); - if ( Digit < 10 ) - fprintf( pFile, "%d", Digit ); - else - fprintf( pFile, "%c", 'A' + Digit-10 ); - } - fprintf( pFile, "\n" ); -} -void Gia_ManSimPatWrite( char * pFileName, Vec_Wrd_t * vSimsIn, int nWords ) -{ - int i, nNodes = Vec_WrdSize(vSimsIn) / nWords; - FILE * pFile = fopen( pFileName, "wb" ); - if ( pFile == NULL ) - { - printf( "Cannot open file \"%s\" for writing.\n", pFileName ); - return; - } - assert( Vec_WrdSize(vSimsIn) % nWords == 0 ); - for ( i = 0; i < nNodes; i++ ) - Gia_ManSimPatWriteOne( pFile, Vec_WrdEntryP(vSimsIn, i*nWords), nWords ); - fclose( pFile ); - printf( "Written %d words of simulation data into file \"%s\".\n", nWords, pFileName ); -} -int Gia_ManSimPatReadOne( char c ) -{ - int Digit = 0; - if ( c >= '0' && c <= '9' ) - Digit = c - '0'; - else if ( c >= 'A' && c <= 'F' ) - Digit = c - 'A' + 10; - else if ( c >= 'a' && c <= 'f' ) - Digit = c - 'a' + 10; - else assert( 0 ); - assert( Digit >= 0 && Digit < 16 ); - return Digit; -} -Vec_Wrd_t * Gia_ManSimPatRead( char * pFileName ) -{ - Vec_Wrd_t * vSimsIn = NULL; - int c, nWords = -1, nChars = 0; word Num = 0; - FILE * pFile = fopen( pFileName, "rb" ); - if ( pFile == NULL ) - { - printf( "Cannot open file \"%s\" for reading.\n", pFileName ); - return NULL; - } - vSimsIn = Vec_WrdAlloc( 1000 ); - while ( (c = fgetc(pFile)) != EOF ) - { - if ( c == '\n' && nWords == -1 ) - nWords = Vec_WrdSize(vSimsIn); - if ( c == '\n' || c == '\r' || c == '\t' || c == ' ' ) - continue; - Num |= (word)Gia_ManSimPatReadOne((char)c) << (nChars * 4); - if ( ++nChars < 16 ) - continue; - Vec_WrdPush( vSimsIn, Num ); - nChars = 0; - Num = 0; - } - assert( Vec_WrdSize(vSimsIn) % nWords == 0 ); - fclose( pFile ); - printf( "Read %d words of simulation data.\n", nWords ); - return vSimsIn; -} /**Function************************************************************* @@ -2029,6 +2375,331 @@ void Gia_ManPatRareImprove( Gia_Man_t * p, int RareLimit, int fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } +/**Function************************************************************* + + Synopsis [Trying vectorized simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimTest( Gia_Man_t * pGia ) +{ + int n, nWords = 4; + Vec_Wrd_t * vSim1, * vSim2; + Vec_Wrd_t * vSim0 = Vec_WrdStartRandom( Gia_ManCiNum(pGia) * nWords ); + abctime clk = Abc_Clock(); + + pGia->vSimsPi = vSim0; + for ( n = 0; n < 20; n++ ) + { + vSim1 = Gia_ManSimPatSim( pGia ); + Vec_WrdFree( vSim1 ); + } + Abc_PrintTime( 1, "Time1", Abc_Clock() - clk ); + + clk = Abc_Clock(); + for ( n = 0; n < 20; n++ ) + { + vSim2 = Gia_ManSimPatSim2( pGia ); + Vec_WrdFree( vSim2 ); + } + Abc_PrintTime( 1, "Time2", Abc_Clock() - clk ); + + pGia->vSimsPi = NULL; + Vec_WrdFree( vSim0 ); +} + +/**Function************************************************************* + + Synopsis [Trying compiled simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimGen( Gia_Man_t * pGia ) +{ + int nWords = 4; + Gia_Obj_t * pObj; + Vec_Wrd_t * vSim0 = Vec_WrdStartRandom( Gia_ManCiNum(pGia) * nWords ); + FILE * pFile = fopen( "comp_sim.c", "wb" ); + int i, k, Id; + fprintf( pFile, "#include <stdio.h>\n" ); + fprintf( pFile, "#include <stdlib.h>\n" ); + fprintf( pFile, "#include <time.h>\n" ); + fprintf( pFile, "int main()\n" ); + fprintf( pFile, "{\n" ); + fprintf( pFile, " clock_t clkThis = clock();\n" ); + fprintf( pFile, " unsigned long Res = 0;\n" ); + fprintf( pFile, " int i;\n" ); + fprintf( pFile, " srand(time(NULL));\n" ); + fprintf( pFile, " for ( i = 0; i < 2000; i++ )\n" ); + fprintf( pFile, " {\n" ); + for ( k = 0; k < nWords; k++ ) + fprintf( pFile, " unsigned long s%07d_%d = 0x%08x%08x;\n", 0, k, 0, 0 ); + Gia_ManForEachCiId( pGia, Id, i ) + { + //word * pSim = Vec_WrdEntryP(vSim0, i*nWords); + //unsigned * pSimU = (unsigned *)pSim; + for ( k = 0; k < nWords; k++ ) + fprintf( pFile, " unsigned long s%07d_%d = ((unsigned long)rand() << 48) | ((unsigned long)rand() << 32) | ((unsigned long)rand() << 16) | (unsigned long)rand();\n", Id, k ); + } + Gia_ManForEachAnd( pGia, pObj, Id ) + { + for ( k = 0; k < nWords; k++ ) + fprintf( pFile, " unsigned long s%07d_%d = %cs%07d_%d & %cs%07d_%d;\n", Id, k, + Gia_ObjFaninC0(pObj) ? '~' : ' ', Gia_ObjFaninId0(pObj, Id), k, + Gia_ObjFaninC1(pObj) ? ' ' : '~', Gia_ObjFaninId1(pObj, Id), k ); + } + Gia_ManForEachCoId( pGia, Id, i ) + { + pObj = Gia_ManObj(pGia, Id); + for ( k = 0; k < nWords; k++ ) + fprintf( pFile, " Res ^= %cs%07d_%d;\n", Gia_ObjFaninC0(pObj) ? '~' : ' ', Gia_ObjFaninId0(pObj, Id), k ); + } + Vec_WrdFree( vSim0 ); + fprintf( pFile, " }\n" ); + fprintf( pFile, " printf( \"Res = 0x%%08x \", (unsigned)Res );\n" ); + fprintf( pFile, " printf( \"Time = %%6.2f sec\\n\", (float)(clock() - clkThis)/CLOCKS_PER_SEC );\n" ); + fprintf( pFile, " return 1;\n" ); + fprintf( pFile, "}\n" ); + fclose( pFile ); +} + + +/**Function************************************************************* + + Synopsis [Trying vectorized simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSimTwo( Gia_Man_t * p0, Gia_Man_t * p1, int nWords, int nRounds, int fVerbose ) +{ + Vec_Wrd_t * vSim0, * vSim1, * vSim2; + abctime clk = Abc_Clock(); + int n, i, RetValue = 1; + printf( "Simulating %d round with %d machine words.\n", nRounds, nWords ); + Abc_RandomW(0); + for ( n = 0; RetValue && n < nRounds; n++ ) + { + vSim0 = Vec_WrdStartRandom( Gia_ManCiNum(p0) * nWords ); + p0->vSimsPi = vSim0; + p1->vSimsPi = vSim0; + vSim1 = Gia_ManSimPatSim( p0 ); + vSim2 = Gia_ManSimPatSim( p1 ); + for ( i = 0; i < Gia_ManCoNum(p0); i++ ) + { + word * pSim1 = Vec_WrdEntryP(vSim1, Gia_ObjId(p0, Gia_ManCo(p0, i))*nWords); + word * pSim2 = Vec_WrdEntryP(vSim2, Gia_ObjId(p1, Gia_ManCo(p1, i))*nWords); + if ( memcmp(pSim1, pSim2, sizeof(word)*nWords) ) + { + printf( "Output %d failed simulation at round %d. ", i, n ); + RetValue = 0; + break; + } + } + Vec_WrdFree( vSim1 ); + Vec_WrdFree( vSim2 ); + Vec_WrdFree( vSim0 ); + p0->vSimsPi = NULL; + p1->vSimsPi = NULL; + } + if ( RetValue == 1 ) + printf( "Simulation did not detect a bug. " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Serialization.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSim2ArrayOne( Vec_Wrd_t * vSimsPi, Vec_Int_t * vRes ) +{ + word * pInfo = Vec_WrdArray(vSimsPi); int w, i; + word * pCare = pInfo + Vec_WrdSize(vSimsPi); + Vec_IntClear( vRes ); + for ( w = 0; w < Vec_WrdSize(vSimsPi); w++ ) + if ( pCare[w] ) + for ( i = 0; i < 64; i++ ) + if ( Abc_TtGetBit(pCare, w*64+i) ) + Vec_IntPush( vRes, Abc_Var2Lit(w*64+i, Abc_TtGetBit(pInfo, w*64+i)) ); + Vec_IntPush( vRes, Vec_WrdSize(vSimsPi) ); +} +Vec_Wec_t * Gia_ManSim2Array( Vec_Ptr_t * vSims ) +{ + Vec_Wec_t * vRes = Vec_WecStart( Vec_PtrSize(vSims) ); + Vec_Int_t * vLevel; int i; + Vec_WecForEachLevel( vRes, vLevel, i ) + Gia_ManSim2ArrayOne( (Vec_Wrd_t *)Vec_PtrEntry(vSims, i), vLevel ); + return vRes; +} + +Vec_Wrd_t * Gia_ManArray2SimOne( Vec_Int_t * vRes ) +{ + int i, iLit, nWords = Vec_IntEntryLast(vRes); + Vec_Wrd_t * vSimsPi = Vec_WrdStart( 2*nWords ); + word * pInfo = Vec_WrdArray(vSimsPi); + word * pCare = pInfo + nWords; + Vec_IntPop( vRes ); + Vec_IntForEachEntry( vRes, iLit, i ) + { + Abc_TtXorBit( pCare, Abc_Lit2Var(iLit) ); + if ( Abc_LitIsCompl(iLit) ) + Abc_TtXorBit( pInfo, Abc_Lit2Var(iLit) ); + } + Vec_IntPush( vRes, nWords ); + Vec_WrdShrink( vSimsPi, Vec_WrdSize(vSimsPi)/2 ); + return vSimsPi; +} +Vec_Ptr_t * Gia_ManArray2Sim( Vec_Wec_t * vRes ) +{ + Vec_Ptr_t * vSims = Vec_PtrAlloc( Vec_WecSize(vRes) ); + Vec_Int_t * vLevel; int i; + Vec_WecForEachLevel( vRes, vLevel, i ) + Vec_PtrPush( vSims, Gia_ManArray2SimOne(vLevel) ); + return vSims; +} + +void Gia_ManSimArrayTest( Vec_Wrd_t * vSimsPi ) +{ + Vec_Ptr_t * vTemp = Vec_PtrAlloc( 2 ); + Vec_PtrPushTwo( vTemp, vSimsPi, vSimsPi ); + { + Vec_Wec_t * vRes = Gia_ManSim2Array( vTemp ); + Vec_WecDumpBin( "temp.sims", vRes, 1 ); + { + Vec_Wec_t * vRes = Vec_WecReadBin( "temp.sims", 1 ); + Vec_Ptr_t * vTemp2 = Gia_ManArray2Sim( vRes ); + Vec_Wrd_t * vSimsPi2 = (Vec_Wrd_t *)Vec_PtrEntry( vTemp2, 0 ); + Vec_Wrd_t * vSimsPi3 = (Vec_Wrd_t *)Vec_PtrEntry( vTemp2, 1 ); + + Abc_TtAnd( Vec_WrdArray(vSimsPi), Vec_WrdArray(vSimsPi), Vec_WrdArray(vSimsPi)+Vec_WrdSize(vSimsPi), Vec_WrdSize(vSimsPi), 0 ); + + vSimsPi->nSize *= 2; + vSimsPi2->nSize *= 2; + vSimsPi3->nSize *= 2; + Vec_WrdDumpHex( "test1.hex", vSimsPi, 1, 1 ); + Vec_WrdDumpHex( "test2.hex", vSimsPi2, 1, 1 ); + Vec_WrdDumpHex( "test3.hex", vSimsPi3, 1, 1 ); + vSimsPi->nSize /= 2; + vSimsPi2->nSize /= 2; + vSimsPi3->nSize /= 2; + + if ( Vec_WrdEqual( vSimsPi, vSimsPi2 ) ) + printf( "Success.\n" ); + else + printf( "Failure.\n" ); + if ( Vec_WrdEqual( vSimsPi, vSimsPi3 ) ) + printf( "Success.\n" ); + else + printf( "Failure.\n" ); + Vec_WrdFree( vSimsPi2 ); + Vec_WrdFree( vSimsPi3 ); + Vec_PtrFree( vTemp2 ); + Vec_WecFree( vRes ); + } + Vec_WecFree( vRes ); + } + Vec_PtrFree( vTemp ); +} + + +/**Function************************************************************* + + Synopsis [Serialization.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPtrWrdDumpBin( char * pFileName, Vec_Ptr_t * p, int fVerbose ) +{ + Vec_Wrd_t * vLevel; + int i, nSize, RetValue; + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + return; + } + nSize = Vec_PtrSize(p); + RetValue = fwrite( &nSize, 1, sizeof(int), pFile ); + Vec_PtrForEachEntry( Vec_Wrd_t *, p, vLevel, i ) + { + nSize = Vec_WrdSize(vLevel); + RetValue += fwrite( &nSize, 1, sizeof(int), pFile ); + RetValue += fwrite( Vec_WrdArray(vLevel), 1, sizeof(word)*nSize, pFile ); + } + fclose( pFile ); + if ( fVerbose ) + printf( "Written %d arrays into file \"%s\".\n", Vec_PtrSize(p), pFileName ); +} +Vec_Ptr_t * Gia_ManPtrWrdReadBin( char * pFileName, int fVerbose ) +{ + Vec_Ptr_t * p = NULL; Vec_Wrd_t * vLevel; int i, nSize, RetValue; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return NULL; + } + fseek( pFile, 0, SEEK_END ); + nSize = ftell( pFile ); + if ( nSize == 0 ) + { + printf( "The input file is empty.\n" ); + fclose( pFile ); + return NULL; + } + if ( nSize % (int)sizeof(int) > 0 ) + { + printf( "Cannot read file with integers because it is not aligned at 4 bytes (remainder = %d).\n", nSize % (int)sizeof(int) ); + fclose( pFile ); + return NULL; + } + rewind( pFile ); + RetValue = fread( &nSize, 1, sizeof(int), pFile ); + assert( RetValue == 4 ); + p = Vec_PtrAlloc( nSize ); + for ( i = 0; i < nSize; i++ ) + Vec_PtrPush( p, Vec_WrdAlloc(100) ); + Vec_PtrForEachEntry( Vec_Wrd_t *, p, vLevel, i ) + { + RetValue = fread( &nSize, 1, sizeof(int), pFile ); + assert( RetValue == 4 ); + Vec_WrdFill( vLevel, nSize, 0 ); + RetValue = fread( Vec_WrdArray(vLevel), 1, sizeof(word)*nSize, pFile ); + assert( RetValue == 8*nSize ); + } + fclose( pFile ); + if ( fVerbose ) + printf( "Read %d arrays from file \"%s\".\n", Vec_PtrSize(p), pFileName ); + return p; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaStoch.c b/src/aig/gia/giaStoch.c new file mode 100644 index 00000000..94f53998 --- /dev/null +++ b/src/aig/gia/giaStoch.c @@ -0,0 +1,448 @@ +/**CFile**************************************************************** + + FileName [giaDeep.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Experiments with synthesis.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaDeep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "base/main/main.h" +#include "base/cmd/cmd.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupMapping( Gia_Man_t * pNew, Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pFanin; int i, k; + Vec_Int_t * vMapping = p->vMapping ? Vec_IntAlloc( Vec_IntSize(p->vMapping) ) : NULL; + if ( p->vMapping == NULL ) + return; + Vec_IntFill( vMapping, Gia_ManObjNum(p), 0 ); + Gia_ManForEachLut( p, i ) + { + pObj = Gia_ManObj( p, i ); + Vec_IntWriteEntry( vMapping, Abc_Lit2Var(pObj->Value), Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Gia_ObjLutSize(p, i) ); + Gia_LutForEachFaninObj( p, i, pFanin, k ) + Vec_IntPush( vMapping, Abc_Lit2Var(pFanin->Value) ); + Vec_IntPush( vMapping, Abc_Lit2Var(pObj->Value) ); + } + pNew->vMapping = vMapping; +} +Gia_Man_t * Gia_ManDupWithMapping( Gia_Man_t * pGia ) +{ + Gia_Man_t * pCopy = Gia_ManDup(pGia); + Gia_ManDupMapping( pCopy, pGia ); + return pCopy; +} +void Gia_ManStochSynthesis( Vec_Ptr_t * vAigs, char * pScript ) +{ + Gia_Man_t * pGia, * pNew; int i; + Vec_PtrForEachEntry( Gia_Man_t *, vAigs, pGia, i ) + { + Gia_Man_t * pCopy = Gia_ManDupWithMapping(pGia); + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pGia ); + if ( Abc_FrameIsBatchMode() ) + { + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + return; + } + } + else + { + Abc_FrameSetBatchMode( 1 ); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + Abc_FrameSetBatchMode( 0 ); + return; + } + Abc_FrameSetBatchMode( 0 ); + } + pNew = Abc_FrameReadGia(Abc_FrameGetGlobalFrame()); + if ( Gia_ManHasMapping(pNew) && Gia_ManHasMapping(pCopy) ) + { + if ( Gia_ManLutNum(pNew) < Gia_ManLutNum(pCopy) ) + { + Gia_ManStop( pCopy ); + pCopy = Gia_ManDupWithMapping( pNew ); + } + } + else + { + if ( Gia_ManAndNum(pNew) < Gia_ManAndNum(pCopy) ) + { + Gia_ManStop( pCopy ); + pCopy = Gia_ManDup( pNew ); + } + } + Vec_PtrWriteEntry( vAigs, i, pCopy ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCollectNodes_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vAnds ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjUpdateTravIdCurrentId( p, iObj ) ) + return; + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) || iObj == 0 ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManCollectNodes_rec( p, Gia_ObjFaninId0(pObj, iObj), vAnds ); + Gia_ManCollectNodes_rec( p, Gia_ObjFaninId1(pObj, iObj), vAnds ); + Vec_IntPush( vAnds, iObj ); +} +void Gia_ManCollectNodes( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos ) +{ + int i, iObj; + if ( !Gia_ManHasMapping(p) ) + return; + Vec_IntClear( vAnds ); + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vCis, iObj, i ) + Gia_ObjSetTravIdCurrentId( p, iObj ); + Vec_IntForEachEntry( vCos, iObj, i ) + Gia_ManCollectNodes_rec( p, iObj, vAnds ); +} +Gia_Man_t * Gia_ManDupDivideOne( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos ) +{ + Vec_Int_t * vMapping; int i; + Gia_Man_t * pNew; Gia_Obj_t * pObj; + pNew = Gia_ManStart( 1+Vec_IntSize(vCis)+Vec_IntSize(vAnds)+Vec_IntSize(vCos) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObjVec( vCis, p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObjVec( vAnds, p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachObjVec( vCos, p, pObj, i ) + Gia_ManAppendCo( pNew, pObj->Value ); + assert( Gia_ManCiNum(pNew) > 0 && Gia_ManCoNum(pNew) > 0 ); + if ( !Gia_ManHasMapping(p) ) + return pNew; + vMapping = Vec_IntAlloc( 4*Gia_ManObjNum(pNew) ); + Vec_IntFill( vMapping, Gia_ManObjNum(pNew), 0 ); + Gia_ManForEachObjVec( vAnds, p, pObj, i ) + { + Gia_Obj_t * pFanin; int k; + int iObj = Gia_ObjId(p, pObj); + if ( !Gia_ObjIsLut(p, iObj) ) + continue; + Vec_IntWriteEntry( vMapping, Abc_Lit2Var(pObj->Value), Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Gia_ObjLutSize(p, iObj) ); + Gia_LutForEachFaninObj( p, iObj, pFanin, k ) + Vec_IntPush( vMapping, Abc_Lit2Var(pFanin->Value) ); + Vec_IntPush( vMapping, Abc_Lit2Var(pObj->Value) ); + } + pNew->vMapping = vMapping; + return pNew; +} +Vec_Ptr_t * Gia_ManDupDivide( Gia_Man_t * p, Vec_Wec_t * vCis, Vec_Wec_t * vAnds, Vec_Wec_t * vCos, char * pScript ) +{ + Vec_Ptr_t * vAigs = Vec_PtrAlloc( Vec_WecSize(vCis) ); int i; + for ( i = 0; i < Vec_WecSize(vCis); i++ ) + { + Gia_ManCollectNodes( p, Vec_WecEntry(vCis, i), Vec_WecEntry(vAnds, i), Vec_WecEntry(vCos, i) ); + Vec_PtrPush( vAigs, Gia_ManDupDivideOne(p, Vec_WecEntry(vCis, i), Vec_WecEntry(vAnds, i), Vec_WecEntry(vCos, i)) ); + } + Gia_ManStochSynthesis( vAigs, pScript ); + return vAigs; +} +Gia_Man_t * Gia_ManDupStitch( Gia_Man_t * p, Vec_Wec_t * vCis, Vec_Wec_t * vAnds, Vec_Wec_t * vCos, Vec_Ptr_t * vAigs, int fHash ) +{ + Gia_Man_t * pGia, * pNew; + Gia_Obj_t * pObj; int i, k; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManCleanValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + if ( fHash ) + Gia_ManHashAlloc( pNew ); + Vec_PtrForEachEntry( Gia_Man_t *, vAigs, pGia, i ) + { + Vec_Int_t * vCi = Vec_WecEntry( vCis, i ); + Vec_Int_t * vCo = Vec_WecEntry( vCos, i ); + Gia_ManCleanValue( pGia ); + Gia_ManConst0(pGia)->Value = 0; + Gia_ManForEachObjVec( vCi, p, pObj, k ) + Gia_ManCi(pGia, k)->Value = pObj->Value; + if ( fHash ) + Gia_ManForEachAnd( pGia, pObj, k ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + Gia_ManForEachAnd( pGia, pObj, k ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachObjVec( vCo, p, pObj, k ) + pObj->Value = Gia_ObjFanin0Copy(Gia_ManCo(pGia, k)); + } + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + if ( fHash ) + { + pNew = Gia_ManCleanup( pGia = pNew ); + Gia_ManStop( pGia ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} +Gia_Man_t * Gia_ManDupStitchMap( Gia_Man_t * p, Vec_Wec_t * vCis, Vec_Wec_t * vAnds, Vec_Wec_t * vCos, Vec_Ptr_t * vAigs ) +{ + Vec_Int_t * vMapping; int n; + Gia_Man_t * pGia, * pNew = Gia_ManDupStitch( p, vCis, vAnds, vCos, vAigs, !Gia_ManHasMapping(p) ); + if ( !Gia_ManHasMapping(p) ) + return pNew; + vMapping = Vec_IntAlloc( Vec_IntSize(p->vMapping) ); + Vec_IntFill( vMapping, Gia_ManObjNum(pNew), 0 ); + Vec_PtrForEachEntry( Gia_Man_t *, vAigs, pGia, n ) + { + Gia_Obj_t * pFanin; int iObj, k; + //printf( "Gia %d has %d Luts\n", n, Gia_ManLutNum(pGia) ); + + Gia_ManForEachLut( pGia, iObj ) + { + Gia_Obj_t * pObj = Gia_ManObj( pGia, iObj ); + Vec_IntWriteEntry( vMapping, Abc_Lit2Var(pObj->Value), Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Gia_ObjLutSize(pGia, iObj) ); + Gia_LutForEachFaninObj( pGia, iObj, pFanin, k ) + Vec_IntPush( vMapping, Abc_Lit2Var(pFanin->Value) ); + Vec_IntPush( vMapping, Abc_Lit2Var(pObj->Value) ); + } + } + pNew->vMapping = vMapping; + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManStochNodes( Gia_Man_t * p, int nMaxSize, int Seed ) +{ + Vec_Wec_t * vRes = Vec_WecAlloc( 100 ); + Vec_Int_t * vPart = Vec_WecPushLevel( vRes ); + int i, iStart = Seed % Gia_ManCoNum(p); + //Gia_ManLevelNum( p ); + Gia_ManIncrementTravId( p ); + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + { + Gia_Obj_t * pObj = Gia_ManCo( p, (iStart+i) % Gia_ManCoNum(p) ); + if ( Vec_IntSize(vPart) > nMaxSize ) + vPart = Vec_WecPushLevel( vRes ); + Gia_ManCollectNodes_rec( p, Gia_ObjFaninId0p(p, pObj), vPart ); + } + if ( Vec_IntSize(vPart) == 0 ) + Vec_WecShrink( vRes, Vec_WecSize(vRes)-1 ); + //Vec_WecPrint( vRes, 0 ); + return vRes; +} +Vec_Wec_t * Gia_ManStochInputs( Gia_Man_t * p, Vec_Wec_t * vAnds ) +{ + Vec_Wec_t * vRes = Vec_WecAlloc( 100 ); + Vec_Int_t * vLevel; Gia_Obj_t * pObj; int i, k, iObj, iFan, f; + Vec_WecForEachLevel( vAnds, vLevel, i ) + { + Vec_Int_t * vVec = Vec_WecPushLevel( vRes ); + assert( Vec_IntSize(vVec) == 0 ); + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vLevel, iObj, k ) + Gia_ObjSetTravIdCurrentId( p, iObj ); + if ( Gia_ManHasMapping(p) ) + { + Vec_IntForEachEntry( vLevel, iObj, k ) + if ( Gia_ObjIsLut(p, iObj) ) + Gia_LutForEachFanin( p, iObj, iFan, f ) + if ( !Gia_ObjUpdateTravIdCurrentId(p, iFan) ) + Vec_IntPush( vVec, iFan ); + } + else + { + Gia_ManForEachObjVec( vLevel, p, pObj, k ) + { + iObj = Gia_ObjFaninId0p(p, pObj); + if ( !Gia_ObjUpdateTravIdCurrentId(p, iObj) ) + Vec_IntPush( vVec, iObj ); + iObj = Gia_ObjFaninId1p(p, pObj); + if ( !Gia_ObjUpdateTravIdCurrentId(p, iObj) ) + Vec_IntPush( vVec, iObj ); + } + } + assert( Vec_IntSize(vVec) > 0 ); + } + return vRes; +} +Vec_Wec_t * Gia_ManStochOutputs( Gia_Man_t * p, Vec_Wec_t * vAnds ) +{ + Vec_Wec_t * vRes = Vec_WecAlloc( 100 ); + Vec_Int_t * vLevel; Gia_Obj_t * pObj; int i, k, iObj, iFan, f; + if ( Gia_ManHasMapping(p) ) + { + Gia_ManSetLutRefs( p ); + Vec_WecForEachLevel( vAnds, vLevel, i ) + { + Vec_Int_t * vVec = Vec_WecPushLevel( vRes ); + assert( Vec_IntSize(vVec) == 0 ); + Vec_IntForEachEntry( vLevel, iObj, k ) + if ( Gia_ObjIsLut(p, iObj) ) + Gia_LutForEachFanin( p, iObj, iFan, f ) + Gia_ObjLutRefDecId( p, iFan ); + Vec_IntForEachEntry( vLevel, iObj, k ) + if ( Gia_ObjIsLut(p, iObj) ) + if ( Gia_ObjLutRefNumId(p, iObj) ) + Vec_IntPush( vVec, iObj ); + Vec_IntForEachEntry( vLevel, iObj, k ) + if ( Gia_ObjIsLut(p, iObj) ) + Gia_LutForEachFanin( p, iObj, iFan, f ) + Gia_ObjLutRefIncId( p, iFan ); + assert( Vec_IntSize(vVec) > 0 ); + } + } + else + { + Gia_ManCreateRefs( p ); + Vec_WecForEachLevel( vAnds, vLevel, i ) + { + Vec_Int_t * vVec = Vec_WecPushLevel( vRes ); + Gia_ManForEachObjVec( vLevel, p, pObj, k ) + { + Gia_ObjRefDecId( p, Gia_ObjFaninId0p(p, pObj) ); + Gia_ObjRefDecId( p, Gia_ObjFaninId1p(p, pObj) ); + } + Gia_ManForEachObjVec( vLevel, p, pObj, k ) + if ( Gia_ObjRefNum(p, pObj) ) + Vec_IntPush( vVec, Gia_ObjId(p, pObj) ); + Gia_ManForEachObjVec( vLevel, p, pObj, k ) + { + Gia_ObjRefIncId( p, Gia_ObjFaninId0p(p, pObj) ); + Gia_ObjRefIncId( p, Gia_ObjFaninId1p(p, pObj) ); + } + } + } + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManStochSyn( int nMaxSize, int nIters, int TimeOut, int Seed, int fVerbose, char * pScript ) +{ + abctime nTimeToStop = TimeOut ? Abc_Clock() + TimeOut * CLOCKS_PER_SEC : 0; + abctime clkStart = Abc_Clock(); + int fMapped = Gia_ManHasMapping(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())); + int nLutEnd, nLutBeg = fMapped ? Gia_ManLutNum(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())) : 0; + int i, nEnd, nBeg = Gia_ManAndNum(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())); + Abc_Random(1); + for ( i = 0; i < 10+Seed; i++ ) + Abc_Random(0); + if ( fVerbose ) + printf( "Running %d iterations of script \"%s\".\n", nIters, pScript ); + for ( i = 0; i < nIters; i++ ) + { + abctime clk = Abc_Clock(); + Gia_Man_t * pGia = Gia_ManDupWithMapping( Abc_FrameReadGia(Abc_FrameGetGlobalFrame()) ); + Vec_Wec_t * vAnds = Gia_ManStochNodes( pGia, nMaxSize, Abc_Random(0) & 0x7FFFFFFF ); + Vec_Wec_t * vIns = Gia_ManStochInputs( pGia, vAnds ); + Vec_Wec_t * vOuts = Gia_ManStochOutputs( pGia, vAnds ); + Vec_Ptr_t * vAigs = Gia_ManDupDivide( pGia, vIns, vAnds, vOuts, pScript ); + Gia_Man_t * pNew = Gia_ManDupStitchMap( pGia, vIns, vAnds, vOuts, vAigs ); + int fMapped = Gia_ManHasMapping(pGia) && Gia_ManHasMapping(pNew); + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew ); + if ( fVerbose ) + printf( "Iteration %3d : Using %3d partitions. Reducing %6d to %6d %s. ", + i, Vec_PtrSize(vAigs), fMapped ? Gia_ManLutNum(pGia) : Gia_ManAndNum(pGia), + fMapped ? Gia_ManLutNum(pNew) : Gia_ManAndNum(pNew), + fMapped ? "LUTs" : "ANDs" ); + if ( fVerbose ) + Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); + Gia_ManStop( pGia ); + Vec_PtrFreeFunc( vAigs, (void (*)(void *)) Gia_ManStop ); + Vec_WecFree( vAnds ); + Vec_WecFree( vIns ); + Vec_WecFree( vOuts ); + if ( nTimeToStop && Abc_Clock() > nTimeToStop ) + { + printf( "Runtime limit (%d sec) is reached after %d iterations.\n", TimeOut, i ); + break; + } + } + fMapped &= Gia_ManHasMapping(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())); + nLutEnd = fMapped ? Gia_ManLutNum(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())) : 0; + nEnd = Gia_ManAndNum(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())); + if ( fVerbose ) + printf( "Cumulatively reduced %d %s after %d iterations. ", + fMapped ? nLutBeg - nLutEnd : nBeg - nEnd, fMapped ? "LUTs" : "ANDs", nIters ); + if ( fVerbose ) + Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/gia/giaStr.c b/src/aig/gia/giaStr.c index 085738c3..a87662a8 100644 --- a/src/aig/gia/giaStr.c +++ b/src/aig/gia/giaStr.c @@ -736,7 +736,7 @@ Str_Ntk_t * Str_ManNormalizeInt( Gia_Man_t * p, Vec_Wec_t * vGroups, Vec_Int_t * if ( p->vStore == NULL ) p->vStore = Vec_IntAlloc( STR_SUPER ); Gia_ManFillValue( p ); - pNtk = Str_NtkCreate( Gia_ManObjNum(p), 1 + Gia_ManCoNum(p) + 2 * Gia_ManAndNum(p) + Gia_ManMuxNum(p) ); + pNtk = Str_NtkCreate( Gia_ManObjNum(p) + 10000, 1 + Gia_ManCoNum(p) + 2 * Gia_ManAndNum(p) + Gia_ManMuxNum(p) + 10000 ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachObj1( p, pObj, i ) { @@ -749,7 +749,7 @@ Str_Ntk_t * Str_ManNormalizeInt( Gia_Man_t * p, Vec_Wec_t * vGroups, Vec_Int_t * pObj->Value = Str_ObjCreate( pNtk, STR_PO, 1, &iFanin ); } } - assert( pNtk->nObjs <= Gia_ManObjNum(p) ); + //assert( pNtk->nObjs <= Gia_ManObjNum(p) ); return pNtk; } Str_Ntk_t * Str_ManNormalize( Gia_Man_t * p ) @@ -859,21 +859,23 @@ static inline void transpose64( word A[64] ) static inline int Str_ManNum( Gia_Man_t * p, int iObj ) { return Vec_IntEntry(&p->vCopies, iObj); } static inline void Str_ManSetNum( Gia_Man_t * p, int iObj, int Num ) { Vec_IntWriteEntry(&p->vCopies, iObj, Num); } -int Str_ManVectorAffinity( Gia_Man_t * p, Vec_Int_t * vSuper, Vec_Int_t * vDelay, word Matrix[256], int nLimit ) +int Str_ManVectorAffinity( Gia_Man_t * p, Vec_Int_t * vSuper, Vec_Int_t * vDelay, word * Matrix, int nLimit ) { int fVerbose = 0; - int Levels[256]; + int * Levels = NULL; int nSize = Vec_IntSize(vSuper); int Prev = nSize, nLevels = 1; int i, k, iLit, iFanin, nSizeNew; word Mask; assert( nSize > 2 ); + assert( nSize <= nLimit ); if ( nSize > 64 ) { for ( i = 0; i < 64; i++ ) Matrix[i] = 0; return 0; } + Levels = ABC_ALLOC( int, nLimit+256 ); // mark current nodes Gia_ManIncrementTravId( p ); Vec_IntForEachEntry( vSuper, iLit, i ) @@ -948,6 +950,7 @@ int Str_ManVectorAffinity( Gia_Man_t * p, Vec_Int_t * vSuper, Vec_Int_t * vDelay if ( nSizeNew == 0 ) { Vec_IntShrink( vSuper, nSize ); + ABC_FREE( Levels ); return 0; } /* @@ -979,6 +982,7 @@ int Str_ManVectorAffinity( Gia_Man_t * p, Vec_Int_t * vSuper, Vec_Int_t * vDelay } i = 0; } + ABC_FREE( Levels ); Vec_IntShrink( vSuper, nSize ); return nSizeNew; } @@ -1088,15 +1092,14 @@ int Str_NtkBalanceTwo( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, int i, void Str_NtkBalanceMulti( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec_Int_t * vDelay, int nLutSize ) { - word pMatrix[256]; - int Limit = 256; + word * pMatrix = ABC_ALLOC( word, pObj->nFanins+256 ); Vec_Int_t * vSuper = pNew->vSuper; Vec_Int_t * vCosts = pNew->vStore; int * pSuper = Vec_IntArray(vSuper); int * pCost = Vec_IntArray(vCosts); int k, iLit, MatrixSize = 0; - assert( Limit <= Vec_IntCap(vSuper) ); - assert( Limit <= Vec_IntCap(vCosts) ); + assert( (int)pObj->nFanins <= Vec_IntCap(vSuper) ); + assert( (int)pObj->nFanins <= Vec_IntCap(vCosts) ); // collect nodes Vec_IntClear( vSuper ); @@ -1111,11 +1114,13 @@ void Str_NtkBalanceMulti( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec if ( Vec_IntSize(vSuper) == 1 ) { pObj->iCopy = Vec_IntEntry(vSuper, 0); + ABC_FREE( pMatrix ); return; } if ( Vec_IntSize(vSuper) == 2 ) { pObj->iCopy = Str_NtkBalanceTwo( pNew, p, pObj, 0, 1, vDelay, pCost, pSuper, pMatrix, 2, nLutSize, -1 ); + ABC_FREE( pMatrix ); return; } @@ -1127,7 +1132,7 @@ void Str_NtkBalanceMulti( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec // compute affinity if ( Vec_IntSize(vSuper) < 64 ) - MatrixSize = Str_ManVectorAffinity( pNew, vSuper, vCosts, pMatrix, Limit ); + MatrixSize = Str_ManVectorAffinity( pNew, vSuper, vCosts, pMatrix, pObj->nFanins ); // start the new product while ( Vec_IntSize(vSuper) > 2 ) @@ -1147,7 +1152,7 @@ void Str_NtkBalanceMulti( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec // compute affinity if ( Vec_IntSize(vSuper) == 64 ) - MatrixSize = Str_ManVectorAffinity( pNew, vSuper, vCosts, pMatrix, Limit ); + MatrixSize = Str_ManVectorAffinity( pNew, vSuper, vCosts, pMatrix, pObj->nFanins ); assert( Vec_IntSize(vSuper) <= 64 ); // Str_PrintState( pCost, pSuper, pMatrix, Vec_IntSize(vSuper) ); @@ -1236,6 +1241,7 @@ void Str_NtkBalanceMulti( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec continue; } pObj->iCopy = Str_NtkBalanceTwo( pNew, p, pObj, 0, 1, vDelay, pCost, pSuper, pMatrix, 2, nLutSize, -1 ); + ABC_FREE( pMatrix ); /* // simple diff --git a/src/aig/gia/giaSupps.c b/src/aig/gia/giaSupps.c new file mode 100644 index 00000000..f95d815d --- /dev/null +++ b/src/aig/gia/giaSupps.c @@ -0,0 +1,817 @@ +/**CFile**************************************************************** + + FileName [giaSupp.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Support computation manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSupp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig/gia/gia.h" +#include "base/main/mainInt.h" +#include "misc/util/utilTruth.h" +#include "misc/extra/extra.h" +#include "misc/vec/vecHsh.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Supp_Man_t_ Supp_Man_t; +struct Supp_Man_t_ +{ + // user data + int nIters; // optimization rounds + int nRounds; // optimization rounds + int nWords; // the number of simulation words + int nDivWords; // the number of divisor words + Vec_Wrd_t * vIsfs; // functions to synthesize + Vec_Int_t * vCands; // candidate divisors + Vec_Int_t * vWeights; // divisor weights (optional) + Vec_Wrd_t * vSims; // simulation values + Vec_Wrd_t * vSimsC; // simulation values + Gia_Man_t * pGia; // used for object names + // computed data + Vec_Wrd_t * vDivs[2]; // simulation values + Vec_Wrd_t * vPats[2]; // simulation values + Vec_Ptr_t * vMatrix; // simulation values + Vec_Wrd_t * vMask; // simulation values + Vec_Wrd_t * vRowTemp; // simulation values + Vec_Int_t * vCosts; // candidate costs + Hsh_VecMan_t * pHash; // subsets considered + Vec_Wrd_t * vSFuncs; // ISF storage + Vec_Int_t * vSStarts; // subset function starts + Vec_Int_t * vSCount; // subset function count + Vec_Int_t * vSPairs; // subset pair count + Vec_Int_t * vTemp; // temporary + Vec_Int_t * vTempSets; // temporary + Vec_Int_t * vTempPairs; // temporary + Vec_Wec_t * vSolutions; // solutions for each node count +}; + +extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Supp_ManFuncInit( Vec_Wrd_t * vFuncs, int nWords ) +{ + int i, k = 0, nFuncs = Vec_WrdSize(vFuncs) / nWords / 2; + assert( 2 * nFuncs * nWords == Vec_WrdSize(vFuncs) ); + for ( i = 0; i < nFuncs; i++ ) + { + word * pFunc0 = Vec_WrdEntryP(vFuncs, (2*i+0)*nWords); + word * pFunc1 = Vec_WrdEntryP(vFuncs, (2*i+1)*nWords); + if ( Abc_TtIsConst0(pFunc0, nWords) || Abc_TtIsConst0(pFunc1, nWords) ) + continue; + if ( k < i ) Abc_TtCopy( Vec_WrdEntryP(vFuncs, (2*k+0)*nWords), pFunc0, nWords, 0 ); + if ( k < i ) Abc_TtCopy( Vec_WrdEntryP(vFuncs, (2*k+1)*nWords), pFunc1, nWords, 0 ); + k++; + } + Vec_WrdShrink( vFuncs, 2*k*nWords ); + return k; +} +int Supp_ManCostInit( Vec_Wrd_t * vFuncs, int nWords ) +{ + int Res = 0, i, nFuncs = Vec_WrdSize(vFuncs) / nWords / 2; + assert( 2 * nFuncs * nWords == Vec_WrdSize(vFuncs) ); + for ( i = 0; i < nFuncs; i++ ) + { + word * pFunc0 = Vec_WrdEntryP(vFuncs, (2*i+0)*nWords); + word * pFunc1 = Vec_WrdEntryP(vFuncs, (2*i+1)*nWords); + Res += Abc_TtCountOnesVec(pFunc0, nWords) * Abc_TtCountOnesVec(pFunc1, nWords); + } + assert( nFuncs < 128 ); + assert( Res < (1 << 24) ); + return (nFuncs << 24) | Res; +} +void Supp_ManInit( Supp_Man_t * p ) +{ + int Value, nFuncs, iSet = Hsh_VecManAdd( p->pHash, p->vTemp ); // empty set + assert( iSet == 0 ); + Vec_IntPush( p->vSStarts, Vec_WrdSize(p->vSFuncs) ); + Vec_WrdAppend( p->vSFuncs, p->vIsfs ); + nFuncs = Supp_ManFuncInit( p->vSFuncs, p->nWords ); + assert( Vec_WrdSize(p->vSFuncs) == 2 * nFuncs * p->nWords ); + Value = Supp_ManCostInit(p->vSFuncs, p->nWords); + Vec_IntPush( p->vSCount, Value >> 24 ); + Vec_IntPush( p->vSPairs, Value & 0xFFFFFF ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Supp_DeriveLines( Supp_Man_t * p ) +{ + int n, i, iObj, nWords = p->nWords; + int nDivWords = Abc_Bit6WordNum( Vec_IntSize(p->vCands) ); + for ( n = 0; n < 2; n++ ) + { + p->vDivs[n] = Vec_WrdStart( 64*nWords*nDivWords ); + p->vPats[n] = Vec_WrdStart( 64*nWords*nDivWords ); + if ( p->vSimsC ) + Vec_IntForEachEntry( p->vCands, iObj, i ) + Abc_TtAndSharp( Vec_WrdEntryP(p->vDivs[n], i*nWords), Vec_WrdEntryP(p->vSimsC, iObj*nWords), Vec_WrdEntryP(p->vSims, iObj*nWords), nWords, !n ); + else + Vec_IntForEachEntry( p->vCands, iObj, i ) + Abc_TtCopy( Vec_WrdEntryP(p->vDivs[n], i*nWords), Vec_WrdEntryP(p->vSims, iObj*nWords), nWords, !n ); + Extra_BitMatrixTransposeP( p->vDivs[n], nWords, p->vPats[n], nDivWords ); + } + return nDivWords; +} +Supp_Man_t * Supp_ManCreate( Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vWeights, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsC, int nWords, Gia_Man_t * pGia, int nIters, int nRounds ) +{ + Supp_Man_t * p = ABC_CALLOC( Supp_Man_t, 1 ); + p->nIters = nIters; + p->nRounds = nRounds; + p->nWords = nWords; + p->vIsfs = vIsfs; + p->vCands = vCands; + p->vWeights = vWeights; + p->vSims = vSims; + p->vSimsC = vSimsC; + p->pGia = pGia; + // computed data + p->nDivWords = Supp_DeriveLines( p ); + p->vMatrix = Vec_PtrAlloc( 100 ); + p->vMask = Vec_WrdAlloc( 100 ); + p->vRowTemp = Vec_WrdStart( 64*p->nDivWords ); + p->vCosts = Vec_IntStart( Vec_IntSize(p->vCands) ); + p->pHash = Hsh_VecManStart( 1000 ); + p->vSFuncs = Vec_WrdAlloc( 1000 ); + p->vSStarts = Vec_IntAlloc( 1000 ); + p->vSCount = Vec_IntAlloc( 1000 ); + p->vSPairs = Vec_IntAlloc( 1000 ); + p->vSolutions = Vec_WecStart( 16 ); + p->vTemp = Vec_IntAlloc( 10 ); + p->vTempSets = Vec_IntAlloc( 10 ); + p->vTempPairs = Vec_IntAlloc( 10 ); + Supp_ManInit( p ); + return p; +} +void Supp_ManCleanMatrix( Supp_Man_t * p ) +{ + Vec_Wrd_t * vTemp; int i; + Vec_PtrForEachEntry( Vec_Wrd_t *, p->vMatrix, vTemp, i ) + Vec_WrdFreeP( &vTemp ); + Vec_PtrClear( p->vMatrix ); +} +void Supp_ManDelete( Supp_Man_t * p ) +{ + Supp_ManCleanMatrix( p ); + Vec_WrdFreeP( &p->vDivs[0] ); + Vec_WrdFreeP( &p->vDivs[1] ); + Vec_WrdFreeP( &p->vPats[0] ); + Vec_WrdFreeP( &p->vPats[1] ); + Vec_PtrFreeP( &p->vMatrix ); + Vec_WrdFreeP( &p->vMask ); + Vec_WrdFreeP( &p->vRowTemp ); + Vec_IntFreeP( &p->vCosts ); + Hsh_VecManStop( p->pHash ); + Vec_WrdFreeP( &p->vSFuncs ); + Vec_IntFreeP( &p->vSStarts ); + Vec_IntFreeP( &p->vSCount ); + Vec_IntFreeP( &p->vSPairs ); + Vec_WecFreeP( &p->vSolutions ); + Vec_IntFreeP( &p->vTemp ); + Vec_IntFreeP( &p->vTempSets ); + Vec_IntFreeP( &p->vTempPairs ); + ABC_FREE( p ); +} +int Supp_ManMemory( Supp_Man_t * p ) +{ + int nMem = sizeof(Supp_Man_t); + nMem += 2*(int)Vec_WrdMemory( p->vDivs[0] ); + nMem += 2*(int)Vec_WrdMemory( p->vPats[0] ); + nMem += (Vec_PtrSize(p->vMatrix)+1)*(int)Vec_WrdMemory( p->vRowTemp ); + nMem += (int)Vec_WrdMemory( p->vMask ); + nMem += (int)Vec_IntMemory( p->vCosts ); + nMem += (int)Hsh_VecManMemory( p->pHash ); + nMem += (int)Vec_WrdMemory( p->vSFuncs ); + nMem += (int)Vec_IntMemory( p->vSStarts ); + nMem += (int)Vec_IntMemory( p->vSCount ); + nMem += (int)Vec_IntMemory( p->vSPairs ); + nMem += (int)Vec_WecMemory( p->vSolutions ); + nMem += (int)Vec_IntMemory( p->vTemp ); + nMem += (int)Vec_IntMemory( p->vTempSets ); + nMem += (int)Vec_IntMemory( p->vTempPairs ); + return nMem; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Supp_ArrayWeight( Vec_Int_t * vRes, Vec_Int_t * vWeights ) +{ + int i, iObj, Cost = 0; + if ( !vWeights ) + return Vec_IntSize(vRes); + Vec_IntForEachEntry( vRes, iObj, i ) + Cost += Vec_IntEntry(vWeights, iObj); + return Cost; +} +int Supp_SetWeight( Supp_Man_t * p, int iSet ) +{ + return Supp_ArrayWeight( Hsh_VecReadEntry(p->pHash, iSet), p->vWeights ); +} +int Supp_SetSize( Supp_Man_t * p, int iSet ) +{ + return Vec_IntSize( Hsh_VecReadEntry(p->pHash, iSet) ); +} +int Supp_SetFuncNum( Supp_Man_t * p, int iSet ) +{ + return Vec_IntEntry(p->vSCount, iSet); +} +int Supp_SetPairNum( Supp_Man_t * p, int iSet ) +{ + return Vec_IntEntry(p->vSPairs, iSet); +} +void Supp_SetConvert( Vec_Int_t * vSet, Vec_Int_t * vCands ) +{ + int i, iObj; + Vec_IntForEachEntry( vSet, iObj, i ) + Vec_IntWriteEntry( vSet, i, Vec_IntEntry(vCands, iObj) ); +} +void Supp_PrintNodes( Gia_Man_t * pGia, Vec_Int_t * vObjs, int Skip, int Limit ) +{ + int i, iObj; + //printf( "Considering %d targets: ", Vec_IntSize(vObjs) ); + Vec_IntForEachEntryStart( vObjs, iObj, i, Skip ) + { + if ( iObj < 0 ) + continue; + printf( "(%d)", iObj ); + if ( pGia && pGia->vWeights && Vec_IntEntry(pGia->vWeights, iObj) > 0 ) + printf( "(%d)", Vec_IntEntry(pGia->vWeights, iObj) ); + if ( pGia ) + printf( " %s ", Gia_ObjName(pGia, iObj)+2 ); + else + printf( " n%d ", iObj ); + if ( i >= Limit ) + { + printf( "... " ); + break; + } + } + printf( "Cost = %d", Supp_ArrayWeight(vObjs, pGia ? pGia->vWeights : NULL) ); + printf( "\n" ); +} +void Supp_PrintOne( Supp_Man_t * p, int iSet ) +{ + Vec_Int_t * vSet = Hsh_VecReadEntry(p->pHash, iSet); + printf( "Set %5d : ", iSet ); + printf( "Funcs %2d ", Supp_SetFuncNum(p, iSet) ); + printf( "Pairs %4d ", Supp_SetPairNum(p, iSet) ); + printf( "Start %8d ", Vec_IntEntry(p->vSStarts, iSet) ); + printf( "Weight %4d ", Supp_ArrayWeight(vSet, p->vWeights) ); + Vec_IntClearAppend( p->vTemp, vSet ); + Supp_SetConvert( p->vTemp, p->vCands ); + Supp_PrintNodes( p->pGia, p->vTemp, 0, 6 ); +} +int Supp_ManRefine1( Supp_Man_t * p, int iSet, int iObj ) +{ + word * pSet = Vec_WrdEntryP( p->vSims, Vec_IntEntry(p->vCands, iObj)*p->nWords ); + word * pIsf; int nFuncs = Vec_IntEntry(p->vSCount, iSet); + int i, n, f, w, nFuncsNew = 0, Mark = Vec_WrdSize(p->vSFuncs), Res = 0; + if ( Vec_WrdSize(p->vSFuncs) + 4*nFuncs*p->nWords > Vec_WrdCap(p->vSFuncs) ) + Vec_WrdGrow( p->vSFuncs, 2*Vec_WrdCap(p->vSFuncs) ); + pIsf = Vec_WrdEntryP( p->vSFuncs, Vec_IntEntry(p->vSStarts, iSet) ); + for ( i = 0; i < nFuncs; i++ ) + { + word * pFunc[2] = { pIsf + (2*i+0)*p->nWords, pIsf + (2*i+1)*p->nWords }; + for ( f = 0; f < 2; f++ ) + { + int nOnes[2], Start = Vec_WrdSize(p->vSFuncs); + for ( n = 0; n < 2; n++ ) + { + word * pLimit = Vec_WrdLimit(p->vSFuncs); + if ( f ) + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[n][w] & pSet[w] ); + else + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[n][w] & ~pSet[w] ); + nOnes[n] = Abc_TtCountOnesVec( pLimit, p->nWords ); + } + if ( nOnes[0] && nOnes[1] ) + Res += nOnes[0] * nOnes[1]; + else + Vec_WrdShrink( p->vSFuncs, Start ); + } + } + assert( Res < (1 << 24) ); + nFuncsNew = (Vec_WrdSize(p->vSFuncs) - Mark)/2/p->nWords; + assert( nFuncsNew < 128 ); + assert( nFuncsNew >= 0 && nFuncsNew <= 2*nFuncs ); + return (nFuncsNew << 24) | Res; +} +void Supp_ManRefine( Supp_Man_t * p, int iSet, int iObj, int * pnFuncs, int * pnPairs ) +{ + word * pDivs0 = Vec_WrdEntryP( p->vDivs[0], iObj*p->nWords ); + word * pDivs1 = Vec_WrdEntryP( p->vDivs[1], iObj*p->nWords ); + word * pIsf; int nFuncs = Supp_SetFuncNum(p, iSet); + int i, f, w, nFuncsNew = 0, Mark = Vec_WrdSize(p->vSFuncs), Res = 0; + if ( Vec_WrdSize(p->vSFuncs) + 6*nFuncs*p->nWords > Vec_WrdCap(p->vSFuncs) ) + Vec_WrdGrow( p->vSFuncs, 2*Vec_WrdCap(p->vSFuncs) ); + if ( Vec_WrdSize(p->vSFuncs) == Vec_IntEntry(p->vSStarts, iSet) ) + pIsf = Vec_WrdLimit( p->vSFuncs ); + else + pIsf = Vec_WrdEntryP( p->vSFuncs, Vec_IntEntry(p->vSStarts, iSet) ); + for ( i = 0; i < nFuncs; i++ ) + { + word * pFunc[2] = { pIsf + (2*i+0)*p->nWords, pIsf + (2*i+1)*p->nWords }; + for ( f = 0; f < 3; f++ ) + { + int nOnes[2], Start = Vec_WrdSize(p->vSFuncs); + word * pLimit[2] = { Vec_WrdLimit(p->vSFuncs), Vec_WrdLimit(p->vSFuncs) + p->nWords }; + if ( f == 0 ) + { + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[0][w] & pDivs0[w] ); + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[1][w] & ~pDivs1[w] ); + } + else if ( f == 1 ) + { + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[0][w] & pDivs1[w] ); + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[1][w] & ~pDivs0[w] ); + } + else + { + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[0][w] & ~pDivs0[w] & ~pDivs1[w] ); + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[1][w] ); + } + nOnes[0] = Abc_TtCountOnesVec( pLimit[0], p->nWords ); + nOnes[1] = Abc_TtCountOnesVec( pLimit[1], p->nWords ); + if ( nOnes[0] && nOnes[1] ) + Res += nOnes[0] * nOnes[1]; + else + Vec_WrdShrink( p->vSFuncs, Start ); + } + } + assert( Res < (1 << 24) ); + nFuncsNew = (Vec_WrdSize(p->vSFuncs) - Mark)/2/p->nWords; + *pnFuncs = nFuncsNew; + *pnPairs = Res; +} +int Supp_ManSubsetAdd( Supp_Man_t * p, int iSet, int iObj, int fVerbose ) +{ + int iSetNew, nEntries = Hsh_VecSize( p->pHash ); + Vec_Int_t * vSet = Hsh_VecReadEntry( p->pHash, iSet ); + Vec_IntClear( p->vTemp ); + Vec_IntAppend( p->vTemp, vSet ); + Vec_IntPushOrder( p->vTemp, iObj ); + assert( Vec_IntIsOrdered(p->vTemp, 0) ); + iSetNew = Hsh_VecManAdd( p->pHash, p->vTemp ); + if ( iSetNew == nEntries ) // new entry + { + int nFuncs, nPairs; + Vec_IntPush( p->vSStarts, Vec_WrdSize(p->vSFuncs) ); + Supp_ManRefine( p, iSet, iObj, &nFuncs, &nPairs ); + Vec_IntPush( p->vSCount, nFuncs ); + Vec_IntPush( p->vSPairs, nPairs ); + assert( Hsh_VecSize(p->pHash) == Vec_IntSize(p->vSStarts) ); + assert( Hsh_VecSize(p->pHash) == Vec_IntSize(p->vSCount) ); + assert( Hsh_VecSize(p->pHash) == Vec_IntSize(p->vSPairs) ); + if ( Supp_SetFuncNum(p, iSetNew) == 0 && Supp_SetSize(p, iSetNew) < Vec_WecSize(p->vSolutions) ) + Vec_WecPush( p->vSolutions, Supp_SetSize(p, iSetNew), iSetNew ); + if ( fVerbose ) + Supp_PrintOne( p, iSetNew ); + } + return iSetNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Supp_ComputePair1( Supp_Man_t * p, int iSet ) +{ + int Random = 0xFFFFFF & Abc_Random(0); + int nFuncs = Vec_IntEntry(p->vSCount, iSet); + int iFunc = Random % nFuncs; + word * pIsf = Vec_WrdEntryP( p->vSFuncs, Vec_IntEntry(p->vSStarts, iSet) ); + word * pFunc[2] = { pIsf + (2*iFunc+0)*p->nWords, pIsf + (2*iFunc+1)*p->nWords }; + int iBit0 = ((Random >> 16) & 1) ? Abc_TtFindFirstBit2(pFunc[0], p->nWords) : Abc_TtFindLastBit2(pFunc[0], p->nWords); + int iBit1 = ((Random >> 17) & 1) ? Abc_TtFindFirstBit2(pFunc[1], p->nWords) : Abc_TtFindLastBit2(pFunc[1], p->nWords); + if ( 1 ) + { + Vec_Int_t * vSet = Hsh_VecReadEntry( p->pHash, iSet ); int i, iObj; + Vec_IntForEachEntry( vSet, iObj, i ) + { + word * pSet = Vec_WrdEntryP( p->vSims, Vec_IntEntry(p->vCands, iObj)*p->nWords ); + assert( Abc_TtGetBit(pSet, iBit0) == Abc_TtGetBit(pSet, iBit1) ); + } + } + return (iBit0 << 16) | iBit1; +} +int Supp_ComputePair( Supp_Man_t * p, int iSet ) +{ + int Random = 0xFFFFFF & Abc_Random(0); + int nFuncs = Vec_IntEntry(p->vSCount, iSet); + int iFunc = Random % nFuncs; + word * pIsf = Vec_WrdEntryP( p->vSFuncs, Vec_IntEntry(p->vSStarts, iSet) ); + word * pFunc[2] = { pIsf + (2*iFunc+0)*p->nWords, pIsf + (2*iFunc+1)*p->nWords }; + int iBit0 = ((Random >> 16) & 1) ? Abc_TtFindFirstBit2(pFunc[0], p->nWords) : Abc_TtFindLastBit2(pFunc[0], p->nWords); + int iBit1 = ((Random >> 17) & 1) ? Abc_TtFindFirstBit2(pFunc[1], p->nWords) : Abc_TtFindLastBit2(pFunc[1], p->nWords); + if ( 1 ) + { + Vec_Int_t * vSet = Hsh_VecReadEntry( p->pHash, iSet ); int i, iObj; + Vec_IntForEachEntry( vSet, iObj, i ) + { + word * pSet0 = Vec_WrdEntryP( p->vDivs[0], iObj*p->nWords ); + word * pSet1 = Vec_WrdEntryP( p->vDivs[1], iObj*p->nWords ); + int Value00 = Abc_TtGetBit(pSet0, iBit0); + int Value01 = Abc_TtGetBit(pSet0, iBit1); + int Value10 = Abc_TtGetBit(pSet1, iBit0); + int Value11 = Abc_TtGetBit(pSet1, iBit1); + assert( !Value00 || !Value11 ); + assert( !Value01 || !Value10 ); + } + } + return (iBit0 << 16) | iBit1; +} +Vec_Int_t * Supp_Compute64Pairs( Supp_Man_t * p, Vec_Int_t * vSets ) +{ + int i; + Vec_IntClear( p->vTempPairs ); + for ( i = 0; i < 64; i++ ) + { + int Rand = 0xFFFFFF & Abc_Random(0); + int iSet = Vec_IntEntry( vSets, Rand % Vec_IntSize(vSets) ); + Vec_IntPush( p->vTempPairs, Supp_ComputePair(p, iSet) ); + } + return p->vTempPairs; +} +void Supp_ManFillBlock( Supp_Man_t * p, Vec_Int_t * vPairs, Vec_Wrd_t * vRes ) +{ + int i, Pair; + assert( Vec_IntSize(vPairs) == 64 ); + Vec_IntForEachEntry( vPairs, Pair, i ) + { + int iBit0 = Pair >> 16, iBit1 = Pair & 0xFFFF; + word * pPat00 = Vec_WrdEntryP(p->vPats[0], iBit0*p->nDivWords); + word * pPat01 = Vec_WrdEntryP(p->vPats[0], iBit1*p->nDivWords); + word * pPat10 = Vec_WrdEntryP(p->vPats[1], iBit0*p->nDivWords); + word * pPat11 = Vec_WrdEntryP(p->vPats[1], iBit1*p->nDivWords); + word * pPat = Vec_WrdEntryP(p->vRowTemp, i*p->nDivWords); + Abc_TtAnd( pPat, pPat00, pPat11, p->nDivWords, 0 ); + Abc_TtOrAnd( pPat, pPat01, pPat10, p->nDivWords ); + } + Extra_BitMatrixTransposeP( p->vRowTemp, p->nDivWords, vRes, 1 ); +} +void Supp_ManAddPatterns( Supp_Man_t * p, Vec_Int_t * vSets ) +{ + Vec_Int_t * vPairs = Supp_Compute64Pairs( p, vSets ); + Vec_Wrd_t * vRow = Vec_WrdStart( 64*p->nDivWords ); + Supp_ManFillBlock( p, vPairs, vRow ); + Vec_PtrPush( p->vMatrix, vRow ); +} +Vec_Int_t * Supp_ManCollectOnes( word * pSim, int nWords ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); int i; + for ( i = 0; i < 64*nWords; i++ ) + if ( Abc_TtGetBit(pSim, i) ) + Vec_IntPush( vRes, i ); + return vRes; +} +Vec_Int_t * Supp_Compute64PairsFunc( Supp_Man_t * p, Vec_Int_t * vBits0, Vec_Int_t * vBits1 ) +{ + int i; + Vec_IntClear( p->vTempPairs ); + for ( i = 0; i < 64; i++ ) + { + int Random = 0xFFFFFF & Abc_Random(0); + int iBit0 = Vec_IntEntry( vBits0, (Random & 0xFFF) % Vec_IntSize(vBits0) ); + int iBit1 = Vec_IntEntry( vBits1, (Random >> 12) % Vec_IntSize(vBits1) ); + Vec_IntPush( p->vTempPairs, (iBit0 << 16) | iBit1 ); + } + return p->vTempPairs; +} +void Supp_ManAddPatternsFunc( Supp_Man_t * p, int nBatches ) +{ + int b; + Vec_Int_t * vBits0 = Supp_ManCollectOnes( Vec_WrdEntryP(p->vSFuncs, 0*p->nWords), p->nWords ); + Vec_Int_t * vBits1 = Supp_ManCollectOnes( Vec_WrdEntryP(p->vSFuncs, 1*p->nWords), p->nWords ); + for ( b = 0; b < nBatches; b++ ) + { + Vec_Int_t * vPairs = Supp_Compute64PairsFunc( p, vBits0, vBits1 ); + Vec_Wrd_t * vRow = Vec_WrdStart( 64*p->nDivWords ); + Supp_ManFillBlock( p, vPairs, vRow ); + Vec_PtrPush( p->vMatrix, vRow ); + } + Vec_IntFree( vBits0 ); + Vec_IntFree( vBits1 ); +} +int Supp_FindNextDiv( Supp_Man_t * p, int Pair ) +{ + int iDiv, iBit0 = Pair >> 16, iBit1 = Pair & 0xFFFF; + word * pPat00 = Vec_WrdEntryP(p->vPats[0], iBit0*p->nDivWords); + word * pPat01 = Vec_WrdEntryP(p->vPats[0], iBit1*p->nDivWords); + word * pPat10 = Vec_WrdEntryP(p->vPats[1], iBit0*p->nDivWords); + word * pPat11 = Vec_WrdEntryP(p->vPats[1], iBit1*p->nDivWords); + int iDiv1 = Abc_TtFindFirstAndBit2( pPat00, pPat11, p->nDivWords ); + int iDiv2 = Abc_TtFindFirstAndBit2( pPat01, pPat10, p->nDivWords ); + iDiv1 = iDiv1 == -1 ? ABC_INFINITY : iDiv1; + iDiv2 = iDiv2 == -1 ? ABC_INFINITY : iDiv2; + iDiv = Abc_MinInt( iDiv1, iDiv2 ); + assert( iDiv >= 0 && iDiv < Vec_IntSize(p->vCands) ); + return iDiv; +} +int Supp_ManRandomSolution( Supp_Man_t * p, int iSet, int fVerbose ) +{ + Vec_IntClear( p->vTempSets ); + while ( Supp_SetFuncNum(p, iSet) > 0 ) + { + int Pair = Supp_ComputePair( p, iSet ); + int iDiv = Supp_FindNextDiv( p, Pair ); + iSet = Supp_ManSubsetAdd( p, iSet, iDiv, fVerbose ); + if ( Supp_SetFuncNum(p, iSet) > 0 ) + Vec_IntPush( p->vTempSets, iSet ); + } + if ( Vec_IntSize(p->vTempSets) < 2 ) + return iSet; + Supp_ManAddPatterns( p, p->vTempSets ); + return iSet; +} +int Supp_ManSubsetRemove( Supp_Man_t * p, int iSet, int iPos ) +{ + int i, iSetNew = 0, nSize = Supp_SetSize(p, iSet); + for ( i = 0; i < nSize; i++ ) + if ( i != iPos && Supp_SetFuncNum(p, iSetNew) > 0 ) + iSetNew = Supp_ManSubsetAdd( p, iSetNew, Vec_IntEntry(Hsh_VecReadEntry(p->pHash, iSet), i), 0 ); + return iSetNew; +} +int Supp_ManMinimize( Supp_Man_t * p, int iSet0, int r, int fVerbose ) +{ + int i, nSize = Supp_SetSize(p, iSet0); + Vec_Int_t * vPerm = Vec_IntStartNatural( Supp_SetSize(p, iSet0) ); + Vec_IntRandomizeOrder( vPerm ); + Vec_IntClear( p->vTempSets ); + if ( fVerbose ) + printf( "Removing items from %d:\n", iSet0 ); + // make sure we first try to remove items with higher weight + for ( i = 0; i < nSize; i++ ) + { + int Index = Vec_IntEntry( vPerm, i ); + int iSet = Supp_ManSubsetRemove( p, iSet0, Index ); + if ( fVerbose ) + printf( "Item %2d : ", Index ); + if ( fVerbose ) + Supp_PrintOne( p, iSet ); + if ( Supp_SetFuncNum(p, iSet) == 0 ) + { + Vec_IntFree( vPerm ); + return Supp_ManMinimize( p, iSet, r, fVerbose ); + } + Vec_IntPush( p->vTempSets, iSet ); + } + Supp_ManAddPatterns( p, p->vTempSets ); + Vec_IntFree( vPerm ); + return iSet0; +} +int Supp_ManFindNextObj( Supp_Man_t * p, int fVerbose ) +{ + Vec_Wrd_t * vTemp; int r, k, iDiv; + word Sim, * pMask = Vec_WrdArray(p->vMask); + assert( Vec_WrdSize(p->vMask) == Vec_PtrSize(p->vMatrix) ); + Vec_IntFill( p->vCosts, Vec_IntSize(p->vCosts), 0 ); + Vec_PtrForEachEntry( Vec_Wrd_t *, p->vMatrix, vTemp, r ) + Vec_WrdForEachEntryStop( vTemp, Sim, k, Vec_IntSize(p->vCosts) ) + Vec_IntAddToEntry( p->vCosts, k, Abc_TtCountOnes(Sim & pMask[r]) ); + iDiv = Vec_IntArgMax( p->vCosts ); + if ( fVerbose ) + printf( "Choosing divisor %d with weight %d.\n", iDiv, Vec_IntEntry(p->vCosts, iDiv) ); + Vec_PtrForEachEntry( Vec_Wrd_t *, p->vMatrix, vTemp, r ) + pMask[r] &= ~Vec_WrdEntry( vTemp, iDiv ); + return iDiv; +} +int Supp_ManReconstruct( Supp_Man_t * p, int fVerbose ) +{ + int iSet = 0; + Vec_WrdFill( p->vMask, Vec_PtrSize(p->vMatrix), ~(word)0 ); + if ( fVerbose ) + printf( "\nBuilding a new set:\n" ); + while ( Supp_SetPairNum(p, iSet) ) + { + int iDiv = Supp_ManFindNextObj( p, fVerbose ); + iSet = Supp_ManSubsetAdd( p, iSet, iDiv, fVerbose ); + if ( Abc_TtIsConst0(Vec_WrdArray(p->vMask), Vec_WrdSize(p->vMask)) ) + break; + } + if ( fVerbose ) + printf( "Adding random part:\n" ); + return Supp_ManRandomSolution( p, iSet, fVerbose ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Supp_ManFindBestSolution( Supp_Man_t * p, Vec_Wec_t * vSols, int fVerbose, Vec_Int_t ** pvDivs ) +{ + Vec_Int_t * vLevel, * vRes = NULL; + int i, k, iSet, nFuncs = 0, Count = 0; + int iSolBest = -1, Cost, CostBest = ABC_INFINITY; + Vec_WecForEachLevel( vSols, vLevel, i ) + { + Count += Vec_IntSize(vLevel) > 0; + Vec_IntForEachEntry( vLevel, iSet, k ) + { + if ( fVerbose ) + printf( "%3d : ", nFuncs++ ); + Cost = Gia_ManEvalSolutionOne( p->pGia, p->vSims, p->vIsfs, p->vCands, Hsh_VecReadEntry(p->pHash, iSet), p->nWords, fVerbose ); + if ( Cost == -1 ) + continue; + if ( CostBest > Cost ) + { + CostBest = Cost; + iSolBest = iSet; + } + if ( nFuncs > 5 ) + break; + } + if ( Count == 2 || k < Vec_IntSize(vLevel) ) + break; + } + if ( iSolBest > 0 && (CostBest >> 2) < 50 ) + { + Vec_Int_t * vSet = Hsh_VecReadEntry( p->pHash, iSolBest ); int i, iObj; + vRes = Gia_ManDeriveSolutionOne( p->pGia, p->vSims, p->vIsfs, p->vCands, vSet, p->nWords, CostBest & 3 ); + assert( !vRes || Vec_IntSize(vRes) == 2*(CostBest >> 2)+1 ); + if ( vRes && pvDivs ) + { + Vec_IntClear( *pvDivs ); + Vec_IntPushTwo( *pvDivs, -1, -1 ); + Vec_IntForEachEntry( vSet, iObj, i ) + Vec_IntPush( *pvDivs, Vec_IntEntry(p->vCands, iObj) ); + } + } + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Supp_FindGivenOne( Supp_Man_t * p ) +{ + int i, iObj, iSet = 0; + Vec_Int_t * vSet = Vec_IntStart( 2 ); + //extern void Patch_GenerateSet11( Gia_Man_t * p, Vec_Int_t * vDivs, Vec_Int_t * vCands ); + //Patch_GenerateSet11( p->pGia, vSet, p->vCands ); + Vec_IntDrop( vSet, 0 ); + Vec_IntDrop( vSet, 0 ); + Vec_IntForEachEntry( vSet, iObj, i ) + iSet = Supp_ManSubsetAdd( p, iSet, iObj, 1 ); + Vec_IntFree( vSet ); + return iSet; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Supp_ManCompute( Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vWeights, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsC, int nWords, Gia_Man_t * pGia, Vec_Int_t ** pvDivs, int nIters, int nRounds, int fVerbose ) +{ + int fVeryVerbose = 0; + int i, r, iSet, iBest = -1; + abctime clk = Abc_Clock(); + Vec_Int_t * vRes = NULL; + Supp_Man_t * p = Supp_ManCreate( vIsfs, vCands, vWeights, vSims, vSimsC, nWords, pGia, nIters, nRounds ); + if ( Supp_SetFuncNum(p, 0) == 0 ) + { + Supp_ManDelete( p ); + Vec_IntClear( *pvDivs ); + Vec_IntPushTwo( *pvDivs, -1, -1 ); + vRes = Vec_IntAlloc( 1 ); + Vec_IntPush( vRes, Abc_TtIsConst0(Vec_WrdArray(vIsfs), nWords) ); + return vRes; + } + if ( fVerbose ) + printf( "\nUsing %d divisors with %d words. Problem has %d functions and %d minterm pairs.\n", + Vec_IntSize(p->vCands), p->nWords, Supp_SetFuncNum(p, 0), Supp_SetPairNum(p, 0) ); + //iBest = Supp_FindGivenOne( p ); + if ( iBest == -1 ) + for ( i = 0; i < p->nIters; i++ ) + { + Supp_ManAddPatternsFunc( p, i ); + iSet = Supp_ManRandomSolution( p, 0, fVeryVerbose ); + for ( r = 0; r < p->nRounds; r++ ) + { + if ( fVeryVerbose ) + printf( "\n\nITER %d ROUND %d\n", i, r ); + iSet = Supp_ManMinimize( p, iSet, r, fVeryVerbose ); + if ( iBest == -1 || Supp_SetWeight(p, iBest) > Supp_SetWeight(p, iSet) ) + //if ( Supp_SetSize(p, iBest) > Supp_SetSize(p, iSet) ) + { + if ( fVeryVerbose ) + printf( "\nThe best solution found:\n" ); + if ( fVeryVerbose ) + Supp_PrintOne( p, iSet ); + iBest = iSet; + } + iSet = Supp_ManReconstruct( p, fVeryVerbose ); + } + if ( fVeryVerbose ) + printf( "Matrix size %d.\n", Vec_PtrSize(p->vMatrix) ); + Supp_ManCleanMatrix( p ); + } + if ( fVerbose ) + { + printf( "Explored %d divisor sets. Found %d solutions. Memory usage %.2f MB. ", + Hsh_VecSize(p->pHash), Vec_WecSizeSize(p->vSolutions), 1.0*Supp_ManMemory(p)/(1<<20) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + printf( "The best solution: " ); + if ( iBest == -1 ) + printf( "No solution.\n" ); + else + Supp_PrintOne( p, iBest ); + } + vRes = Supp_ManFindBestSolution( p, p->vSolutions, fVerbose, pvDivs ); + Supp_ManDelete( p ); +// if ( vRes && Vec_IntSize(vRes) == 0 ) +// Vec_IntFreeP( &vRes ); + return vRes; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/gia/giaSweep.c b/src/aig/gia/giaSweep.c index 1d66caee..8a7fcbd0 100644 --- a/src/aig/gia/giaSweep.c +++ b/src/aig/gia/giaSweep.c @@ -388,6 +388,14 @@ Vec_Int_t * Gia_ManComputeCarryOuts( Gia_Man_t * p ) Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; int i, iLast, iBox, nBoxes = Tim_ManBoxNum( pManTime ); Vec_Int_t * vCarryOuts = Vec_IntAlloc( nBoxes ); + + // Create and populate reference count (and free later) only if not already + // done. + int createRefs = (p->pRefs == NULL); + if (createRefs) { + Gia_ManCreateRefs( p ); + } + for ( i = 0; i < nBoxes; i++ ) { iLast = Tim_ManBoxInputLast( pManTime, i ); @@ -398,9 +406,24 @@ Vec_Int_t * Gia_ManComputeCarryOuts( Gia_Man_t * p ) if ( iBox == -1 ) continue; assert( Gia_ObjIsCi(pObj) ); - if ( Gia_ObjCioId(pObj) == Tim_ManBoxOutputLast(pManTime, iBox) ) + if ( Gia_ObjCioId(pObj) == Tim_ManBoxOutputLast(pManTime, iBox) ) { Vec_IntPush( vCarryOuts, Gia_ObjId(p, pObj) ); + + // We have identified a carry connection. Check if the carry out + // of the destination box is unconnected. If so then add it to + // the carry list as well. + iLast = Tim_ManBoxOutputLast(pManTime, i); + pObj = Gia_ManCi(p, iLast); + if ( Gia_ObjRefNum(p, pObj) == 0 ) { + Vec_IntPush( vCarryOuts, Gia_ObjId(p, pObj) ); + } + } + } + + if (createRefs) { + ABC_FREE( p->pRefs ); } + return vCarryOuts; } diff --git a/src/aig/gia/giaTruth.c b/src/aig/gia/giaTruth.c index 91c4fa24..c24748ed 100644 --- a/src/aig/gia/giaTruth.c +++ b/src/aig/gia/giaTruth.c @@ -118,27 +118,6 @@ word Gia_LutComputeTruth6Map( Gia_Man_t * p, int iPo, Vec_Int_t * vMap ) SeeAlso [] ***********************************************************************/ -static unsigned s_Truths5[5] = { - 0xAAAAAAAA, - 0xCCCCCCCC, - 0xF0F0F0F0, - 0xFF00FF00, - 0xFFFF0000, -}; -static inline int Abc_Tt5HasVar( unsigned t, int iVar ) -{ - return ((t << (1<<iVar)) & s_Truths5[iVar]) != (t & s_Truths5[iVar]); -} -static inline unsigned Abc_Tt5Cofactor0( unsigned t, int iVar ) -{ - assert( iVar >= 0 && iVar < 6 ); - return (t & ~s_Truths5[iVar]) | ((t & ~s_Truths5[iVar]) << (1<<iVar)); -} -static inline unsigned Abc_Tt5Cofactor1( unsigned t, int iVar ) -{ - assert( iVar >= 0 && iVar < 6 ); - return (t & s_Truths5[iVar]) | ((t & s_Truths5[iVar]) >> (1<<iVar)); -} int Gia_Truth5ToGia( Gia_Man_t * p, int * pVarLits, int nVars, unsigned Truth, int fHash ) { int Var, Lit0, Lit1; @@ -645,9 +624,18 @@ word * Gia_ObjComputeTruthTableCut( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t { Gia_Obj_t * pTemp; word * pTruth, * pTruthL, * pTruth0, * pTruth1; - int i, iObj, Id0, Id1; + int i, iObj, Id0, Id1, Index = Vec_IntFind(vLeaves, Gia_ObjId(p, pRoot)); assert( p->vTtMemory != NULL ); assert( Vec_IntSize(vLeaves) <= p->nTtVars ); + if ( Index >= 0 ) + return Gla_ObjTruthElem( p, Index ); + if ( Gia_ObjIsConst0(pRoot) ) + { + if ( Vec_WrdSize(p->vTtMemory) < p->nTtWords ) + Vec_WrdFillExtra( p->vTtMemory, p->nTtWords, 0 ); + return Gla_ObjTruthConst0( p, Gla_ObjTruthFree1(p) ); + } + assert( Gia_ObjIsAnd(pRoot) ); // extend ID numbers if ( Vec_IntSize(p->vTtNums) < Gia_ManObjNum(p) ) Vec_IntFillExtra( p->vTtNums, Gia_ManObjNum(p), -ABC_INFINITY ); diff --git a/src/aig/gia/giaUtil.c b/src/aig/gia/giaUtil.c index d0ec969f..431be5b7 100644 --- a/src/aig/gia/giaUtil.c +++ b/src/aig/gia/giaUtil.c @@ -522,6 +522,28 @@ int Gia_ManLevelNum( Gia_Man_t * p ) } return p->nLevels; } +int Gia_ManLevelRNum( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManCleanLevels( p, Gia_ManObjNum(p) ); + p->nLevels = 0; + Gia_ManForEachObjReverse( p, pObj, i ) + { + if ( !p->fGiaSimple && Gia_ObjIsBuf(pObj) ) + Gia_ObjUpdateLevelId( p, Gia_ObjFaninId0(pObj, i), Gia_ObjLevel(p, pObj) ); + else if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ObjUpdateLevelId( p, Gia_ObjFaninId0(pObj, i), 1+Gia_ObjLevel(p, pObj) ); + Gia_ObjUpdateLevelId( p, Gia_ObjFaninId1(pObj, i), 1+Gia_ObjLevel(p, pObj) ); + } + else if ( Gia_ObjIsCo(pObj) ) + Gia_ObjUpdateLevelId( p, Gia_ObjFaninId0(pObj, i), 1 ); + else + p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) ); + } + return p->nLevels; +} float Gia_ManLevelAve( Gia_Man_t * p ) { Gia_Obj_t * pObj; @@ -1101,19 +1123,20 @@ int Gia_NodeDeref_rec( Gia_Man_t * p, Gia_Obj_t * pNode ) SeeAlso [] ***********************************************************************/ -int Gia_NodeRef_rec( Gia_Man_t * p, Gia_Obj_t * pNode ) +int Gia_NodeRef_rec( Gia_Man_t * p, Gia_Obj_t * pNode, int fMark ) { Gia_Obj_t * pFanin; int Counter = 0; if ( Gia_ObjIsCi(pNode) ) return 0; assert( Gia_ObjIsAnd(pNode) ); + if ( fMark ) Gia_ObjSetTravIdCurrent(p, pNode); pFanin = Gia_ObjFanin0(pNode); if ( Gia_ObjRefInc(p, pFanin) == 0 ) - Counter += Gia_NodeRef_rec( p, pFanin ); + Counter += Gia_NodeRef_rec( p, pFanin, fMark ); pFanin = Gia_ObjFanin1(pNode); if ( Gia_ObjRefInc(p, pFanin) == 0 ) - Counter += Gia_NodeRef_rec( p, pFanin ); + Counter += Gia_NodeRef_rec( p, pFanin, fMark ); return Counter + 1; } @@ -1152,7 +1175,19 @@ int Gia_NodeMffcSize( Gia_Man_t * p, Gia_Obj_t * pNode ) assert( !Gia_IsComplement(pNode) ); assert( Gia_ObjIsCand(pNode) ); ConeSize1 = Gia_NodeDeref_rec( p, pNode ); - ConeSize2 = Gia_NodeRef_rec( p, pNode ); + ConeSize2 = Gia_NodeRef_rec( p, pNode, 0 ); + assert( ConeSize1 == ConeSize2 ); + assert( ConeSize1 >= 0 ); + return ConeSize1; +} +int Gia_NodeMffcSizeMark( Gia_Man_t * p, Gia_Obj_t * pNode ) +{ + int ConeSize1, ConeSize2; + assert( !Gia_IsComplement(pNode) ); + assert( Gia_ObjIsCand(pNode) ); + ConeSize1 = Gia_NodeDeref_rec( p, pNode ); + Gia_ManIncrementTravId( p ); + ConeSize2 = Gia_NodeRef_rec( p, pNode, 1 ); assert( ConeSize1 == ConeSize2 ); assert( ConeSize1 >= 0 ); return ConeSize1; @@ -1193,7 +1228,7 @@ int Gia_NodeMffcSizeSupp( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSupp ) ConeSize1 = Gia_NodeDeref_rec( p, pNode ); Gia_NodeCollect_rec( p, Gia_ObjFanin0(pNode), vSupp ); Gia_NodeCollect_rec( p, Gia_ObjFanin1(pNode), vSupp ); - ConeSize2 = Gia_NodeRef_rec( p, pNode ); + ConeSize2 = Gia_NodeRef_rec( p, pNode, 0 ); assert( ConeSize1 == ConeSize2 ); assert( ConeSize1 >= 0 ); return ConeSize1; @@ -1201,6 +1236,53 @@ int Gia_NodeMffcSizeSupp( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSupp ) /**Function************************************************************* + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_NodeMffcMapping_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vMapping, Vec_Int_t * vSupp ) +{ + Gia_Obj_t * pObj; int i, iNode, Count = 1; + if ( !iObj || Vec_IntEntry(vMapping, iObj) ) + return 0; + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + return 0; + Gia_NodeMffcSizeSupp( p, pObj, vSupp ); + Vec_IntSort( vSupp, 0 ); + Vec_IntWriteEntry( vMapping, iObj, Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Vec_IntSize(vSupp) ); + Vec_IntAppend( vMapping, vSupp ); + Vec_IntPush( vMapping, iObj ); + Vec_IntForEachEntry( vSupp, iNode, i ) + Count += Gia_NodeMffcMapping_rec( p, iNode, vMapping, vSupp ); + return Count; +} +int Gia_NodeMffcMapping( Gia_Man_t * p ) +{ + int i, Id, Count = 0; + int * pRefsOld; + Vec_Int_t * vMapping, * vSupp = Vec_IntAlloc( 100 ); + vMapping = Vec_IntAlloc( 2 * Gia_ManObjNum(p) ); + Vec_IntFill( vMapping, Gia_ManObjNum(p), 0 ); + pRefsOld = p->pRefs; p->pRefs = NULL; + Gia_ManCreateRefs( p ); + Gia_ManForEachCoDriverId( p, Id, i ) + Count += Gia_NodeMffcMapping_rec( p, Id, vMapping, vSupp ); + p->pRefs = pRefsOld; + Vec_IntFree( vSupp ); + p->vMapping = vMapping; + //printf( "Mapping is %.2fx larger than AIG manager.\n", 1.0*Vec_IntSize(vMapping)/Gia_ManObjNum(p) ); + return Count; +} + +/**Function************************************************************* + Synopsis [Returns 1 if AIG has dangling nodes.] Description [] @@ -2027,11 +2109,13 @@ void Gia_AigerWriteLut( Gia_Man_t * p, char * pFileName ) Gia_ManForEachObj( p, pObj, i ) if ( i && Gia_ObjIsLut(p, i) ) { + word truth; pLuts[iLut].Type = 3; Gia_LutForEachFanin( p, i, iFan, k ) pLuts[iLut].pFans[k] = Gia_ManObj(p, iFan)->Value; pLuts[iLut].nFans = k; - *(word *)pLuts[iLut].pTruth = Gia_LutComputeTruth6(p, i, vTruths); + truth = Gia_LutComputeTruth6(p, i, vTruths); + memcpy( pLuts[iLut].pTruth, &truth, sizeof(word) ); pObj->Value = pLuts[iLut].Out = Abc_Var2Lit( iLut, 0 ); iLut++; } @@ -2290,6 +2374,713 @@ Gia_Man_t * Gia_ManDupWithMuxPos( Gia_Man_t * p ) return pNew; } +/**Function************************************************************* + + Synopsis [Collect distance info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManRingAdd( Gia_Man_t * p, int iObj, Vec_Int_t * vRes, Vec_Int_t * vDists, int Dist ) +{ + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + Vec_IntWriteEntry( vDists, iObj, Dist ); + Vec_IntPush( vRes, iObj ); +} +void Gia_ManCollectRing( Gia_Man_t * p, Vec_Int_t * vStart, Vec_Int_t * vRes, Vec_Int_t * vDists ) +{ + int i, k, iObj, iFan; + Vec_IntForEachEntry( vStart, iObj, i ) + { + int Weight = Vec_IntEntry( vDists, iObj ); + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); + assert( Weight > 0 ); + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ManRingAdd( p, Gia_ObjFaninId0(pObj, iObj), vRes, vDists, Weight + 1*!Gia_ObjIsBuf(Gia_ObjFanin0(pObj)) ); + Gia_ManRingAdd( p, Gia_ObjFaninId1(pObj, iObj), vRes, vDists, Weight + 1*!Gia_ObjIsBuf(Gia_ObjFanin1(pObj)) ); + } + Gia_ObjForEachFanoutStaticId( p, iObj, iFan, k ) + Gia_ManRingAdd( p, iFan, vRes, vDists, Weight + 1*!Gia_ObjIsBuf(Gia_ManObj(p, iFan)) ); + } +} +Vec_Int_t * Gia_ManComputeDistanceInt( Gia_Man_t * p, int iTarg, Vec_Int_t * vObjs, int fVerbose ) +{ + int i, iObj; + Vec_Int_t * vDists, * vStart, * vNexts; + vStart = Vec_IntAlloc( 100 ); + vNexts = Vec_IntAlloc( 100 ); + vDists = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManIncrementTravId( p ); + if ( vObjs ) + { + Vec_IntForEachEntry( vObjs, iObj, i ) + { + Gia_ObjSetTravIdCurrentId(p, iObj); + Vec_IntWriteEntry( vDists, iObj, 1 ); + Vec_IntPush( vStart, iObj ); + } + } + else + { + Gia_ObjSetTravIdCurrentId(p, iTarg); + Vec_IntWriteEntry( vDists, iTarg, 1 ); + Vec_IntPush( vStart, iTarg ); + } + for ( i = 0; ; i++ ) + { + if ( fVerbose ) + printf( "Ring %2d : %6d\n", i, Vec_IntSize(vDists)-Vec_IntCountZero(vDists) ); + Gia_ManCollectRing( p, vStart, vNexts, vDists ); + if ( Vec_IntSize(vNexts) == 0 ) + break; + Vec_IntClear( vStart ); + ABC_SWAP( Vec_Int_t, *vStart, *vNexts ); + } + Vec_IntFree( vStart ); + Vec_IntFree( vNexts ); + return vDists; +} +Vec_Int_t * Gia_ManComputeDistance( Gia_Man_t * p, int iObj, Vec_Int_t * vObjs, int fVerbose ) +{ + Vec_Int_t * vDists; + if ( p->vFanoutNums ) + vDists = Gia_ManComputeDistanceInt( p, iObj, vObjs, fVerbose ); + else + { + Gia_ManStaticFanoutStart( p ); + vDists = Gia_ManComputeDistanceInt( p, iObj, vObjs, fVerbose ); + Gia_ManStaticFanoutStop( p ); + } + return vDists; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ComputeTest() +{ + char * pStart, Line [1000]; float Total = 0; + char * pFileName = "data.txt"; + FILE * pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { printf( "Input file \"%s\" cannot be opened.\n", pFileName ); return; } + while ( fgets( Line, 1000, pFile ) != NULL ) + { + if ( !strstr(Line, "xxx") ) + continue; + if ( !strstr(Line, "yyy") ) + continue; + //printf( "%s", Line ); + pStart = strstr(Line, "zzz"); + if ( pStart == NULL ) + continue; + //printf( "%s", pStart + 4 ); + Total += -atof( pStart + 4 ); + } + printf( "Total = %.2f\n", Total ); + fclose( pFile ); +} + + +/**Function************************************************************* + + Synopsis [Computes sum total of support size of primary outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSumTotalOfSupportSizes( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + Vec_Wec_t * vSupps = Vec_WecStart( Gia_ManObjNum(p) ); + int i, nResult = 0; + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + Vec_IntPush( Vec_WecEntry(vSupps, 1+i), i ); + Gia_ManForEachAnd( p, pObj, i ) + Vec_IntTwoMerge2( Vec_WecEntry(vSupps, Gia_ObjFaninId0(pObj, i)), Vec_WecEntry(vSupps, Gia_ObjFaninId1(pObj, i)), Vec_WecEntry(vSupps, i) ); + Gia_ManForEachCo( p, pObj, i ) + nResult += Vec_IntSize( Vec_WecEntry(vSupps, Gia_ObjFaninId0p(p, pObj)) ); + Vec_WecFree( vSupps ); + return nResult; +} + +/**Function************************************************************* + + Synopsis [Computes sum total of support size of primary outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSumTotalOfSupportSizes2( Gia_Man_t * p ) +{ + Vec_Wrd_t * vSims = Vec_WrdStart( Gia_ManObjNum(p) ); + int r, nResult = 0, nRounds = (Gia_ManCiNum(p) + 63)/64; + for ( r = 0; r < nRounds; r++ ) + { + Gia_Obj_t * pObj; + int i, Limit = r == nRounds-1 ? Gia_ManCiNum(p) % 64 : 64; + for ( i = 0; i < Limit; i++ ) + Vec_WrdWriteEntry( vSims, 1+64*r+i, (word)1 << i ); + Gia_ManForEachAnd( p, pObj, i ) + Vec_WrdWriteEntry( vSims, i, Vec_WrdEntry(vSims, Gia_ObjFaninId0(pObj, i)) | Vec_WrdEntry(vSims, Gia_ObjFaninId1(pObj, i)) ); + Gia_ManForEachCo( p, pObj, i ) + nResult += Abc_TtCountOnes( Vec_WrdEntry(vSims, Gia_ObjFaninId0p(p, pObj)) ); + for ( i = 0; i < Limit; i++ ) + Vec_WrdWriteEntry( vSims, 1+64*r+i, 0 ); + } + Vec_WrdFree( vSims ); + return nResult; +} + +/**Function************************************************************* + + Synopsis [Compute dependency.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManComputeCofs( Gia_Man_t * p, int nVars ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; int i, m; + Gia_Obj_t * pSink = Gia_ManCo(p, 0); + Vec_Int_t * vRoots = Vec_IntAlloc( 1 ); + Vec_Int_t * vNodes = Vec_IntAlloc( 1000 ); + Vec_IntPush( vRoots, Gia_ObjFaninId0p(p, pSink) ); + Gia_ManCollectTfi( p, vRoots, vNodes ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + for ( m = 0; m < (1 << nVars); m++ ) + { + for ( i = 0; i < nVars; i++ ) + Gia_ManCi(p, Gia_ManCiNum(p)-nVars+i)->Value = (m >> i) & 1; + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pSink) ); + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vRoots ); + Vec_IntFree( vNodes ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Compute dependency.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManComputeCofs2( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pSink; int i, o, m; + Vec_Int_t * vSupp = Vec_IntAlloc( 1000 ); + Vec_Int_t * vAnds = Vec_IntAlloc( 1000 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManForEachCi( p, pObj, i ) + { + pObj->Value = Gia_ManAppendCi(pNew); + assert( (int)pObj->Value == Abc_Var2Lit( 1 + Gia_ObjCioId(pObj), 0 ) ); + } + Gia_ManHashAlloc( pNew ); + Gia_ManForEachRi( p, pSink, o ) + { + int Fanin = Gia_ObjFaninId0p( p, pSink ); + Vec_Int_t * vNodes = Gia_ManCollectNodesCis( p, &Fanin, 1 ); + Vec_IntClear( vSupp ); + Vec_IntClear( vAnds ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + Vec_IntPush( Gia_ObjIsAnd(pObj) ? vAnds : vSupp, Gia_ObjId(p, pObj) ); + Vec_IntFree( vNodes ); + Vec_IntSort( vSupp, 0 ); + for ( m = 0; m < 5; m++ ) + { + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + if ( i >= Vec_IntSize(vSupp)-5 ) + pObj->Value = (i == Vec_IntSize(vSupp)-5+m) ? 1 : 0; + Gia_ManForEachObjVec( vAnds, p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + //if ( m == 4 ) + // Gia_ManAppendCo( pNew, 0 ); + //else + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pSink) ); + Gia_ManAppendCo( pNew, Abc_Var2Lit( Vec_IntEntry(vSupp, Vec_IntSize(vSupp)-5+m), 0 ) ); + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + if ( i >= Vec_IntSize(vSupp)-5 ) + pObj->Value = Abc_Var2Lit( 1 + Gia_ObjCioId(pObj), 0 ); + } + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vSupp ); + Vec_IntFree( vAnds ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Compute dependency.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManComputeDepAig( Gia_Man_t * p, int iIn, int iOut ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; int i, n, iLits[2]; + Gia_Obj_t * pPivot = Gia_ManCi(p, iIn); + Gia_Obj_t * pSink = Gia_ManCo(p, iOut); + Vec_Int_t * vRoots = Vec_IntAlloc( 1 ); + Vec_Int_t * vNodes = Vec_IntAlloc( 1000 ); + Vec_IntPush( vRoots, Gia_ObjFaninId0p(p, pSink) ); + Gia_ManCollectTfi( p, vRoots, vNodes ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + for ( n = 0; n < 2; n++ ) + { + pPivot->Value = n; + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + iLits[n] = Gia_ObjFanin0Copy(pSink); + } + Gia_ManAppendCo( pNew, Gia_ManHashAnd(pNew, iLits[1], Abc_LitNot(iLits[0])) ); + Gia_ManAppendCo( pNew, Gia_ManHashAnd(pNew, iLits[0], Abc_LitNot(iLits[1])) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vRoots ); + Vec_IntFree( vNodes ); + return pNew; +} +int Gia_ManComputeDep( Gia_Man_t * p, int iIn, int iOut ) +{ + extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); + Gia_Man_t * pNew = Gia_ManComputeDepAig( p, iIn, iOut ); + Gia_Man_t * pSwp = Cec4_ManSimulateTest3( pNew, 100000, 0 ); + int iLit[2] = { Gia_ObjFaninId0p( pSwp, Gia_ManCo(pSwp, 0) ), Gia_ObjFaninId0p( pSwp, Gia_ManCo(pSwp, 1) ) }; + Gia_ManStop( pNew ); + Gia_ManStop( pSwp ); + if ( iLit[0] == 0 && iLit[1] == 0 ) + return 2; + if ( iLit[1] == 0 ) + return 1; + if ( iLit[0] == 0 ) + return 0; + return -1; +} +Gia_Man_t * Gia_ManComputeDepTest( Gia_Man_t * p ) +{ + abctime clk = Abc_Clock(); + int i; + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + printf( "%3d : %3d\n", i, Gia_ManComputeDep(p, i, 0) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return Gia_ManDup(p); +} + +/**Function************************************************************* + + Synopsis [Compute support diffs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManComputeSupports( Gia_Man_t * p ) +{ + Vec_Wec_t * vRes = Vec_WecStart( Gia_ManCoNum(p) ); + Vec_Wec_t * vSupps = Vec_WecStart( Gia_ManObjNum(p) ); + Gia_Obj_t * pObj; int i; + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + Vec_IntPush( Vec_WecEntry(vSupps, 1+i), i ); + Gia_ManForEachAnd( p, pObj, i ) + Vec_IntTwoMerge2( Vec_WecEntry(vSupps, Gia_ObjFaninId0(pObj, i)), Vec_WecEntry(vSupps, Gia_ObjFaninId1(pObj, i)), Vec_WecEntry(vSupps, i) ); + Gia_ManForEachCo( p, pObj, i ) + Vec_IntAppend( Vec_WecEntry(vRes, i), Vec_WecEntry(vSupps, Gia_ObjFaninId0p(p, pObj)) ); + Vec_WecFree( vSupps ); + return vRes; +} +Vec_Wec_t * Gia_ManComputeSharing( Vec_Wec_t * vSupps ) +{ + Vec_Wec_t * vDiffs = Vec_WecStart( Vec_WecSize(vSupps) ); + Vec_Int_t * vNew, * vOld; int i; + Vec_WecForEachLevelTwo( vDiffs, vSupps, vNew, vOld, i ) if ( i ) + Vec_IntTwoFindCommon( Vec_WecEntry(vSupps, i-1), vOld, vNew ); + return vDiffs; +} +Vec_Str_t * Gia_ManConvertDump( Gia_Man_t * p, Vec_Wec_t * vSupps ) +{ + int fPrintDep = 1; + int nSize = Gia_ManCoNum(p) * (Gia_ManCiNum(p) + 1) + 1; + Vec_Str_t * vRes = Vec_StrAlloc( nSize ); + Vec_Int_t * vLevel; int i, k, Obj; + assert( Gia_ManCoNum(p) == Vec_WecSize(vSupps) ); + Vec_StrFill( vRes, nSize-1, '_' ); + Vec_StrPush( vRes, '\0' ); + Vec_WecForEachLevel( vSupps, vLevel, i ) + { + Vec_IntForEachEntry( vLevel, Obj, k ) + { + if ( !fPrintDep ) + Vec_StrWriteEntry( vRes, i * (Gia_ManCiNum(p) + 1) + Obj, '*' ); + else + { + int Value = Gia_ManComputeDep( p, Obj, i ); + if ( Value == -1 ) + Vec_StrWriteEntry( vRes, i * (Gia_ManCiNum(p) + 1) + Obj, '*' ); + else + Vec_StrWriteEntry( vRes, i * (Gia_ManCiNum(p) + 1) + Obj, (char)('0'+Value) ); + } + } + Vec_StrWriteEntry( vRes, i * (Gia_ManCiNum(p) + 1) + Gia_ManCiNum(p), '\n' ); + //printf( "Output %d\n", i ); + } + return vRes; +} +void Gia_ManDumpSuppFile( Vec_Str_t * p, char * pFileName ) +{ + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + else + { + int nOuts = Vec_StrCountEntry(p, '\n'); + int nIns = Vec_StrSize(p)/Vec_StrCountEntry(p, '\n') - 1; + int nSize1 = Vec_StrSize(p) - 1; + int nSize2 = fwrite( Vec_StrArray(p), 1, nSize1, pFile ); + assert( nSize1 == nSize2 ); + printf( "Successfully dumped file \"%s\" with support data for %d outputs and %d inputs.\n", pFileName, nOuts, nIns ); + } + fclose( pFile ); +} +void Gia_ManDumpSuppFileTest3( Gia_Man_t * p, char * pFileName ) +{ + Vec_Wec_t * vSupps = Gia_ManComputeSupports( p ); + Vec_Wec_t * vDiffs = Gia_ManComputeSharing( vSupps ); + Vec_Wec_t * vDiffs2 = Gia_ManComputeSharing( vDiffs ); + Vec_Str_t * vRes = Gia_ManConvertDump( p, vDiffs2 ); + Gia_ManDumpSuppFile( vRes, pFileName ); + Vec_WecFree( vDiffs2 ); + Vec_WecFree( vDiffs ); + Vec_WecFree( vSupps ); + Vec_StrFree( vRes ); +} +void Gia_ManDumpSuppFileTest( Gia_Man_t * p, char * pFileName ) +{ + Vec_Wec_t * vSupps = Gia_ManComputeSupports( p ); + Vec_Str_t * vRes = Gia_ManConvertDump( p, vSupps ); + Gia_ManDumpSuppFile( vRes, pFileName ); + Vec_WecFree( vSupps ); + Vec_StrFree( vRes ); +} + + +/**Function************************************************************* + + Synopsis [Compute support diffs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManConvertSupp_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( !Gia_ObjIsAnd(pObj) ) + return; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + Gia_ManConvertSupp_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManConvertSupp_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManConvertSupp( Gia_Man_t * p ) +{ + int fOnly1 = 0; + int fVerbose = 1; + abctime clk = Abc_Clock(); + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObjPi, * pObjRi, * pObjRo; + Vec_Int_t * vSupp = Vec_IntAlloc( 100 ); + Vec_Int_t * vAnds = Vec_IntAlloc( 100 ); + int i, n, iLits[2]; + assert( Gia_ManRegNum(p) && Gia_ManRegNum(p) % 8 == 0 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObjPi, i ) + pObjPi->Value = Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachRi( p, pObjRi, i ) + { + pObjRo = Gia_ObjRiToRo(p, pObjRi); + if ( (i - Gia_ManPoNum(p)) % 8 != 0 ) + continue; + if ( fOnly1 ) + { + assert( pObjRo->Value == ~0 ); + for ( n = 0; n < 2; n++ ) + { + pObjRo->Value = n; + Gia_ManIncrementTravId( p ); + Gia_ManConvertSupp_rec( pNew, p, Gia_ObjFanin0(pObjRi) ); + iLits[n] = Gia_ObjFanin0Copy(pObjRi); + } + pObjRo->Value = ~0; + Gia_ManAppendCo( pNew, Abc_LitNot(Gia_ManHashAnd( pNew, iLits[1], Abc_LitNot(iLits[0]) )) ); + } + else + { + int Fanin = Gia_ObjFaninId0p( p, pObjRi ); + Vec_Int_t * vNodes = Gia_ManCollectNodesCis( p, &Fanin, 1 ); + Gia_Obj_t * pObj; int i, m; + Vec_IntClear( vSupp ); + Vec_IntClear( vAnds ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + Vec_IntPush( Gia_ObjIsAnd(pObj) ? vAnds : vSupp, Gia_ObjId(p, pObj) ); + Vec_IntFree( vNodes ); + Vec_IntSort( vSupp, 0 ); + for ( m = 0; m < 4; m++ ) + { + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + if ( i >= Vec_IntSize(vSupp)-5 ) + pObj->Value = (i == Vec_IntSize(vSupp)-5+m) ? 1 : 0; + Gia_ManForEachObjVec( vAnds, p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + //if ( m == 4 ) + // Gia_ManAppendCo( pNew, 0 ); + //else + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObjRi) ); + //Gia_ManAppendCo( pNew, Abc_Var2Lit( Vec_IntEntry(vSupp, Vec_IntSize(vSupp)-5+m), 0 ) ); + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + if ( i >= Vec_IntSize(vSupp)-5 ) + pObj->Value = Abc_Var2Lit( 1 + Gia_ObjCioId(pObj), 0 ); + } + } + } + Vec_IntFree( vSupp ); + Vec_IntFree( vAnds ); + Gia_ManHashStop( pNew ); + //Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + if ( fVerbose ) + printf( "Transformed %d outputs, ", Gia_ManPoNum(pNew) ); + if ( fVerbose ) + Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Transform flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManTransformCond2( Gia_Man_t * p ) +{ + int fVerbose = 1; + abctime clk = Abc_Clock(); + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObjPi, * pObjRi, * pObjRo; + int i, n, iTempLit, iLits[2]; + assert( Gia_ManRegNum(p) > 0 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObjPi, i ) + pObjPi->Value = Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachRi( p, pObjRi, i ) + { + //if ( (i - Gia_ManPoNum(p)) % 8 != 0 ) + // continue; + pObjRo = Gia_ObjRiToRo(p, pObjRi); + iTempLit = pObjRo->Value; + for ( n = 0; n < 2; n++ ) + { + pObjRo->Value = n; + Gia_ManIncrementTravId( p ); + Gia_ManConvertSupp_rec( pNew, p, Gia_ObjFanin0(pObjRi) ); + iLits[n] = Gia_ObjFanin0Copy(pObjRi); + } + pObjRo->Value = iTempLit; + Gia_ManAppendCo( pNew, Abc_LitNot(Gia_ManHashAnd( pNew, iLits[1], Abc_LitNot(iLits[0]) )) ); + Gia_ManAppendCo( pNew, Abc_LitNot(Gia_ManHashAnd( pNew, iLits[0], Abc_LitNot(iLits[1]) )) ); + } + Gia_ManHashStop( pNew ); + //Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + if ( fVerbose ) + printf( "Created %d outputs. ", Gia_ManPoNum(pNew) ); + if ( fVerbose ) + Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Transform flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Gia_ManDetectSims( Gia_Man_t * p, int iCo, int nWords ) +{ + extern int Cec4_ManGeneratePatterns_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int Value, Vec_Int_t * vPat, Vec_Int_t * vVisit ); + Vec_Wrd_t * vSim = Vec_WrdStart( nWords * Gia_ManCiNum(p) ); + Vec_Int_t * vPat = Vec_IntAlloc( Gia_ManCiNum(p) ); + Vec_Int_t * vVis = Vec_IntAlloc( Gia_ManAndNum(p) ); + Gia_Obj_t * pObj = Gia_ManCo( p, iCo ), * pTemp; int iLit, i, k, nTries = 0; + if ( Gia_ObjFanin0(pObj) == Gia_ManConst0(p) ) + return NULL; + Gia_ManForEachObj( p, pTemp, k ) + assert( !pTemp->fMark0 && !pTemp->fMark1 ); + for ( i = 0; i < 64*nWords; ) + { + int Res = Cec4_ManGeneratePatterns_rec( p, Gia_ObjFanin0(pObj), !Gia_ObjFaninC0(pObj), vPat, vVis ); + if ( Res ) + { + Vec_IntForEachEntry( vPat, iLit, k ) + { + if ( Abc_LitIsCompl(iLit) ) + continue; + pTemp = Gia_ManObj( p, Abc_Lit2Var(iLit) ); + assert( Gia_ObjIsCi(pTemp) ); + Abc_InfoSetBit( (unsigned *)Vec_WrdEntryP(vSim, nWords*Gia_ObjCioId(pTemp)), i ); + } + i++; + } + Gia_ManForEachObjVec( vVis, p, pTemp, k ) + pTemp->fMark0 = pTemp->fMark1 = 0; + nTries++; + } + //printf( "%d ", nTries ); + Vec_IntFree( vPat ); + Vec_IntFree( vVis ); + return vSim; +} +Vec_Wrd_t * Vec_WrdInterleave( Vec_Wrd_t * p1, Vec_Wrd_t * p2, int nWords, int nIns ) +{ + Vec_Wrd_t * p = Vec_WrdAlloc( Vec_WrdSize(p1)+Vec_WrdSize(p2) ); + int i, k; + assert( Vec_WrdSize(p1) == nWords*nIns ); + assert( Vec_WrdSize(p2) == nWords*nIns ); + for ( i = 0; i < nIns; i++ ) + { + for ( k = 0; k < nWords; k++ ) + Vec_WrdPush( p, Vec_WrdEntry(p1, i*nWords+k) ); + for ( k = 0; k < nWords; k++ ) + Vec_WrdPush( p, Vec_WrdEntry(p2, i*nWords+k) ); + } + return p; +} +Gia_Man_t * Gia_ManTransformCond( Gia_Man_t * p ) +{ + extern void Gia_ManResubPair( Vec_Wrd_t * vOn, Vec_Wrd_t * vOff, int nWords, int nIns ); + abctime clk = Abc_Clock(); + Vec_Wrd_t * vSims; + Vec_Wrd_t * vSim[4]; + Vec_Wrd_t * vInt[6]; + int i; + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + { + vSims = Gia_ManDetectSims( p, i, 1 ); + if ( i >= Gia_ManCoNum(p)-4 ) + vSim[i-(Gia_ManCoNum(p)-4)] = vSims; + else + Vec_WrdFreeP( &vSims ); + //Vec_PtrPush( vAll, vSims ); + } + vInt[0] = Vec_WrdInterleave( vSim[0], vSim[1], 1, Gia_ManCiNum(p) ); + vInt[1] = Vec_WrdInterleave( vSim[0], vSim[2], 1, Gia_ManCiNum(p) ); + vInt[2] = Vec_WrdInterleave( vSim[0], vSim[3], 1, Gia_ManCiNum(p) ); + vInt[3] = Vec_WrdInterleave( vSim[1], vSim[2], 1, Gia_ManCiNum(p) ); + vInt[4] = Vec_WrdInterleave( vSim[1], vSim[3], 1, Gia_ManCiNum(p) ); + vInt[5] = Vec_WrdInterleave( vSim[2], vSim[3], 1, Gia_ManCiNum(p) ); + + Gia_ManResubPair( vInt[0], vInt[5], 2, Gia_ManCiNum(p) ); + Gia_ManResubPair( vInt[1], vInt[4], 2, Gia_ManCiNum(p) ); + Gia_ManResubPair( vInt[2], vInt[3], 2, Gia_ManCiNum(p) ); + + Gia_ManResubPair( vInt[5], vInt[0], 2, Gia_ManCiNum(p) ); + Gia_ManResubPair( vInt[4], vInt[1], 2, Gia_ManCiNum(p) ); + Gia_ManResubPair( vInt[3], vInt[2], 2, Gia_ManCiNum(p) ); + +/* + for ( i = 0; i < 4; i++ ) + for ( k = i+1; k < 4; k++ ) + Gia_ManResubPair( vSim[i], vSim[k], 1, Gia_ManCiNum(p) ); +*/ + Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); + return NULL; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/aig/gia/module.make b/src/aig/gia/module.make index 26909410..d801a243 100644 --- a/src/aig/gia/module.make +++ b/src/aig/gia/module.make @@ -14,8 +14,10 @@ SRC += src/aig/gia/giaAig.c \ src/aig/gia/giaCSatOld.c \ src/aig/gia/giaCSat.c \ src/aig/gia/giaCSat2.c \ + src/aig/gia/giaCSat3.c \ src/aig/gia/giaCTas.c \ src/aig/gia/giaCut.c \ + src/aig/gia/giaDecs.c \ src/aig/gia/giaDeep.c \ src/aig/gia/giaDfs.c \ src/aig/gia/giaDup.c \ @@ -51,14 +53,21 @@ SRC += src/aig/gia/giaAig.c \ src/aig/gia/giaMem.c \ src/aig/gia/giaMfs.c \ src/aig/gia/giaMini.c \ + src/aig/gia/giaMinLut.c \ + src/aig/gia/giaMinLut2.c \ src/aig/gia/giaMuxes.c \ src/aig/gia/giaNf.c \ src/aig/gia/giaOf.c \ src/aig/gia/giaPack.c \ src/aig/gia/giaPat.c \ + src/aig/gia/giaPat2.c \ src/aig/gia/giaPf.c \ src/aig/gia/giaQbf.c \ + src/aig/gia/giaReshape1.c \ + src/aig/gia/giaReshape2.c \ src/aig/gia/giaResub.c \ + src/aig/gia/giaResub2.c \ + src/aig/gia/giaResub3.c \ src/aig/gia/giaRetime.c \ src/aig/gia/giaRex.c \ src/aig/gia/giaSatEdge.c \ @@ -75,16 +84,16 @@ SRC += src/aig/gia/giaAig.c \ src/aig/gia/giaShrink7.c \ src/aig/gia/giaSim.c \ src/aig/gia/giaSim2.c \ - src/aig/gia/giaSim4.c \ - src/aig/gia/giaSim5.c \ src/aig/gia/giaSimBase.c \ src/aig/gia/giaSort.c \ src/aig/gia/giaSpeedup.c \ src/aig/gia/giaSplit.c \ src/aig/gia/giaStg.c \ + src/aig/gia/giaStoch.c \ src/aig/gia/giaStr.c \ src/aig/gia/giaSupMin.c \ src/aig/gia/giaSupp.c \ + src/aig/gia/giaSupps.c \ src/aig/gia/giaSweep.c \ src/aig/gia/giaSweeper.c \ src/aig/gia/giaSwitch.c \ diff --git a/src/aig/hop/hopBalance.c b/src/aig/hop/hopBalance.c index e9aa4d4d..a3ce1c86 100644 --- a/src/aig/hop/hopBalance.c +++ b/src/aig/hop/hopBalance.c @@ -246,7 +246,7 @@ Hop_Obj_t * Hop_NodeBalanceBuildSuper( Hop_Man_t * p, Vec_Ptr_t * vSuper, Hop_Ty int LeftBound; assert( vSuper->nSize > 1 ); // sort the new nodes by level in the decreasing order - Vec_PtrSort( vSuper, (int (*)(void))Hop_NodeCompareLevelsDecrease ); + Vec_PtrSort( vSuper, (int (*)(const void *, const void *))Hop_NodeCompareLevelsDecrease ); // balance the nodes while ( vSuper->nSize > 1 ) { diff --git a/src/aig/ivy/ivyBalance.c b/src/aig/ivy/ivyBalance.c index 6eba318c..2bcc69ee 100644 --- a/src/aig/ivy/ivyBalance.c +++ b/src/aig/ivy/ivyBalance.c @@ -178,7 +178,7 @@ Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Ty int LeftBound; assert( vSuper->nSize > 1 ); // sort the new nodes by level in the decreasing order - Vec_PtrSort( vSuper, (int (*)(void))Ivy_NodeCompareLevelsDecrease ); + Vec_PtrSort( vSuper, (int (*)(const void *, const void *))Ivy_NodeCompareLevelsDecrease ); // balance the nodes while ( vSuper->nSize > 1 ) { diff --git a/src/aig/ivy/ivyCutTrav.c b/src/aig/ivy/ivyCutTrav.c index 74212b10..b1cdb456 100644 --- a/src/aig/ivy/ivyCutTrav.c +++ b/src/aig/ivy/ivyCutTrav.c @@ -329,7 +329,7 @@ void Ivy_NodeComputeVolume2( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNode } while ( Vec_PtrSize(vNodes) < nNodeLimit ); // sort nodes by level - Vec_PtrSort( vNodes, (int (*)(void))Ivy_CompareNodesByLevel ); + Vec_PtrSort( vNodes, (int (*)(const void *, const void *))Ivy_CompareNodesByLevel ); // make sure the nodes are ordered in the increasing number of levels pFanin = (Ivy_Obj_t *)Vec_PtrEntry( vNodes, 0 ); pPivot = (Ivy_Obj_t *)Vec_PtrEntryLast( vNodes ); diff --git a/src/aig/ivy/ivyRwrAlg.c b/src/aig/ivy/ivyRwrAlg.c index ce605003..53fe5817 100644 --- a/src/aig/ivy/ivyRwrAlg.c +++ b/src/aig/ivy/ivyRwrAlg.c @@ -371,7 +371,7 @@ int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeave if ( Vec_PtrSize(vFront) <= 2 ) return 1; // sort the entries in increasing order - Vec_PtrSort( vFront, (int (*)(void))Ivy_ManFindAlgCutCompare ); + Vec_PtrSort( vFront, (int (*)(const void *, const void *))Ivy_ManFindAlgCutCompare ); // remove duplicates from vFront and save the nodes in vLeaves pPrev = Vec_PtrEntry(vFront, 0); Vec_PtrPush( vLeaves, pPrev ); diff --git a/src/aig/miniaig/abcOper.h b/src/aig/miniaig/abcOper.h index 2fd7ab24..c3d6e176 100644 --- a/src/aig/miniaig/abcOper.h +++ b/src/aig/miniaig/abcOper.h @@ -29,7 +29,9 @@ /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// +#ifndef _YOSYS_ ABC_NAMESPACE_HEADER_START +#endif //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// @@ -232,6 +234,26 @@ static inline const char * Abc_OperName( int Type ) return NULL; } +// printing operator types +static inline const char * Abc_OperNameSimple( int Type ) +{ + if ( Type == ABC_OPER_NONE ) return NULL; + if ( Type == ABC_OPER_CONST_F ) return "buf"; + if ( Type == ABC_OPER_CONST_T ) return "buf"; + if ( Type == ABC_OPER_CONST_X ) return "buf"; + if ( Type == ABC_OPER_CONST_Z ) return "buf"; + if ( Type == ABC_OPER_BIT_BUF ) return "buf"; + if ( Type == ABC_OPER_BIT_INV ) return "not"; + if ( Type == ABC_OPER_BIT_AND ) return "and"; + if ( Type == ABC_OPER_BIT_OR ) return "or"; + if ( Type == ABC_OPER_BIT_XOR ) return "xor"; + if ( Type == ABC_OPER_BIT_NAND ) return "nand"; + if ( Type == ABC_OPER_BIT_NOR ) return "nor"; + if ( Type == ABC_OPER_BIT_NXOR ) return "xnor"; + assert( 0 ); + return NULL; +} + //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -244,9 +266,9 @@ static inline const char * Abc_OperName( int Type ) /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// - +#ifndef _YOSYS_ ABC_NAMESPACE_HEADER_END - +#endif #endif diff --git a/src/aig/miniaig/minilut.h b/src/aig/miniaig/minilut.h index b080c983..2a27ccad 100644 --- a/src/aig/miniaig/minilut.h +++ b/src/aig/miniaig/minilut.h @@ -179,7 +179,37 @@ static void Mini_LutPrintStats( Mini_Lut_t * p ) nNodes = 0; Mini_LutForEachNode( p, i ) nNodes++; - printf( "PI = %d. PO = %d. LUT = %d.\n", nPis, nPos, nNodes ); + printf( "PI = %d. PO = %d. LUT = %d. FF = %d.\n", nPis, nPos, nNodes, p->nRegs ); +} +static void Mini_LutPrint( Mini_Lut_t * p ) +{ + int i, k, Fan; + printf( "MiniLUT statistics: " ); + Mini_LutPrintStats( p ); + printf( "Printout of nodes:\n" ); + for ( i = 0; i < p->nSize; i++ ) + { + printf( "%6d : ", i ); + if ( Mini_LutNodeIsConst(p, i) ) + printf( "Const%d", i ); + else if ( Mini_LutNodeIsPi(p, i) ) + printf( "PI" ); + else if ( Mini_LutNodeIsPo(p, i) ) + printf( "PO" ); + else if ( Mini_LutNodeIsNode(p, i) ) + { + printf( "LUT%d Fanins:", p->LutSize ); + Mini_LutForEachFanin( p, i, Fan, k ) + printf( " %6d", Fan ); + while ( k++ < p->LutSize ) + printf( " " ); + printf( " Function: " ); + for ( k = 31; k >= 0; k-- ) + printf( "%c", '0' + ((p->pTruths[i] >> k) & 1) ); + } + printf( "\n" ); + } + printf( "End of printout.\n" ); } // serialization diff --git a/src/aig/miniaig/ndr.h b/src/aig/miniaig/ndr.h index 8d630159..68c2779c 100644 --- a/src/aig/miniaig/ndr.h +++ b/src/aig/miniaig/ndr.h @@ -33,7 +33,9 @@ #include "abcOper.h" +#ifndef _YOSYS_ ABC_NAMESPACE_HEADER_START +#endif #ifdef _WIN32 #define inline __inline @@ -215,8 +217,9 @@ static inline void Ndr_DataPushString( Ndr_Data_t * p, int ObjType, int Type, ch return; if ( ObjType == ABC_OPER_LUT ) { - word Truth = (word)pFunc; - Ndr_DataPushArray( p, Type, 2, (int *)&Truth ); + //word Truth = (word)pFunc; + //Ndr_DataPushArray( p, Type, 2, (int *)&Truth ); + Ndr_DataPushArray( p, Type, 2, (int *)&pFunc ); } else { @@ -334,7 +337,7 @@ static inline int Ndr_DataObjNum( Ndr_Data_t * p, int Mod ) } // to write signal names, this procedure takes a mapping of name IDs into actual char-strings (pNames) -static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod, char ** pNames ) +static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod, char ** pNames, int fSimple ) { Ndr_Data_t * p = (Ndr_Data_t *)pDesign; int * pOuts = NDR_ALLOC( int, Ndr_DataCoNum(p, Mod) ); @@ -377,6 +380,8 @@ static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod break; if ( k < i ) continue; + if ( Ndr_ObjReadOutName(p, Obj, pNames)[0] == '1' ) + continue; fprintf( pFile, " wire " ); Ndr_ObjWriteRange( p, Obj, pFile, 1 ); fprintf( pFile, " %s;\n", Ndr_ObjReadOutName(p, Obj, pNames) ); @@ -459,6 +464,24 @@ static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod fprintf( pFile, ");\n" ); continue; } + if ( fSimple ) + { + if ( Ndr_ObjReadOutName(p, Obj, pNames)[0] == '1' ) + continue; + nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + fprintf( pFile, " %s ( %s", Abc_OperNameSimple(Type), Ndr_ObjReadOutName(p, Obj, pNames) ); + if ( nArray == 0 ) + fprintf( pFile, ", %s );\n", (char *)Ndr_ObjReadBodyP(p, Obj, NDR_FUNCTION) ); + else if ( nArray == 1 && Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE) == ABC_OPER_BIT_BUF ) + fprintf( pFile, ", %s );\n", pNames[pArray[0]] ); + else + { + for ( i = 0; i < nArray; i++ ) + fprintf( pFile, ", %s", pNames[pArray[i]] ); + fprintf( pFile, " );\n" ); + } + continue; + } fprintf( pFile, " assign %s = ", Ndr_ObjReadOutName(p, Obj, pNames) ); nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); if ( nArray == 0 ) @@ -492,15 +515,15 @@ static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod } // to write signal names, this procedure takes a mapping of name IDs into actual char-strings (pNames) -static inline void Ndr_WriteVerilog( char * pFileName, void * pDesign, char ** pNames ) +static inline void Ndr_WriteVerilog( char * pFileName, void * pDesign, char ** pNames, int fSimple ) { Ndr_Data_t * p = (Ndr_Data_t *)pDesign; int Mod; FILE * pFile = pFileName ? fopen( pFileName, "wb" ) : stdout; - if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return; } + if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ? pFileName : "stdout" ); return; } Ndr_DesForEachMod( p, Mod ) - Ndr_WriteVerilogModule( pFile, p, Mod, pNames ); + Ndr_WriteVerilogModule( pFile, p, Mod, pNames, fSimple ); if ( pFileName ) fclose( pFile ); } @@ -613,7 +636,7 @@ static inline void Ndr_Write( char * pFileName, void * pDesign ) { Ndr_Data_t * p = (Ndr_Data_t *)pDesign; int RetValue; FILE * pFile = fopen( pFileName, "wb" ); - if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return; } + if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ? pFileName : "stdout" ); return; } RetValue = (int)fwrite( p->pBody, 4, p->pBody[0], pFile ); RetValue = (int)fwrite( p->pHead, 1, p->pBody[0], pFile ); fclose( pFile ); @@ -642,7 +665,7 @@ static inline void Ndr_ModuleTest() // array of fanins of node s int Fanins[2] = { NameIdA, NameIdC }; // map name IDs into char strings - char * ppNames[5] = { NULL, "add10", "a", "s", "const10" }; + //char * ppNames[5] = { NULL, "add10", "a", "s", "const10" }; // create a new module void * pDesign = Ndr_Create( 1 ); @@ -651,13 +674,13 @@ static inline void Ndr_ModuleTest() // add objects to the modele Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &NameIdA, NULL ); // no fanins - Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CONST, 0, 3, 0, 0, 0, NULL, 1, &NameIdC, "4'b1010" ); // no fanins + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CONST, 0, 3, 0, 0, 0, NULL, 1, &NameIdC, (char*)"4'b1010" ); // no fanins Ndr_AddObject( pDesign, ModuleID, ABC_OPER_ARI_ADD, 0, 3, 0, 0, 2, Fanins, 1, &NameIdS, NULL ); // fanins are a and const10 Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 3, 0, 0, 1, &NameIdS, 0, NULL, NULL ); // fanin is a // write Verilog for verification - Ndr_WriteVerilog( NULL, pDesign, ppNames ); - Ndr_Write( "add4.ndr", pDesign ); + //Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); + Ndr_Write( (char*)"add4.ndr", pDesign ); Ndr_Delete( pDesign ); } @@ -686,6 +709,7 @@ static inline void Ndr_ModuleTest() static inline void Ndr_ModuleTestAdder() { +/* // map name IDs into char strings char * ppNames[20] = { NULL, "a", "b", "s", "co", // 1, 2, 3, 4 @@ -693,6 +717,7 @@ static inline void Ndr_ModuleTestAdder() "r0", "s0", "rco", // 9, 10, 11 "r1", "s1", "add8" // 12, 13, 14 }; +*/ // fanins int FaninA = 1; int FaninB = 2; @@ -744,8 +769,8 @@ static inline void Ndr_ModuleTestAdder() Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 0, 0, 0, 1, &FaninCO, 0, NULL, NULL ); // write Verilog for verification - Ndr_WriteVerilog( NULL, pDesign, ppNames ); - Ndr_Write( "add8.ndr", pDesign ); + //Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); + Ndr_Write( (char*)"add8.ndr", pDesign ); Ndr_Delete( pDesign ); } @@ -772,6 +797,7 @@ static inline void Ndr_ModuleTestAdder() static inline void Ndr_ModuleTestHierarchy() { +/* // map name IDs into char strings char * ppNames[20] = { NULL, "mux21w", "mux41w", // 1, 2 @@ -781,6 +807,7 @@ static inline void Ndr_ModuleTestHierarchy() "t0", "t1", // 12, 13 "i0", "i1", "i2" // 14, 15, 16 }; +*/ // fanins int FaninSel = 3; int FaninSel0 = 10; @@ -830,8 +857,8 @@ static inline void Ndr_ModuleTestHierarchy() Ndr_AddObject( pDesign, Module41, ABC_OPER_CO, 0, 3, 0, 0, 1, &FaninOut, 0, NULL, NULL ); // write Verilog for verification - Ndr_WriteVerilog( NULL, pDesign, ppNames ); - Ndr_Write( "mux41w.ndr", pDesign ); + //Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); + Ndr_Write( (char*)"mux41w.ndr", pDesign ); Ndr_Delete( pDesign ); } @@ -859,6 +886,7 @@ static inline void Ndr_ModuleTestHierarchy() static inline void Ndr_ModuleTestMemory() { +/* // map name IDs into char strings char * ppNames[20] = { NULL, "clk", "raddr", "waddr", "data", "mem_init", "out", // 1, 2, 3, 4, 5, 6 @@ -868,6 +896,7 @@ static inline void Ndr_ModuleTestMemory() "i_read1", "i_read2", // 15, 16 "i_write1", "i_write2", "memtest" // 17, 18, 19 }; +*/ // inputs int NameIdClk = 1; int NameIdRaddr = 2; @@ -919,8 +948,8 @@ static inline void Ndr_ModuleTestMemory() Ndr_AddObject( pDesign, ModuleID, ABC_OPER_COMP_NOTEQU, 0, 0, 0, 0, 2, FaninsComp, 1, &NameIdComp, NULL ); // write Verilog for verification - Ndr_WriteVerilog( NULL, pDesign, ppNames ); - Ndr_Write( "memtest.ndr", pDesign ); + //Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); + Ndr_Write( (char*)"memtest.ndr", pDesign ); Ndr_Delete( pDesign ); } @@ -934,7 +963,7 @@ static inline void Ndr_ModuleTestMemory() static inline void Ndr_ModuleTestFlop() { // map name IDs into char strings - char * ppNames[12] = { NULL, "flop", "data", "clk", "reset", "set", "enable", "async", "sre", "init", "q" }; + //char * ppNames[12] = { NULL, "flop", "data", "clk", "reset", "set", "enable", "async", "sre", "init", "q" }; // name IDs int NameIdData = 2; int NameIdClk = 3; @@ -968,8 +997,8 @@ static inline void Ndr_ModuleTestFlop() Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 3, 0, 0, 1, &NameIdQ, 0, NULL, NULL ); // write Verilog for verification - Ndr_WriteVerilog( NULL, pDesign, ppNames ); - Ndr_Write( "flop.ndr", pDesign ); + //Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); + Ndr_Write( (char*)"flop.ndr", pDesign ); Ndr_Delete( pDesign ); } @@ -1022,8 +1051,8 @@ static inline void Ndr_ModuleTestSelSel() Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 2, 0, 0, 1, &NameIdOut,0, NULL, NULL ); // write Verilog for verification - //Ndr_WriteVerilog( NULL, pDesign, ppNames ); - Ndr_Write( "sel.ndr", pDesign ); + //Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); + Ndr_Write( (char*)"sel.ndr", pDesign ); Ndr_Delete( pDesign ); } @@ -1056,7 +1085,7 @@ static inline void Ndr_ModuleTestDec() Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SEL_DEC, 0, 3, 0, 0, 1, &NameIdIn, 1, &NameIdOut, NULL ); Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 3, 0, 0, 1, &NameIdOut, 0, NULL, NULL ); - Ndr_Write( "dec.ndr", pDesign ); + Ndr_Write( (char*)"dec.ndr", pDesign ); Ndr_Delete( pDesign ); } @@ -1092,7 +1121,7 @@ static inline void Ndr_ModuleTestAddSub() Ndr_AddObject( pDesign, ModuleID, ABC_OPER_ARI_ADDSUB, 0, 3, 0, 0, 4, Fanins, 1, &NameIdOut, NULL ); Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 3, 0, 0, 1, &NameIdOut, 0, NULL, NULL ); - Ndr_Write( "addsub.ndr", pDesign ); + Ndr_Write( (char*)"addsub.ndr", pDesign ); Ndr_Delete( pDesign ); } @@ -1116,16 +1145,20 @@ static inline void Ndr_ModuleTestLut() int ModuleID = Ndr_AddModule( pDesign, 1 ); + unsigned pTruth[2] = { 0x88888888, 0x88888888 }; + // add objects to the modele Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 1, 0, 0, 0, NULL, 1, &NameIdIn, NULL ); - Ndr_AddObject( pDesign, ModuleID, ABC_OPER_LUT, 0, 0, 0, 0, 1, &NameIdIn, 1, &NameIdOut, (char *)(ABC_CONST(0x8)) ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_LUT, 0, 0, 0, 0, 1, &NameIdIn, 1, &NameIdOut, (char *)pTruth ); Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 0, 0, 0, 1, &NameIdOut, 0, NULL, NULL ); - Ndr_Write( "lut_test.ndr", pDesign ); + Ndr_Write( (char*)"lut_test.ndr", pDesign ); Ndr_Delete( pDesign ); } +#ifndef _YOSYS_ ABC_NAMESPACE_HEADER_END +#endif #endif diff --git a/src/aig/saig/saigConstr.c b/src/aig/saig/saigConstr.c index ac58839b..90e82816 100644 --- a/src/aig/saig/saigConstr.c +++ b/src/aig/saig/saigConstr.c @@ -300,8 +300,8 @@ Aig_Man_t * Saig_ManDupUnfoldConstrs( Aig_Man_t * pAig ) Vec_VecFree( (Vec_Vec_t *)vConsAll ); return Aig_ManDupDfs( pAig ); } - Vec_PtrSort( vOuts, (int (*)(void))Saig_ManDupCompare ); - Vec_PtrSort( vCons, (int (*)(void))Saig_ManDupCompare ); + Vec_PtrSort( vOuts, (int (*)(const void *, const void *))Saig_ManDupCompare ); + Vec_PtrSort( vCons, (int (*)(const void *, const void *))Saig_ManDupCompare ); Vec_PtrPush( vOutsAll, vOuts ); Vec_PtrPush( vConsAll, vCons ); } diff --git a/src/aig/saig/saigIso.c b/src/aig/saig/saigIso.c index 40500361..7b8d488a 100644 --- a/src/aig/saig/saigIso.c +++ b/src/aig/saig/saigIso.c @@ -63,7 +63,7 @@ Vec_Int_t * Saig_ManFindIsoPermCos( Aig_Man_t * pAig, Vec_Int_t * vPermCis ) pObj->iData = Abc_Var2Lit( pFanin->iData, Aig_ObjFaninC0(pObj) ); Vec_PtrPush( vRoots, pObj ); } - Vec_PtrSort( vRoots, (int (*)(void))Iso_ObjCompareByData ); + Vec_PtrSort( vRoots, (int (*)(const void *, const void *))Iso_ObjCompareByData ); Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i ) Vec_IntPush( vPermCos, Aig_ObjCioId(pObj) ); Vec_PtrFree( vRoots ); @@ -467,7 +467,7 @@ Aig_Man_t * Iso_ManFilterPos( Aig_Man_t * pAig, Vec_Ptr_t ** pvPosEquivs, int fV // sort the infos clk = Abc_Clock(); - Vec_PtrSort( vBuffers, (int (*)(void))Iso_StoCompareVecStr ); + Vec_PtrSort( vBuffers, (int (*)(const void *, const void *))Iso_StoCompareVecStr ); // create classes clk = Abc_Clock(); diff --git a/src/aig/saig/saigIsoFast.c b/src/aig/saig/saigIsoFast.c index 7393e7fc..10d1384d 100644 --- a/src/aig/saig/saigIsoFast.c +++ b/src/aig/saig/saigIsoFast.c @@ -303,7 +303,7 @@ Vec_Vec_t * Saig_IsoDetectFast( Aig_Man_t * pAig ) // sort the infos clk = Abc_Clock(); - Vec_PtrSort( vInfos, (int (*)(void))Iso_StoCompareVecInt ); + Vec_PtrSort( vInfos, (int (*)(const void *, const void *))Iso_StoCompareVecInt ); // create classes clk = Abc_Clock(); diff --git a/src/aig/saig/saigIsoSlow.c b/src/aig/saig/saigIsoSlow.c index a0e2d1d0..4784d98a 100644 --- a/src/aig/saig/saigIsoSlow.c +++ b/src/aig/saig/saigIsoSlow.c @@ -572,8 +572,8 @@ void Iso_ManCollectClasses( Iso_Man_t * p ) } } clk = Abc_Clock(); - Vec_PtrSort( p->vSingles, (int (*)(void))Iso_ObjCompare ); - Vec_PtrSort( p->vClasses, (int (*)(void))Iso_ObjCompare ); + Vec_PtrSort( p->vSingles, (int (*)(const void *, const void *))Iso_ObjCompare ); + Vec_PtrSort( p->vClasses, (int (*)(const void *, const void *))Iso_ObjCompare ); p->timeSort += Abc_Clock() - clk; assert( Vec_PtrSize(p->vSingles) == p->nSingles ); assert( Vec_PtrSize(p->vClasses) == p->nClasses ); @@ -1115,8 +1115,8 @@ Vec_Int_t * Iso_ManFinalize( Iso_Man_t * p ) Vec_PtrPush( p->vTemp1, pObj ); } // sort CIs by their IDs - Vec_PtrSort( p->vTemp1, (int (*)(void))Iso_ObjCompareByData ); - Vec_PtrSort( p->vTemp2, (int (*)(void))Iso_ObjCompareByData ); + Vec_PtrSort( p->vTemp1, (int (*)(const void *, const void *))Iso_ObjCompareByData ); + Vec_PtrSort( p->vTemp2, (int (*)(const void *, const void *))Iso_ObjCompareByData ); // create the result vRes = Vec_IntAlloc( Aig_ManCiNum(p->pAig) ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vTemp1, pObj, i ) diff --git a/src/aig/saig/saigWnd.c b/src/aig/saig/saigWnd.c index ce70e7b4..949a2728 100644 --- a/src/aig/saig/saigWnd.c +++ b/src/aig/saig/saigWnd.c @@ -106,7 +106,7 @@ Vec_Ptr_t * Saig_ManWindowOutline( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist ) vNodes = Vec_PtrAlloc( 1000 ); Aig_ManIncrementTravId( p ); Saig_ManWindowOutline_rec( p, pObj, nDist, vNodes, pDists ); - Vec_PtrSort( vNodes, (int (*)(void))Aig_ObjCompareIdIncrease ); + Vec_PtrSort( vNodes, (int (*)(const void *, const void *))Aig_ObjCompareIdIncrease ); // make sure LI/LO are labeled/unlabeled mutually Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) assert( Aig_ObjIsTravIdCurrent(p, pObjLi) == diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index 312354da..e7f6c0ad 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -600,7 +600,7 @@ extern ABC_DLL int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk ); /*=== abcCollapse.c ==========================================================*/ -extern ABC_DLL Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fReverse, int fVerbose ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fReverse, int fDumpOrder, int fVerbose ); extern ABC_DLL Abc_Ntk_t * Abc_NtkCollapseSat( Abc_Ntk_t * pNtk, int nCubeLim, int nBTLimit, int nCostMax, int fCanon, int fReverse, int fCnfShared, int fVerbose ); extern ABC_DLL Gia_Man_t * Abc_NtkClpGia( Abc_Ntk_t * pNtk ); /*=== abcCut.c ==========================================================*/ @@ -671,7 +671,7 @@ extern ABC_DLL Abc_Ntk_t * Abc_NtkFraigRestore( int nPatsRand, int nPatsD extern ABC_DLL void Abc_NtkFraigStoreClean(); /*=== abcFunc.c ==========================================================*/ extern ABC_DLL int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk ); -extern ABC_DLL int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit ); +extern ABC_DLL int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit, int fCubeSort ); extern ABC_DLL void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Mem_Flex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 ); extern ABC_DLL void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkSopToAig( Abc_Ntk_t * pNtk ); @@ -752,6 +752,7 @@ extern ABC_DLL void Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkShortNames( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkCleanNames( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkStartNameIds( Abc_Ntk_t * p ); extern ABC_DLL void Abc_NtkTransferNameIds( Abc_Ntk_t * p, Abc_Ntk_t * pNew ); extern ABC_DLL void Abc_NtkUpdateNameIds( Abc_Ntk_t * p ); @@ -761,7 +762,7 @@ extern ABC_DLL Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk ); /*=== abcNtbdd.c ==========================================================*/ extern ABC_DLL Abc_Ntk_t * Abc_NtkDeriveFromBdd( void * dd, void * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi ); -extern ABC_DLL Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk, int fGlobal, int Limit ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk, int fGlobal, int Limit, int fUseAdd ); extern ABC_DLL void * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDropInternal, int fReorder, int fReverse, int fVerbose ); extern ABC_DLL void * Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk, int fFreeMan ); extern ABC_DLL int Abc_NtkSizeOfGlobalBdds( Abc_Ntk_t * pNtk ); diff --git a/src/base/abc/abcCheck.c b/src/base/abc/abcCheck.c index 3e978bf0..a7448530 100644 --- a/src/base/abc/abcCheck.c +++ b/src/base/abc/abcCheck.c @@ -865,7 +865,7 @@ int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk ) vNames = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) ); Abc_NtkForEachCi( pNtk, pObj, i ) Vec_PtrPush( vNames, Abc_ObjName(pObj) ); - Vec_PtrSort( vNames, (int (*)())Abc_NtkNamesCompare ); + Vec_PtrSort( vNames, (int (*)(const void *, const void *))Abc_NtkNamesCompare ); for ( i = 1; i < Abc_NtkCiNum(pNtk); i++ ) if ( !strcmp( (const char *)Vec_PtrEntry(vNames,i-1), (const char *)Vec_PtrEntry(vNames,i) ) ) { @@ -896,7 +896,7 @@ int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk ) vNames = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) Vec_PtrPush( vNames, Abc_ObjName(pObj) ); - Vec_PtrSort( vNames, (int (*)())Abc_NtkNamesCompare ); + Vec_PtrSort( vNames, (int (*)(const void *, const void *))Abc_NtkNamesCompare ); for ( i = 1; i < Abc_NtkCoNum(pNtk); i++ ) { // printf( "%s\n", Vec_PtrEntry(vNames,i) ); diff --git a/src/base/abc/abcDfs.c b/src/base/abc/abcDfs.c index 731d35f5..a1345db8 100644 --- a/src/base/abc/abcDfs.c +++ b/src/base/abc/abcDfs.c @@ -897,9 +897,9 @@ Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNod vNodes = Vec_PtrAlloc( 100 ); // go through the PO nodes and call for each of them for ( i = 0; i < nNodes; i++ ) - if ( Abc_ObjIsCo(ppNodes[i]) ) + if ( Abc_ObjIsCo(ppNodes[i]) && Abc_ObjFaninNum(Abc_ObjFanin0(ppNodes[i])) != 0 ) Abc_NtkNodeSupport_rec( Abc_ObjFanin0(ppNodes[i]), vNodes ); - else + else if ( !Abc_ObjIsCo(ppNodes[i]) && Abc_ObjFaninNum(ppNodes[i]) != 0 ) Abc_NtkNodeSupport_rec( ppNodes[i], vNodes ); return vNodes; } diff --git a/src/base/abc/abcFanOrder.c b/src/base/abc/abcFanOrder.c index 12df7d85..949170aa 100644 --- a/src/base/abc/abcFanOrder.c +++ b/src/base/abc/abcFanOrder.c @@ -476,9 +476,9 @@ void Abc_NodeSortCubes( Abc_Obj_t * pNode, Vec_Ptr_t * vCubes, Vec_Str_t * vStor Vec_PtrPush( vCubes, pCube ); } if ( fWeight ) - Vec_PtrSort( vCubes, (int (*)())Abc_NodeCompareCubes2 ); + Vec_PtrSort( vCubes, (int (*)(const void *, const void *))Abc_NodeCompareCubes2 ); else - Vec_PtrSort( vCubes, (int (*)())Abc_NodeCompareCubes1 ); + Vec_PtrSort( vCubes, (int (*)(const void *, const void *))Abc_NodeCompareCubes1 ); Vec_StrGrow( vStore, Vec_PtrSize(vCubes) * (nVars + 3) ); pPivot = Vec_StrArray( vStore ); Vec_PtrForEachEntry( char *, vCubes, pCube, i ) diff --git a/src/base/abc/abcFunc.c b/src/base/abc/abcFunc.c index 8f68d4be..84ecf7bf 100644 --- a/src/base/abc/abcFunc.c +++ b/src/base/abc/abcFunc.c @@ -356,7 +356,7 @@ char * Abc_ConvertBddToSop( Mem_Flex_t * pMan, DdManager * dd, DdNode * bFuncOn, SeeAlso [] ***********************************************************************/ -int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit ) +int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit, int fCubeSort ) { Vec_Int_t * vGuide; Vec_Str_t * vCube; @@ -445,6 +445,7 @@ int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit ) Extra_StopManager( dd ); // reorder fanins and cubes to make SOPs more human-readable + if ( fCubeSort ) Abc_NtkSortSops( pNtk ); return 1; } @@ -788,7 +789,7 @@ DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot ) #else int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk ) { return 1; } -int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit ) { return 1; } +int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit, int fCubeSort ) { return 1; } void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Mem_Flex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 ) {} void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ) {} int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk ) { return 1; } @@ -1178,17 +1179,17 @@ int Abc_NtkToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit ) return 1; if ( !Abc_NtkSopToBdd(pNtk) ) return 0; - return Abc_NtkBddToSop(pNtk, fMode, nCubeLimit); + return Abc_NtkBddToSop(pNtk, fMode, nCubeLimit, 1); } if ( Abc_NtkHasMapping(pNtk) ) return Abc_NtkMapToSop(pNtk); if ( Abc_NtkHasBdd(pNtk) ) - return Abc_NtkBddToSop(pNtk, fMode, nCubeLimit); + return Abc_NtkBddToSop(pNtk, fMode, nCubeLimit, 1); if ( Abc_NtkHasAig(pNtk) ) { if ( !Abc_NtkAigToBdd(pNtk) ) return 0; - return Abc_NtkBddToSop(pNtk, fMode, nCubeLimit); + return Abc_NtkBddToSop(pNtk, fMode, nCubeLimit, 1); } assert( 0 ); return 0; @@ -1253,7 +1254,7 @@ int Abc_NtkToAig( Abc_Ntk_t * pNtk ) } if ( Abc_NtkHasBdd(pNtk) ) { - if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY) ) + if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY, 1) ) return 0; return Abc_NtkSopToAig(pNtk); } diff --git a/src/base/abc/abcHie.c b/src/base/abc/abcHie.c index 8397301f..bd08c35d 100644 --- a/src/base/abc/abcHie.c +++ b/src/base/abc/abcHie.c @@ -442,7 +442,7 @@ void Abc_NtkPrintBoxInfo( Abc_Ntk_t * pNtk ) } // sort models by name vMods = pNtk->pDesign->vModules; - Vec_PtrSort( vMods, (int(*)())Abc_NtkCompareNames ); + Vec_PtrSort( vMods, (int(*)(const void *, const void *))Abc_NtkCompareNames ); // Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) // printf( "%s\n", Abc_NtkName(pModel) ); diff --git a/src/base/abc/abcHieNew.c b/src/base/abc/abcHieNew.c index 0f191707..54a61609 100644 --- a/src/base/abc/abcHieNew.c +++ b/src/base/abc/abcHieNew.c @@ -558,7 +558,7 @@ void Au_ManPrintBoxInfo( Au_Ntk_t * pNtk ) vMods->nSize--; vMods->pArray++; // sort models by name - Vec_PtrSort( vMods, (int(*)())Au_NtkCompareNames ); + Vec_PtrSort( vMods, (int(*)(const void *, const void *))Au_NtkCompareNames ); // swap the first model Num = Vec_PtrFind( vMods, pNtk ); assert( Num >= 0 && Num < Vec_PtrSize(vMods) ); @@ -643,7 +643,7 @@ void Au_ManPrintBoxInfoSorted( Au_Ntk_t * pNtk ) vMods->pArray--; vMods->nSize++; - Vec_PtrSort( vModsNew, (int(*)())Au_NtkCompareSign ); + Vec_PtrSort( vModsNew, (int(*)(const void *, const void *))Au_NtkCompareSign ); Vec_PtrForEachEntryStart( Au_Ntk_t *, vModsNew, pModel, i, 1 ) { printf( "MODULE " ); diff --git a/src/base/abc/abcLatch.c b/src/base/abc/abcLatch.c index fcace105..d8432382 100644 --- a/src/base/abc/abcLatch.c +++ b/src/base/abc/abcLatch.c @@ -148,7 +148,7 @@ int Abc_NtkRemoveSelfFeedLatches( Abc_Ntk_t * pNtk ) void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches ) { Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj, * pLatch, * pFanin, * pFanout; + Abc_Obj_t * pObj, * pFanin, * pFanout; int i, k, nTotal, nDigits; if ( nLatches < 1 ) return; @@ -157,18 +157,9 @@ void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches ) vNodes = Vec_PtrAlloc( 100 ); Abc_NtkForEachPi( pNtk, pObj, i ) { - // remember current fanins of the PI Abc_NodeCollectFanouts( pObj, vNodes ); - // create the latches - for ( pFanin = pObj, k = 0; k < nLatches; k++, pFanin = pLatch ) - { - pLatch = Abc_NtkCreateLatch( pNtk ); - Abc_ObjAddFanin( pLatch, pFanin ); - Abc_LatchSetInitDc( pLatch ); - // create the name of the new latch - Abc_ObjAssignName( pLatch, Abc_ObjNameDummy("LL", i*nLatches + k, nDigits), NULL ); - } - // patch the PI fanouts + for ( pFanin = pObj, k = 0; k < nLatches; k++ ) + pFanin = Abc_NtkAddLatch( pNtk, pFanin, ABC_INIT_ZERO ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pFanout, k ) Abc_ObjPatchFanin( pFanout, pObj, pFanin ); } diff --git a/src/base/abc/abcMinBase.c b/src/base/abc/abcMinBase.c index 22d1e285..3f441e99 100644 --- a/src/base/abc/abcMinBase.c +++ b/src/base/abc/abcMinBase.c @@ -72,7 +72,7 @@ int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -int Abc_NodeMinimumBase( Abc_Obj_t * pNode ) +int Abc_NodeMinimumBase_buggy( Abc_Obj_t * pNode ) { Vec_Str_t * vSupport; Vec_Ptr_t * vFanins; @@ -107,6 +107,55 @@ int Abc_NodeMinimumBase( Abc_Obj_t * pNode ) return 1; } +int Abc_NodeMinimumBase( Abc_Obj_t * pNode ) +{ + DdManager * dd = (DdManager *)pNode->pNtk->pManFunc; + DdNode * bTemp, ** pbVars; + Vec_Str_t * vSupport; + int i, nVars, j, iFanin, iFanin2, k = 0; + + assert( Abc_NtkIsBddLogic(pNode->pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + + // compute support + vSupport = Vec_StrAlloc( 10 ); + nVars = Abc_NodeSupport( Cudd_Regular(pNode->pData), vSupport, Abc_ObjFaninNum(pNode) ); + if ( nVars == Abc_ObjFaninNum(pNode) ) + { + Vec_StrFree( vSupport ); + return 0; + } + + // remove unused fanins + pbVars = ABC_CALLOC( DdNode *, Abc_ObjFaninNum(pNode) ); + Vec_IntForEachEntry( &pNode->vFanins, iFanin, i ) + { + Abc_Obj_t * pFanin = Abc_NtkObj( pNode->pNtk, iFanin ); + if ( !Vec_StrEntry(vSupport, i) ) + { + if ( !Vec_IntRemove( &pFanin->vFanouts, pNode->Id ) ) + printf( "The obj %d is not found among the fanouts of obj %d ...\n", pNode->Id, iFanin ); + continue; + } + Vec_IntForEachEntryStop( &pNode->vFanins, iFanin2, j, k ) + if ( iFanin == iFanin2 ) + break; + if ( j == k ) + Vec_IntWriteEntry( &pNode->vFanins, k++, iFanin ); + else if ( !Vec_IntRemove( &pFanin->vFanouts, pNode->Id ) ) + printf( "The obj %d is not found among the fanouts of obj %d ...\n", pNode->Id, iFanin ); + pbVars[i] = Cudd_bddIthVar( dd, j ); + } + Vec_IntShrink( &pNode->vFanins, k ); + + // update the function of the node + pNode->pData = Cudd_bddVectorCompose( dd, bTemp = (DdNode *)pNode->pData, pbVars ); Cudd_Ref( (DdNode *)pNode->pData ); + Cudd_RecursiveDeref( dd, bTemp ); + Vec_StrFree( vSupport ); + ABC_FREE( pbVars ); + return 1; +} + /**Function************************************************************* Synopsis [Makes nodes of the network fanin-dup-free.] @@ -447,7 +496,7 @@ int Abc_NtkEliminate( Abc_Ntk_t * pNtk, int nMaxSize, int fReverse, int fVerbose return 0; } // prepare nodes for sweeping - Abc_NtkRemoveDupFanins( pNtk ); + //Abc_NtkRemoveDupFanins( pNtk ); Abc_NtkMinimumBase( pNtk ); Abc_NtkCleanup( pNtk, 0 ); // get the nodes in the given order @@ -703,7 +752,7 @@ void Abc_ObjSortInReverseOrder( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ) vOrder = Abc_NtkDfsReverse( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pNode, i ) pNode->iTemp = i; - Vec_PtrSort( vNodes, (int (*)())Abc_ObjCompareByNumber ); + Vec_PtrSort( vNodes, (int (*)(const void *, const void *))Abc_ObjCompareByNumber ); Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pNode, i ) pNode->iTemp = 0; Vec_PtrFree( vOrder ); @@ -740,7 +789,7 @@ int Abc_NtkEliminateSpecial( Abc_Ntk_t * pNtk, int nMaxSize, int fVerbose ) } // prepare nodes for sweeping - Abc_NtkRemoveDupFanins( pNtk ); + //Abc_NtkRemoveDupFanins( pNtk ); Abc_NtkMinimumBase( pNtk ); Abc_NtkCleanup( pNtk, 0 ); diff --git a/src/base/abc/abcNames.c b/src/base/abc/abcNames.c index fe9b3dca..dec5f01e 100644 --- a/src/base/abc/abcNames.c +++ b/src/base/abc/abcNames.c @@ -606,6 +606,17 @@ void Abc_NtkShortNames( Abc_Ntk_t * pNtk ) Abc_NtkAddDummyPoNames( pNtk ); Abc_NtkAddDummyBoxNames( pNtk ); } +void Abc_NtkCleanNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; int i; + Nm_Man_t * pManName = Nm_ManCreate( Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk) + Abc_NtkBoxNum(pNtk) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Nm_ManStoreIdName( pManName, pObj->Id, pObj->Type, Abc_ObjName(pObj), NULL ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Nm_ManStoreIdName( pManName, pObj->Id, pObj->Type, Abc_ObjName(pObj), NULL ); + Nm_ManFree( pNtk->pManName ); + pNtk->pManName = pManName; +} /**Function************************************************************* diff --git a/src/base/abc/abcNtk.c b/src/base/abc/abcNtk.c index 7c54f3c4..f8e40b41 100644 --- a/src/base/abc/abcNtk.c +++ b/src/base/abc/abcNtk.c @@ -1286,6 +1286,7 @@ void Abc_NtkDelete( Abc_Ntk_t * pNtk ) Abc_Obj_t * pObj; void * pAttrMan; int TotalMemory, i; + int fWarning = 0; // int LargePiece = (4 << ABC_NUM_STEPS); if ( pNtk == NULL ) return; @@ -1310,9 +1311,11 @@ void Abc_NtkDelete( Abc_Ntk_t * pNtk ) // ABC_FREE( pObj->vFanouts.pArray ); // these flags should be always zero // if this is not true, something is wrong somewhere - assert( pObj->fMarkA == 0 ); - assert( pObj->fMarkB == 0 ); - assert( pObj->fMarkC == 0 ); +// assert( pObj->fMarkA == 0 ); +// assert( pObj->fMarkB == 0 ); +// assert( pObj->fMarkC == 0 ); + if ( !fWarning && (pObj->fMarkA || pObj->fMarkB || pObj->fMarkC) ) + { printf( "Flags A, B, or C are not zero.\n" ), fWarning = 1; } } // free the nodes if ( pNtk->pMmStep == NULL ) diff --git a/src/base/abc/abcObj.c b/src/base/abc/abcObj.c index 533f1f73..65ea91dc 100644 --- a/src/base/abc/abcObj.c +++ b/src/base/abc/abcObj.c @@ -393,6 +393,7 @@ Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName } else if ( Abc_ObjIsLatch(pObj) ) // copy the reset value pObjNew->pData = pObj->pData; + pObjNew->fPersist = pObj->fPersist; // transfer HAIG // pObjNew->pEquiv = pObj->pEquiv; // remember the new node in the old node diff --git a/src/base/abc/abcShow.c b/src/base/abc/abcShow.c index 7df1e323..dd8e9efe 100644 --- a/src/base/abc/abcShow.c +++ b/src/base/abc/abcShow.c @@ -121,7 +121,7 @@ void Abc_NodeShowBdd( Abc_Obj_t * pNode, int fCompl ) // visualize the file Abc_ShowFile( FileNameDot ); } -void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl ) +void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl, int fReorder ) { char FileNameDot[200]; char ** ppNamesIn, ** ppNamesOut; @@ -131,7 +131,7 @@ void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl ) FILE * pFile; assert( Abc_NtkIsStrash(pNtk) ); - dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, 0, 0 ); + dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, fReorder, 0, 0 ); if ( dd == NULL ) { printf( "Construction of global BDDs has failed.\n" ); @@ -186,7 +186,7 @@ void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl ) #else void Abc_NodeShowBdd( Abc_Obj_t * pNode, int fCompl ) {} -void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl ) {} +void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl, int fReorder ) {} #endif /**Function************************************************************* diff --git a/src/base/abc/abcUtil.c b/src/base/abc/abcUtil.c index 1f0c9725..29753210 100644 --- a/src/base/abc/abcUtil.c +++ b/src/base/abc/abcUtil.c @@ -3122,7 +3122,10 @@ Vec_Wec_t * Abc_SopSynthesize( Vec_Ptr_t * vSops ) Abc_Obj_t * pObj, * pFanin; int i, k, iNode = 0; Abc_FrameReplaceCurrentNetwork( Abc_FrameReadGlobalFrame(), pNtk ); - Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "fx; strash; balance; dc2; map -a" ); + //Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "fx; strash; balance; dc2; map -a" ); + Abc_FrameSetBatchMode( 1 ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "st; collapse; sop; fx; strash; &get; &ps; &deepsyn -I 4 -J 50 -T 5 -S 111 -t; &ps; &put; map -a" ); + Abc_FrameSetBatchMode( 0 ); pNtkNew = Abc_FrameReadNtk( Abc_FrameReadGlobalFrame() ); vRes = Vec_WecStart( Abc_NtkPiNum(pNtkNew) + Abc_NtkNodeNum(pNtkNew) + Abc_NtkPoNum(pNtkNew) ); Abc_NtkForEachPi( pNtkNew, pObj, i ) @@ -3149,7 +3152,9 @@ Vec_Wec_t * Abc_GiaSynthesize( Vec_Ptr_t * vGias, Gia_Man_t * pMulti ) Abc_Obj_t * pObj, * pFanin; int i, k, iNode = 0; Abc_FrameReplaceCurrentNetwork( Abc_FrameReadGlobalFrame(), pNtk ); - Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "compress2rs; dch; map -a; strash; compress2rs; dch; map -a; strash; compress2rs; dch; map -a" ); + Abc_FrameSetBatchMode( 1 ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "clp; sop; fx; strash; compress2rs; dch; map -a; strash; compress2rs; dch; map -a" ); + Abc_FrameSetBatchMode( 0 ); pNtkNew = Abc_FrameReadNtk( Abc_FrameReadGlobalFrame() ); vRes = Vec_WecStart( Abc_NtkPiNum(pNtkNew) + Abc_NtkNodeNum(pNtkNew) + Abc_NtkPoNum(pNtkNew) ); Abc_NtkForEachPi( pNtkNew, pObj, i ) @@ -3253,9 +3258,11 @@ Gia_Man_t * Abc_SopSynthesizeOne( char * pSop, int fClp ) pNtk = Abc_NtkCreateFromSops( "top", vSops ); Vec_PtrFree( vSops ); Abc_FrameReplaceCurrentNetwork( Abc_FrameReadGlobalFrame(), pNtk ); + Abc_FrameSetBatchMode( 1 ); if ( fClp ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "clp; sop" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "fx; strash; balance; dc2" ); + Abc_FrameSetBatchMode( 0 ); pNtkNew = Abc_FrameReadNtk( Abc_FrameReadGlobalFrame() ); return Abc_NtkStrashToGia( pNtkNew ); } diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 85053e18..29732bc6 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -86,7 +86,9 @@ static int Abc_CommandPrintMffc ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandPrintFactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintLevel ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintSupport ( Abc_Frame_t * pAbc, int argc, char ** argv ); +#ifdef ABC_USE_CUDD static int Abc_CommandPrintMint ( Abc_Frame_t * pAbc, int argc, char ** argv ); +#endif static int Abc_CommandPrintSymms ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintUnate ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintAuto ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -138,7 +140,6 @@ static int Abc_CommandTestRPO ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandTestTruth ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRunEco ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRunGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandRunSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRunTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -193,6 +194,7 @@ static int Abc_CommandCone ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandNode ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCof ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTopmost ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBottommost ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTopAnd ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTrim ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandShortNames ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -378,6 +380,7 @@ static int Abc_CommandAbcLoad ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Get ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Put ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9MoveNames ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Save ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Save2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SaveAig ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -399,6 +402,7 @@ static int Abc_CommandAbc9Status ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9MuxProfile ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9MuxPos ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9MuxStr ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9MuxDec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9PrintTruth ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Unate ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Rex2Gia ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -412,9 +416,11 @@ static int Abc_CommandAbc9Cof ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Trim ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Dfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Sim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Sim2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Sim3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9MLGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9MLTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Iwls21Test ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9ReadSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9WriteSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9PrintSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -435,8 +441,11 @@ static int Abc_CommandAbc9Dsd ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Bidec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Shrink ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Fx ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Extract ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Balance ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9BalanceLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Resub ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Reshape ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Syn2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Syn3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Syn4 ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -482,6 +491,11 @@ static int Abc_CommandAbc9Of ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Pack ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Edge ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SatLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9LNetRead ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9LNetSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9LNetEval ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9LNetOpt ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9LNetMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Unmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Struct ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Trace ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -503,6 +517,7 @@ static int Abc_CommandAbc9Mesh ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Iso ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9IsoNpn ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9IsoSt ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Compare ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9CexInfo ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Cycle ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Cone ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -540,6 +555,7 @@ static int Abc_CommandAbc9Exorcism ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Mfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Mfsd ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9DeepSyn ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9StochSyn ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandAbc9PoPart2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandAbc9CexCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandAbc9CexMerge ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -572,6 +588,9 @@ extern int Abc_CommandNChooseK ( Abc_Frame_t * pAbc, int argc, cha extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); +extern Vec_Ptr_t * Abc_NtkCollectCiNames( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkCollectCoNames( Abc_Ntk_t * pNtk ); + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -754,6 +773,11 @@ void Abc_FrameUpdateGia( Abc_Frame_t * pAbc, Gia_Man_t * pNew ) pNew->vNamesOut = pAbc->pGia->vNamesOut; pAbc->pGia->vNamesOut = NULL; } + if (!pNew->vNamesNode && pAbc->pGia && pAbc->pGia->vNamesNode && Gia_ManObjNum(pNew) == Vec_PtrSize(pAbc->pGia->vNamesNode)) + { + pNew->vNamesNode = pAbc->pGia->vNamesNode; + pAbc->pGia->vNamesNode = NULL; + } // update if ( pAbc->pGia2 ) Gia_ManStop( pAbc->pGia2 ); @@ -806,7 +830,9 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Printing", "print_factor", Abc_CommandPrintFactor, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_level", Abc_CommandPrintLevel, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_supp", Abc_CommandPrintSupport, 0 ); +#ifdef ABC_USE_CUDD Cmd_CommandAdd( pAbc, "Printing", "print_mint", Abc_CommandPrintMint, 0 ); +#endif Cmd_CommandAdd( pAbc, "Printing", "print_symm", Abc_CommandPrintSymms, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_unate", Abc_CommandPrintUnate, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_auto", Abc_CommandPrintAuto, 0 ); @@ -858,8 +884,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "testtruth", Abc_CommandTestTruth, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "runeco", Abc_CommandRunEco, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "rungen", Abc_CommandRunGen, 0 ); - Cmd_CommandAdd( pAbc, "Synthesis", "runsim", Abc_CommandRunSim, 0 ); - Cmd_CommandAdd( pAbc, "Synthesis", "runtest", Abc_CommandRunTest, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "xec", Abc_CommandRunTest, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "rewrite", Abc_CommandRewrite, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "refactor", Abc_CommandRefactor, 1 ); @@ -914,6 +939,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Various", "node", Abc_CommandNode, 1 ); Cmd_CommandAdd( pAbc, "Various", "cof", Abc_CommandCof, 1 ); Cmd_CommandAdd( pAbc, "Various", "topmost", Abc_CommandTopmost, 1 ); + Cmd_CommandAdd( pAbc, "Various", "bottommost", Abc_CommandBottommost, 1 ); Cmd_CommandAdd( pAbc, "Various", "topand", Abc_CommandTopAnd, 1 ); Cmd_CommandAdd( pAbc, "Various", "trim", Abc_CommandTrim, 1 ); Cmd_CommandAdd( pAbc, "Various", "short_names", Abc_CommandShortNames, 0 ); @@ -1013,7 +1039,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Sequential", "zero", Abc_CommandZero, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "undc", Abc_CommandUndc, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "onehot", Abc_CommandOneHot, 1 ); -// Cmd_CommandAdd( pAbc, "Sequential", "pipe", Abc_CommandPipe, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "pipe", Abc_CommandPipe, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "retime", Abc_CommandRetime, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "dretime", Abc_CommandDRetime, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "fretime", Abc_CommandFlowRetime, 1 ); @@ -1095,6 +1121,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&get", Abc_CommandAbc9Get, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&put", Abc_CommandAbc9Put, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&move_names", Abc_CommandAbc9MoveNames, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&save", Abc_CommandAbc9Save, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&save2", Abc_CommandAbc9Save2, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&saveaig", Abc_CommandAbc9SaveAig, 0 ); @@ -1118,6 +1145,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&profile", Abc_CommandAbc9MuxProfile, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&muxpos", Abc_CommandAbc9MuxPos, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&muxstr", Abc_CommandAbc9MuxStr, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&muxdec", Abc_CommandAbc9MuxDec, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&print_truth", Abc_CommandAbc9PrintTruth, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&unate", Abc_CommandAbc9Unate, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&rex2gia", Abc_CommandAbc9Rex2Gia, 0 ); @@ -1131,9 +1159,11 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&trim", Abc_CommandAbc9Trim, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&dfs", Abc_CommandAbc9Dfs, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&sim", Abc_CommandAbc9Sim, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sim2", Abc_CommandAbc9Sim2, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&sim3", Abc_CommandAbc9Sim3, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&mlgen", Abc_CommandAbc9MLGen, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&mltest", Abc_CommandAbc9MLTest, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&iwls21test", Abc_CommandAbc9Iwls21Test, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&sim_read", Abc_CommandAbc9ReadSim, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&sim_write", Abc_CommandAbc9WriteSim, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&sim_print", Abc_CommandAbc9PrintSim, 0 ); @@ -1154,8 +1184,11 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&bidec", Abc_CommandAbc9Bidec, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&shrink", Abc_CommandAbc9Shrink, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&fx", Abc_CommandAbc9Fx, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&extract", Abc_CommandAbc9Extract, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&b", Abc_CommandAbc9Balance, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&blut", Abc_CommandAbc9BalanceLut, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&resub", Abc_CommandAbc9Resub, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&reshape", Abc_CommandAbc9Reshape, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&syn2", Abc_CommandAbc9Syn2, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&syn3", Abc_CommandAbc9Syn3, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&syn4", Abc_CommandAbc9Syn4, 0 ); @@ -1201,6 +1234,11 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&pack", Abc_CommandAbc9Pack, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&edge", Abc_CommandAbc9Edge, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&satlut", Abc_CommandAbc9SatLut, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&lnetread", Abc_CommandAbc9LNetRead, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&lnetsim", Abc_CommandAbc9LNetSim, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&lneteval", Abc_CommandAbc9LNetEval, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&lnetopt", Abc_CommandAbc9LNetOpt, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&lnetmap", Abc_CommandAbc9LNetMap, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&unmap", Abc_CommandAbc9Unmap, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&struct", Abc_CommandAbc9Struct, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&trace", Abc_CommandAbc9Trace, 0 ); @@ -1222,6 +1260,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&iso", Abc_CommandAbc9Iso, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&isonpn", Abc_CommandAbc9IsoNpn, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&isost", Abc_CommandAbc9IsoSt, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&compare", Abc_CommandAbc9Compare, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cexinfo", Abc_CommandAbc9CexInfo, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cycle", Abc_CommandAbc9Cycle, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cone", Abc_CommandAbc9Cone, 0 ); @@ -1259,6 +1298,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&mfs", Abc_CommandAbc9Mfs, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&mfsd", Abc_CommandAbc9Mfsd, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&deepsyn", Abc_CommandAbc9DeepSyn, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&stochsyn", Abc_CommandAbc9StochSyn, 0 ); // Cmd_CommandAdd( pAbc, "ABC9", "&popart2", Abc_CommandAbc9PoPart2, 0 ); // Cmd_CommandAdd( pAbc, "ABC9", "&cexcut", Abc_CommandAbc9CexCut, 0 ); // Cmd_CommandAdd( pAbc, "ABC9", "&cexmerge", Abc_CommandAbc9CexMerge, 0 ); @@ -2075,6 +2115,7 @@ usage: SeeAlso [] ***********************************************************************/ +#ifdef ABC_USE_CUDD int Abc_CommandPrintMint( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); @@ -2113,6 +2154,7 @@ int Abc_CommandPrintMint( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "This command works only for logic networks with local functions represented by BDDs.\n" ); return 1; } + Abc_NtkForEachNode( pNtk, pObj, c ) printf( "ObjId %3d : SuppSize = %5d MintCount = %32.0f\n", c, Abc_ObjFaninNum(pObj), Cudd_CountMinterm((DdManager *)pNtk->pManFunc, (DdNode *)pObj->pData, Abc_ObjFaninNum(pObj)) ); @@ -2125,6 +2167,7 @@ usage: Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } +#endif /**Function************************************************************* @@ -3152,13 +3195,13 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Obj_t * pNode; - int c, fCompl = 0, fGlobal = 0; + int c, fCompl = 0, fGlobal = 0, fReorder = 1; extern void Abc_NodeShowBdd( Abc_Obj_t * pNode, int fCompl ); - extern void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl ); + extern void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl, int fReorder ); // set defaults Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "cgh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "cgrh" ) ) != EOF ) { switch ( c ) { @@ -3168,6 +3211,9 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'g': fGlobal ^= 1; break; + case 'r': + fReorder ^= 1; + break; case 'h': goto usage; default: @@ -3184,7 +3230,7 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( fGlobal ) { Abc_Ntk_t * pTemp = Abc_NtkIsStrash(pNtk) ? pNtk : Abc_NtkStrash(pNtk, 0, 0, 0); - Abc_NtkShowBdd( pTemp, fCompl ); + Abc_NtkShowBdd( pTemp, fCompl, fReorder ); if ( pTemp != pNtk ) Abc_NtkDelete( pTemp ); return 0; @@ -3222,7 +3268,7 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: show_bdd [-cgh] <node>\n" ); + Abc_Print( -2, "usage: show_bdd [-cgrh] <node>\n" ); Abc_Print( -2, " uses DOT and GSVIEW to visualize the global BDDs of primary outputs\n" ); Abc_Print( -2, " in terms of primary inputs or the local BDD of a node in terms of its fanins\n" ); #ifdef WIN32 @@ -3232,6 +3278,7 @@ usage: Abc_Print( -2, "\t<node>: (optional) the node to consider [default = the driver of the first PO]\n"); Abc_Print( -2, "\t-c : toggle visualizing BDD with complemented edges [default = %s].\n", fCompl? "yes": "no" ); Abc_Print( -2, "\t-g : toggle visualizing the global BDDs of primary outputs [default = %s].\n", fGlobal? "yes": "no" ); + Abc_Print( -2, "\t-r : toggles dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -3353,6 +3400,7 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) int fDualRail; int fReorder; int fReverse; + int fDumpOrder; int c; char * pLogFileName = NULL; pNtk = Abc_FrameReadNtk(pAbc); @@ -3362,9 +3410,10 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) fReorder = 1; fReverse = 0; fDualRail = 0; + fDumpOrder = 0; fBddSizeMax = ABC_INFINITY; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "BLrodvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "BLrodxvh" ) ) != EOF ) { switch ( c ) { @@ -3397,6 +3446,9 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'd': fDualRail ^= 1; break; + case 'x': + fDumpOrder ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -3421,11 +3473,11 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) // get the new network if ( Abc_NtkIsStrash(pNtk) ) - pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fReverse, fVerbose ); + pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fReverse, fDumpOrder, fVerbose ); else { pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); - pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fReverse, fVerbose ); + pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fReverse, fDumpOrder, fVerbose ); Abc_NtkDelete( pNtk ); } if ( pNtkRes == NULL ) @@ -3448,13 +3500,14 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: collapse [-B <num>] [-L file] [-rodvh]\n" ); + Abc_Print( -2, "usage: collapse [-B <num>] [-L file] [-rodxvh]\n" ); Abc_Print( -2, "\t collapses the network by constructing global BDDs\n" ); Abc_Print( -2, "\t-B <num>: limit on live BDD nodes during collapsing [default = %d]\n", fBddSizeMax ); Abc_Print( -2, "\t-L file : the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); Abc_Print( -2, "\t-r : toggles dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" ); Abc_Print( -2, "\t-o : toggles reverse variable ordering [default = %s]\n", fReverse? "yes": "no" ); Abc_Print( -2, "\t-d : toggles dual-rail collapsing mode [default = %s]\n", fDualRail? "yes": "no" ); + Abc_Print( -2, "\t-x : toggles dumping file \"order.txt\" with variable order [default = %s]\n", fDumpOrder? "yes": "no" ); Abc_Print( -2, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -5417,7 +5470,7 @@ int Abc_CommandMfs2( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults Sfm_ParSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCZNIdaeijvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCZNIdaeijlvwh" ) ) != EOF ) { switch ( c ) { @@ -5535,6 +5588,9 @@ int Abc_CommandMfs2( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'j': fUseAllFfs ^= 1; break; + case 'l': + pPars->fUseDcs ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -5606,7 +5662,7 @@ int Abc_CommandMfs2( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: mfs2 [-WFDMLCZNI <num>] [-daeijvwh]\n" ); + Abc_Print( -2, "usage: mfs2 [-WFDMLCZNI <num>] [-daeijlvwh]\n" ); Abc_Print( -2, "\t performs don't-care-based optimization of logic networks\n" ); Abc_Print( -2, "\t-W <num> : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nTfoLevMax ); Abc_Print( -2, "\t-F <num> : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nFanoutMax ); @@ -5622,6 +5678,7 @@ usage: Abc_Print( -2, "\t-i : toggle using inductive don't-cares [default = %s]\n", fIndDCs? "yes": "no" ); Abc_Print( -2, "\t-j : toggle using all flops when \"-i\" is enabled [default = %s]\n", fUseAllFfs? "yes": "no" ); Abc_Print( -2, "\t-I : the number of additional frames inserted [default = %d]\n", nFramesAdd ); + Abc_Print( -2, "\t-l : toggle deriving don't-cares [default = %s]\n", pPars->fUseDcs? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -7051,20 +7108,37 @@ usage: ***********************************************************************/ int Abc_CommandRunEco( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Acb_NtkRunEco( char * pFileNames[4], int fCheck, int fRandom, int fVerbose, int fVeryVerbose ); + extern void Acb_NtkRunEco( char * pFileNames[4], int nTimeout, int fCheck, int fRandom, int fInputs, int fUnitW, int fVerbose, int fVeryVerbose ); char * pFileNames[4] = {NULL}; - int c, fCheck = 0, fRandom = 0, fVerbose = 0, fVeryVerbose = 0; + int c, nTimeout = 0, fCheck = 0, fRandom = 0, fInputs = 0, fUnitW = 0, fVerbose = 0, fVeryVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "crvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Tcriuvwh" ) ) != EOF ) { switch ( c ) { + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + nTimeout = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nTimeout < 0 ) + goto usage; + break; case 'c': fCheck ^= 1; break; case 'r': fRandom ^= 1; break; + case 'i': + fInputs ^= 1; + break; + case 'u': + fUnitW ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -7096,11 +7170,11 @@ int Abc_CommandRunEco( Abc_Frame_t * pAbc, int argc, char ** argv ) fclose( pFile ); pFileNames[c] = argv[globalUtilOptind+c]; } - Acb_NtkRunEco( pFileNames, fCheck, fRandom, fVerbose, fVeryVerbose ); + Acb_NtkRunEco( pFileNames, nTimeout, fCheck, fRandom, fInputs, fUnitW, fVerbose, fVeryVerbose ); return 0; usage: - Abc_Print( -2, "usage: runeco [-crvwh] <implementation> <specification> <weights>\n" ); + Abc_Print( -2, "usage: runeco [-T num] [-criuvwh] <implementation> <specification> <weights>\n" ); Abc_Print( -2, "\t performs computation of patch functions during ECO,\n" ); Abc_Print( -2, "\t as described in the following paper: A. Q. Dao et al\n" ); Abc_Print( -2, "\t \"Efficient computation of ECO patch functions\", Proc. DAC\'18\n" ); @@ -7108,8 +7182,11 @@ usage: Abc_Print( -2, "\t (currently only applicable to benchmarks from 2017 ICCAD CAD competition\n" ); Abc_Print( -2, "\t http://cad-contest-2017.el.cycu.edu.tw/Problem_A/default.html as follows:\n" ); Abc_Print( -2, "\t \"runeco unit1/F.v unit1/G.v unit1/weight.txt; cec -n out.v unit1/G.v\")\n" ); + Abc_Print( -2, "\t-T num : the timeout in seconds [default = %d]\n", nTimeout ); Abc_Print( -2, "\t-c : toggle checking that the problem has a solution [default = %s]\n", fCheck? "yes": "no" ); Abc_Print( -2, "\t-r : toggle using random permutation of support variables [default = %s]\n", fRandom? "yes": "no" ); + Abc_Print( -2, "\t-i : toggle using primary inputs as support variables [default = %s]\n", fInputs? "yes": "no" ); + Abc_Print( -2, "\t-u : toggle using unit weights [default = %s]\n", fUnitW? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing more verbose information [default = %s]\n", fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -7176,139 +7253,6 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandRunSim( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - extern void Acb_NtkRunSim( char * pFileName[4], int nWords, int nBeam, int LevL, int LevU, int fOrder, int fFancy, int fUseBuf, int fRandom, int fUseWeights, int fVerbose, int fVeryVerbose ); - char * pFileNames[4] = {NULL, NULL, "out.v", NULL}; - int c, nWords = 8, nBeam = 4, LevL = -1, LevU = -1, fOrder = 0, fFancy = 0, fUseBuf = 0, fRandom = 0, fUseWeights = 0, fVerbose = 0, fVeryVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WBLUofbruvwh" ) ) != EOF ) - { - switch ( c ) - { - case 'W': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); - goto usage; - } - nWords = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nWords < 0 ) - goto usage; - break; - case 'B': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" ); - goto usage; - } - nBeam = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nBeam < 0 ) - goto usage; - break; - case 'L': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); - goto usage; - } - LevL = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( LevL < 0 ) - goto usage; - break; - case 'U': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-U\" should be followed by an integer.\n" ); - goto usage; - } - LevU = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( LevU < 0 ) - goto usage; - break; - case 'o': - fOrder ^= 1; - break; - case 'f': - fFancy ^= 1; - break; - case 'b': - fUseBuf ^= 1; - break; - case 'r': - fRandom ^= 1; - break; - case 'u': - fUseWeights ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'w': - fVeryVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc - globalUtilOptind < 2 || argc - globalUtilOptind > 4 ) - { - Abc_Print( 1, "Expecting two or three file names on the command line.\n" ); - goto usage; - } - Gia_ManRandom(1); - for ( c = 0; c < argc - globalUtilOptind; c++ ) - pFileNames[c] = argv[globalUtilOptind+c]; - for ( c = 0; c < argc - globalUtilOptind - 1; c++ ) - { - FILE * pFile = fopen( pFileNames[c], "rb" ); - if ( pFile == NULL ) - { - printf( "Cannot open input file \"%s\".\n", pFileNames[c] ); - return 0; - } - else - fclose( pFile ); - } - Acb_NtkRunSim( pFileNames, nWords, nBeam, LevL, LevU, fOrder, fFancy, fUseBuf, fRandom, fUseWeights, fVerbose, fVeryVerbose ); - return 0; - -usage: - Abc_Print( -2, "usage: runsim [-WBLU] [-ofbruvwh] [-N <num>] <file1> <file2> <file3>\n" ); - Abc_Print( -2, "\t experimental simulation command\n" ); - Abc_Print( -2, "\t-W <num> : the number of words of simulation info [default = %d]\n", nWords ); - Abc_Print( -2, "\t-B <num> : the beam width parameter [default = %d]\n", nBeam ); - Abc_Print( -2, "\t-L <num> : the lower bound on level [default = %d]\n", LevL ); - Abc_Print( -2, "\t-U <num> : the upper bound on level [default = %d]\n", LevU ); - Abc_Print( -2, "\t-o : toggle using a different node ordering [default = %s]\n", fOrder? "yes": "no" ); - Abc_Print( -2, "\t-f : toggle using experimental feature [default = %s]\n", fFancy? "yes": "no" ); - Abc_Print( -2, "\t-b : toggle using buffers [default = %s]\n", fUseBuf? "yes": "no" ); - Abc_Print( -2, "\t-r : toggle using random permutation of support variables [default = %s]\n", fRandom? "yes": "no" ); - Abc_Print( -2, "\t-u : toggle using topological info to select support variables [default = %s]\n", fUseWeights? "yes": "no" ); - Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-w : toggle printing more verbose information [default = %s]\n", fVeryVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ int Abc_CommandRunTest( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Acb_NtkRunTest( char * pFileNames[4], int fFancy, int fVerbose ); @@ -7342,8 +7286,8 @@ int Abc_CommandRunTest( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: runtest [-fvh] <file1> <file2>\n" ); - Abc_Print( -2, "\t experimental simulation command\n" ); + Abc_Print( -2, "usage: xec [-fvh] <file1> <file2>\n" ); + Abc_Print( -2, "\t combinational equivalence checking with x-values\n" ); Abc_Print( -2, "\t-f : toggle using experimental feature [default = %s]\n", fFancy? "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"); @@ -10353,7 +10297,7 @@ int Abc_CommandPutOnTop( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkPutOnTop( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtk2 ); - Abc_Ntk_t * pNtk, * pNtk2, * pNtkRes; + Abc_Ntk_t * pNtk, * pNtk2, * pNtkRes = NULL; char * FileName; int fComb = 0; int c; @@ -10373,6 +10317,36 @@ int Abc_CommandPutOnTop( Abc_Frame_t * pAbc, int argc, char ** argv ) } } + if ( argc > globalUtilOptind + 1 ) + { + for ( c = 1; c < argc; c++ ) + { + Abc_Ntk_t * pTemp, * pLogic = Io_Read( argv[c], Io_ReadFileType(argv[c]), 1, 0 ); + if ( pLogic == NULL ) + return 1; + if ( Abc_NtkIsStrash(pLogic) ) + { + pLogic = Abc_NtkToLogic( pTemp = pLogic ); + Abc_NtkDelete( pTemp ); + } + if ( pLogic == NULL ) + return 1; + if ( pNtkRes == NULL ) + pNtkRes = pLogic; + else + { + pNtkRes = Abc_NtkPutOnTop( pTemp = pNtkRes, pLogic ); + Abc_NtkDelete( pTemp ); + Abc_NtkDelete( pLogic ); + if ( pNtkRes == NULL ) + return 1; + } + } + assert( Abc_NtkIsLogic(pNtkRes) ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + } + // get the second network if ( argc != globalUtilOptind + 1 ) { @@ -10415,7 +10389,15 @@ int Abc_CommandPutOnTop( Abc_Frame_t * pAbc, int argc, char ** argv ) } // get the new network - pNtkRes = Abc_NtkPutOnTop( pNtk, pNtk2 ); + if ( Abc_NtkIsLogic(pNtk2) ) + pNtkRes = Abc_NtkPutOnTop( pNtk, pNtk2 ); + else if ( Abc_NtkIsStrash(pNtk2) ) + { + Abc_Ntk_t * pLogic = Abc_NtkToLogic( pNtk2 ); + pNtkRes = Abc_NtkPutOnTop( pNtk, pLogic ); + Abc_NtkDelete( pLogic ); + } + else assert( 0 ); Abc_NtkDelete( pNtk2 ); // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); @@ -10426,6 +10408,7 @@ usage: Abc_Print( -2, "\t connects PIs of network in <file> to POs of current network\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t<file> : file name with the second network\n"); + Abc_Print( -2, "\t : (given several files, all networks are stacked on top of each other)\n"); return 1; } @@ -10640,11 +10623,11 @@ usage: int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); - int c, fMode = -1, nCubeLimit = 1000000; + int c, fCubeSort = 1, fMode = -1, nCubeLimit = 1000000; // set defaults Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Cdnh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Csdnh" ) ) != EOF ) { switch ( c ) { @@ -10659,6 +10642,9 @@ int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nCubeLimit < 0 ) goto usage; break; + case 's': + fCubeSort ^= 1; + break; case 'd': fMode = 1; break; @@ -10681,6 +10667,11 @@ int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Converting to SOP is possible only for logic networks.\n" ); return 1; } + if ( !fCubeSort && Abc_NtkHasBdd(pNtk) && !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY, 0) ) + { + Abc_Print( -1, "Converting to SOP has failed.\n" ); + return 0; + } if ( !Abc_NtkToSop(pNtk, fMode, nCubeLimit) ) { Abc_Print( -1, "Converting to SOP has failed.\n" ); @@ -10689,9 +10680,10 @@ int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: sop [-C num] [-dnh]\n" ); + Abc_Print( -2, "usage: sop [-C num] [-sdnh]\n" ); Abc_Print( -2, "\t converts node functions to SOP\n" ); Abc_Print( -2, "\t-C num : the limit on the number of cubes at a node [default = %d]\n", nCubeLimit ); + Abc_Print( -2, "\t-s : toggles cube sort when converting from BDDs [default = %s]\n", fCubeSort ? "yes": "no" ); Abc_Print( -2, "\t-d : toggles using only positive polarity [default = %s]\n", fMode == 1 ? "yes": "no" ); Abc_Print( -2, "\t-n : toggles using only negative polarity [default = %s]\n", fMode == 0 ? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -11036,11 +11028,11 @@ usage: int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; - int c, fGlobal = 0, Limit = 1000000; + int c, fGlobal = 0, fUseAdd = 0, Limit = 1000000; pNtk = Abc_FrameReadNtk(pAbc); // set defaults Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Bgh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Bgah" ) ) != EOF ) { switch ( c ) { @@ -11058,6 +11050,9 @@ int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'g': fGlobal ^= 1; break; + case 'a': + fUseAdd ^= 1; + break; case 'h': goto usage; default: @@ -11089,7 +11084,7 @@ int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv ) } // get the new network - pNtkRes = Abc_NtkBddToMuxes( pNtk, fGlobal, Limit ); + pNtkRes = Abc_NtkBddToMuxes( pNtk, fGlobal, Limit, fUseAdd ); if ( pNtkRes == NULL ) { Abc_Print( 0, "Converting to MUXes has failed.\n" ); @@ -11100,11 +11095,12 @@ int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: muxes [-B num] [-gh]\n" ); + Abc_Print( -2, "usage: muxes [-B num] [-gah]\n" ); Abc_Print( -2, "\t converts the current network into a network derived by\n" ); Abc_Print( -2, "\t replacing all nodes by DAGs isomorphic to the local BDDs\n" ); Abc_Print( -2, "\t-B <num>: limit on live BDD nodes during collapsing [default = %d]\n", Limit ); Abc_Print( -2, "\t-g : toggle visualizing the global BDDs of primary outputs [default = %s].\n", fGlobal? "yes": "no" ); + Abc_Print( -2, "\t-a : toggle using ADDs instead of BDDs [default = %s].\n", fUseAdd? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -11895,12 +11891,7 @@ int Abc_CommandTopmost( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( Abc_NtkLatchNum(pNtk) > 0 ) { - Abc_Print( -1, "Currently can only works for combinational circuits.\n" ); - return 0; - } - if ( Abc_NtkPoNum(pNtk) != 1 ) - { - Abc_Print( -1, "Currently expects a single-output miter.\n" ); + Abc_Print( -1, "Currently only works for combinational circuits.\n" ); return 0; } @@ -11934,6 +11925,86 @@ usage: SeeAlso [] ***********************************************************************/ +int Abc_CommandBottommost( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nLevels; + extern Abc_Ntk_t * Abc_NtkBottommost( Abc_Ntk_t * pNtk, int nLevels ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + nLevels = 10; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nLevels = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevels < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" ); + return 0; + } + + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + Abc_Print( -1, "Currently only works for combinational circuits.\n" ); + return 0; + } + + pNtkRes = Abc_NtkBottommost( pNtk, nLevels ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "The command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: bottommost [-N num] [-h]\n" ); + Abc_Print( -2, "\t replaces the current network by several of its bottommost levels\n" ); + Abc_Print( -2, "\t-N num : max number of levels [default = %d]\n", nLevels ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\tname : the node name\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int Abc_CommandTopAnd( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; @@ -12085,13 +12156,16 @@ usage: int Abc_CommandShortNames( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); - int c; + int c, fKeepIo = 0; // set defaults Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "kh" ) ) != EOF ) { switch ( c ) { + case 'k': + fKeepIo ^= 1; + break; case 'h': goto usage; default: @@ -12104,12 +12178,16 @@ int Abc_CommandShortNames( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Empty network.\n" ); return 1; } - Abc_NtkShortNames( pNtk ); + if ( fKeepIo ) + Abc_NtkCleanNames( pNtk ); + else + Abc_NtkShortNames( pNtk ); return 0; usage: - Abc_Print( -2, "usage: short_names [-h]\n" ); + Abc_Print( -2, "usage: short_names [-kh]\n" ); Abc_Print( -2, "\t replaces PI/PO/latch names by short char strings\n" ); + Abc_Print( -2, "\t-k : toggle keeping PI/PO names unchanged [default = %s]\n", fKeepIo? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -13893,7 +13971,6 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) //Dau_NetworkEnumTest(); //Extra_SimulationTest( nDivMax, nNumOnes, fNewOrder ); //Mnist_ExperimentWithScaling( nDecMax ); - Gia_Gen2CodeTest(); return 0; usage: Abc_Print( -2, "usage: test [-CKDNM] [-aovwh] <file_name>\n" ); @@ -14913,7 +14990,7 @@ int Abc_CommandDch( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults Dch_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptgcfrvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptgcfrxvh" ) ) != EOF ) { switch ( c ) { @@ -14971,6 +15048,9 @@ int Abc_CommandDch( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'r': pPars->fSkipRedSupp ^= 1; break; + case 'x': + pPars->fUseNew ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -15001,7 +15081,7 @@ int Abc_CommandDch( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: dch [-WCS num] [-sptgcfrvh]\n" ); + Abc_Print( -2, "usage: dch [-WCS num] [-sptgcfrxvh]\n" ); Abc_Print( -2, "\t computes structural choices using a new approach\n" ); Abc_Print( -2, "\t-W num : the max number of simulation words [default = %d]\n", pPars->nWords ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); @@ -15013,6 +15093,7 @@ usage: Abc_Print( -2, "\t-c : toggle using circuit-based SAT vs. MiniSat [default = %s]\n", pPars->fUseCSat? "yes": "no" ); Abc_Print( -2, "\t-f : toggle using faster logic synthesis [default = %s]\n", pPars->fLightSynth? "yes": "no" ); Abc_Print( -2, "\t-r : toggle skipping choices with redundant support [default = %s]\n", pPars->fSkipRedSupp? "yes": "no" ); + Abc_Print( -2, "\t-x : toggle using new choice computation [default = %s]\n", pPars->fUseNew? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -15337,7 +15418,7 @@ int Abc_CommandIFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) nPartSize = 0; nLevelMax = 0; nConfLimit = 100; - fDoSparse = 0; + fDoSparse = 1; fProve = 0; fVerbose = 0; Extra_UtilGetoptReset(); @@ -20302,9 +20383,15 @@ int Abc_CommandPipe( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( Abc_NtkIsComb(pNtk) ) + if ( !Abc_NtkIsLogic(pNtk) ) { - Abc_Print( 0, "The current network is combinational.\n" ); + Abc_Print( 0, "Abc_CommandPipe(): Expecting a logic network (run command \"logic\").\n" ); + return 0; + } + + if ( !Abc_NtkIsComb(pNtk) ) + { + Abc_Print( 0, "Abc_CommandPipe(): Expecting a combinational network.\n" ); return 0; } @@ -23540,12 +23627,24 @@ int Abc_CommandPermute( Abc_Frame_t * pAbc, int argc, char ** argv ) int fFlops = 1; int fNodes = 1; int fFanout = 0; + int Seed = -1; int c; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Fiofnxh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "SFiofnxh" ) ) != EOF ) { switch ( c ) { + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Seed < 0 ) + goto usage; + break; case 'F': if ( globalUtilOptind >= argc ) { @@ -23577,6 +23676,8 @@ int Abc_CommandPermute( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + if ( Seed >= 0 ) + srand( (unsigned)Seed ); if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); @@ -23611,8 +23712,9 @@ int Abc_CommandPermute( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: permute [-iofnxh] [-F filename]\n" ); + Abc_Print( -2, "usage: permute [-S num] [-iofnxh] [-F filename]\n" ); Abc_Print( -2, "\t performs random permutation of inputs/outputs/flops\n" ); + Abc_Print( -2, "\t-S num : the random seed to generate permutations (0 <= num < INT_MAX) [default = %d]\n", Seed ); Abc_Print( -2, "\t-i : toggle permuting primary inputs [default = %s]\n", fInputs? "yes": "no" ); Abc_Print( -2, "\t-o : toggle permuting primary outputs [default = %s]\n", fOutputs? "yes": "no" ); Abc_Print( -2, "\t-f : toggle permuting flip-flops [default = %s]\n", fFlops? "yes": "no" ); @@ -29728,8 +29830,10 @@ static inline int Abc_NtkCompareWithBest( Abc_Ntk_t * pBest, Abc_Ntk_t * p, Abc_NtkPoNum(pBest) != Abc_NtkPoNum(p) || Abc_NtkLatchNum(pBest) != Abc_NtkLatchNum(p) || strcmp(Abc_NtkName(pBest), Abc_NtkName(p)) || - (!fArea && (*pnBestNtkLevels > nNtkLevels || (*pnBestNtkLevels == nNtkLevels && *pnBestNtkDelay > nNtkDelay ))) || - ( fArea && (*pnBestNtkNodes > nNtkNodes || (*pnBestNtkNodes == nNtkNodes && *pnBestNtkArea > nNtkArea ))) +// (!fArea && (*pnBestNtkLevels > nNtkLevels || (*pnBestNtkLevels == nNtkLevels && *pnBestNtkDelay > nNtkDelay ))) || +// ( fArea && (*pnBestNtkNodes > nNtkNodes || (*pnBestNtkNodes == nNtkNodes && *pnBestNtkArea > nNtkArea ))) + (!fArea && (*pnBestNtkDelay > nNtkDelay || (*pnBestNtkDelay == nNtkDelay && *pnBestNtkArea > nNtkArea ))) || + ( fArea && (*pnBestNtkArea > nNtkArea || (*pnBestNtkArea == nNtkArea && *pnBestNtkDelay > nNtkDelay ))) ) { *pnBestNtkArea = nNtkArea; @@ -29854,18 +29958,22 @@ usage: int Abc_CommandAbc9Read( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc3_ReadShowHie( char * pFileName, int fFlat ); + extern Gia_Man_t * Gia_MiniAigSuperDerive( char * pFileName, int fVerbose ); + extern Gia_Man_t * Gia_FileSimpleRead( char * pFileName, int fNames, char * pFileW ); Gia_Man_t * pAig = NULL; FILE * pFile; char ** pArgvNew; char * FileName, * pTemp; int c, nArgcNew; int fMiniAig = 0; + int fMiniAig2 = 0; int fMiniLut = 0; int fVerbose = 0; int fGiaSimple = 0; int fSkipStrash = 0; + int fNewReader = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "csmlvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "csmnlpvh" ) ) != EOF ) { switch ( c ) { @@ -29878,9 +29986,15 @@ int Abc_CommandAbc9Read( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'm': fMiniAig ^= 1; break; + case 'n': + fMiniAig2 ^= 1; + break; case 'l': fMiniLut ^= 1; break; + case 'p': + fNewReader ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -29912,8 +30026,12 @@ int Abc_CommandAbc9Read( Abc_Frame_t * pAbc, int argc, char ** argv ) } fclose( pFile ); - if ( fMiniAig ) - pAig = Gia_ManReadMiniAig( FileName ); + if ( fNewReader ) + pAig = Gia_FileSimpleRead( FileName, fGiaSimple, NULL ); + else if ( fMiniAig ) + pAig = Gia_ManReadMiniAig( FileName, fGiaSimple || fSkipStrash ); + else if ( fMiniAig2 ) + pAig = Gia_MiniAigSuperDerive( FileName, fVerbose ); else if ( fMiniLut ) pAig = Gia_ManReadMiniLut( FileName ); // else if ( Extra_FileIsType( FileName, ".v", NULL, NULL ) ) @@ -29925,11 +30043,12 @@ int Abc_CommandAbc9Read( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &r [-csmlvh] <file>\n" ); + Abc_Print( -2, "usage: &r [-csmnlvh] <file>\n" ); Abc_Print( -2, "\t reads the current AIG from the AIGER file\n" ); Abc_Print( -2, "\t-c : toggles reading simple AIG [default = %s]\n", fGiaSimple? "yes": "no" ); Abc_Print( -2, "\t-s : toggles structural hashing while reading [default = %s]\n", !fSkipStrash? "yes": "no" ); Abc_Print( -2, "\t-m : toggles reading MiniAIG rather than AIGER file [default = %s]\n", fMiniAig? "yes": "no" ); + Abc_Print( -2, "\t-n : toggles reading MiniAIG as a set of supergates [default = %s]\n", fMiniAig2? "yes": "no" ); Abc_Print( -2, "\t-l : toggles reading MiniLUT rather than AIGER file [default = %s]\n", fMiniLut? "yes": "no" ); Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -30250,8 +30369,6 @@ usage: int Abc_CommandAbc9Get( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Aig_Man_t * Abc_NtkToDarChoices( Abc_Ntk_t * pNtk ); - extern Vec_Ptr_t * Abc_NtkCollectCiNames( Abc_Ntk_t * pNtk ); - extern Vec_Ptr_t * Abc_NtkCollectCoNames( Abc_Ntk_t * pNtk ); Abc_Ntk_t * pStrash; Aig_Man_t * pAig; Gia_Man_t * pGia, * pTemp; @@ -30419,7 +30536,7 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) else { Abc_Ntk_t * pNtkNoCh; -// Abc_Print( -1, "Transforming AIG with %d choice nodes.\n", Gia_ManEquivCountClasses(pAbc->pGia) ); + Abc_Print( -1, "Transforming AIG with %d choice nodes.\n", Gia_ManEquivCountClasses(pAbc->pGia) ); // create network without choices pMan = Gia_ManToAig( pAbc->pGia, 0 ); pNtkNoCh = Abc_NtkFromAigPhase( pMan ); @@ -30463,6 +30580,8 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) } } } + if ( pAbc->pGia->vNamesNode ) + Abc_Print( 0, "Internal nodes names are not transferred.\n" ); // decouple CI/CO with the same name if ( pAbc->pGia->vNamesIn || pAbc->pGia->vNamesOut ) @@ -30503,6 +30622,67 @@ usage: /**Function************************************************************* + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9MoveNames( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nvh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + default: + goto usage; + } + } + if ( pAbc->pNtkCur == NULL ) + { + Abc_Print( -1, "There is no current network\n" ); + return 1; + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "There is no current AIG.\n" ); + return 1; + } + if ( Gia_ManCiNum(pAbc->pGia) != Abc_NtkCiNum(pAbc->pNtkCur) ) + { + Abc_Print( -1, "The number of CIs does not match.\n" ); + return 1; + } + if ( Gia_ManCoNum(pAbc->pGia) != Abc_NtkCoNum(pAbc->pNtkCur) ) + { + Abc_Print( -1, "The number of COs does not match.\n" ); + return 1; + } + if ( pAbc->pGia->vNamesIn ) Vec_PtrFreeFree( pAbc->pGia->vNamesIn ); + if ( pAbc->pGia->vNamesOut ) Vec_PtrFreeFree( pAbc->pGia->vNamesOut ); + pAbc->pGia->vNamesIn = Abc_NtkCollectCiNames( pAbc->pNtkCur ); + pAbc->pGia->vNamesOut = Abc_NtkCollectCoNames( pAbc->pNtkCur ); + return 0; + +usage: + Abc_Print( -2, "usage: &move_names [-vh]\n" ); + Abc_Print( -2, "\t move CI/CO names\n" ); + Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t<file> : the file name\n"); + return 1; +} + +/**Function************************************************************* + Synopsis [Compares to versions of the design and finds the best.] Description [] @@ -30919,12 +31099,13 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) int c, nArgcNew; int fUnique = 0; int fVerilog = 0; + int fVerBufs = 0; int fMiniAig = 0; int fMiniLut = 0; int fWriteNewLine = 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "upmlnvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "upbmlnvh" ) ) != EOF ) { switch ( c ) { @@ -30934,6 +31115,9 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'p': fVerilog ^= 1; break; + case 'b': + fVerBufs ^= 1; + break; case 'm': fMiniAig ^= 1; break; @@ -30972,7 +31156,7 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_ManStop( pGia ); } else if ( fVerilog ) - Gia_ManDumpVerilog( pAbc->pGia, pFileName, NULL ); + Gia_ManDumpVerilog( pAbc->pGia, pFileName, NULL, fVerBufs ); else if ( fMiniAig ) Gia_ManWriteMiniAig( pAbc->pGia, pFileName ); else if ( fMiniLut ) @@ -30982,10 +31166,11 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &w [-upmlnvh] <file>\n" ); + Abc_Print( -2, "usage: &w [-upbmlnvh] <file>\n" ); Abc_Print( -2, "\t writes the current AIG into the AIGER file\n" ); Abc_Print( -2, "\t-u : toggle writing canonical AIG structure [default = %s]\n", fUnique? "yes" : "no" ); Abc_Print( -2, "\t-p : toggle writing Verilog with 'and' and 'not' [default = %s]\n", fVerilog? "yes" : "no" ); + Abc_Print( -2, "\t-b : toggle writing additional buffers in Verilog [default = %s]\n", fVerBufs? "yes" : "no" ); Abc_Print( -2, "\t-m : toggle writing MiniAIG rather than AIGER [default = %s]\n", fMiniAig? "yes" : "no" ); Abc_Print( -2, "\t-l : toggle writing MiniLUT rather than AIGER [default = %s]\n", fMiniLut? "yes" : "no" ); Abc_Print( -2, "\t-n : toggle writing \'\\n\' after \'c\' in the AIGER file [default = %s]\n", fWriteNewLine? "yes": "no" ); @@ -31500,6 +31685,58 @@ usage: SeeAlso [] ***********************************************************************/ +int Abc_CommandAbc9MuxDec( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManPerformMuxDec( Gia_Man_t * p ); + Gia_Man_t * pGia; + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9MuxDec(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManCiNum(pAbc->pGia) <= 6 || Gia_ManCiNum(pAbc->pGia) > 26 ) + { + Abc_Print( -1, "Abc_CommandAbc9MuxDec(): The number of inputs is wrong.\n" ); + return 1; + } + pGia = Gia_ManPerformMuxDec( pAbc->pGia ); + Abc_FrameUpdateGia( pAbc, pGia ); + return 0; + +usage: + Abc_Print( -2, "usage: &muxdec [-vh]\n" ); + Abc_Print( -2, "\t performs restructuring\n" ); + Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int Abc_CommandAbc9PrintTruth( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern word Gia_LutComputeTruth6Simple( Gia_Man_t * p, int iPo ); @@ -31902,13 +32139,14 @@ int Abc_CommandAbc9Strash( Abc_Frame_t * pAbc, int argc, char ** argv ) extern Gia_Man_t * Gia_ManDupMuxRestructure( Gia_Man_t * p ); Gia_Man_t * pTemp; int c, Limit = 2; + int Multi = 0; int fAddStrash = 0; int fCollapse = 0; int fAddMuxes = 0; int fStrMuxes = 0; int fRehashMap = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Lacmrsh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "LMacmrsh" ) ) != EOF ) { switch ( c ) { @@ -31923,6 +32161,17 @@ int Abc_CommandAbc9Strash( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( Limit < 0 ) goto usage; break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + Multi = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Multi <= 0 ) + goto usage; + break; case 'a': fAddStrash ^= 1; break; @@ -31949,6 +32198,13 @@ int Abc_CommandAbc9Strash( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9Strash(): There is no AIG.\n" ); return 1; } + if ( Multi > 0 ) + { + extern Gia_Man_t * Gia_ManDupAddPis( Gia_Man_t * p, int nMulti ); + pTemp = Gia_ManDupAddPis( pAbc->pGia, Multi ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + } if ( fStrMuxes ) { if ( Gia_ManHasMapping(pAbc->pGia) ) @@ -32016,13 +32272,14 @@ int Abc_CommandAbc9Strash( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &st [-L num] [-acmrsh]\n" ); + Abc_Print( -2, "usage: &st [-LM num] [-acmrsh]\n" ); Abc_Print( -2, "\t performs structural hashing\n" ); Abc_Print( -2, "\t-a : toggle additional hashing [default = %s]\n", fAddStrash? "yes": "no" ); Abc_Print( -2, "\t-c : toggle collapsing hierarchical AIG [default = %s]\n", fCollapse? "yes": "no" ); Abc_Print( -2, "\t-m : toggle converting to larger gates [default = %s]\n", fAddMuxes? "yes": "no" ); Abc_Print( -2, "\t-L num : create MUX when sum of refs does not exceed this limit [default = %d]\n", Limit ); Abc_Print( -2, "\t (use L = 1 to create AIG with XORs but without MUXes)\n" ); + Abc_Print( -2, "\t-M num : create an AIG with additional primary inputs [default = %d]\n", Multi ); Abc_Print( -2, "\t-r : toggle rehashing AIG while preserving mapping [default = %s]\n", fRehashMap? "yes": "no" ); Abc_Print( -2, "\t-s : toggle using MUX restructuring [default = %s]\n", fStrMuxes? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -32139,11 +32396,12 @@ usage: ***********************************************************************/ int Abc_CommandAbc9Cof( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern Gia_Man_t * Gia_ManComputeCofs( Gia_Man_t * p, int nVars ); Gia_Man_t * pTemp; int c, fVerbose = 0; - int iVar = 0, nLimFan = 0; + int iVar = 0, nLimFan = 0, nVars = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "VLvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "VLNvh" ) ) != EOF ) { switch ( c ) { @@ -32169,6 +32427,17 @@ int Abc_CommandAbc9Cof( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nLimFan < 0 ) goto usage; break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 0 ) + goto usage; + break; case 'v': fVerbose ^= 1; break; @@ -32183,15 +32452,21 @@ int Abc_CommandAbc9Cof( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9Cof(): There is no AIG.\n" ); return 1; } - if ( nLimFan ) + if ( nVars ) + { + Abc_Print( 0, "Cofactoring the last %d inputs.\n", nVars ); + pTemp = Gia_ManComputeCofs( pAbc->pGia, nVars ); + Abc_FrameUpdateGia( pAbc, pTemp ); + } + else if ( nLimFan ) { - Abc_Print( -1, "Cofactoring all variables whose fanout count is higher than %d.\n", nLimFan ); + Abc_Print( 0, "Cofactoring all variables whose fanout count is higher than %d.\n", nLimFan ); pTemp = Gia_ManDupCofAll( pAbc->pGia, nLimFan, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); } else if ( iVar ) { - Abc_Print( -1, "Cofactoring one variable with object ID %d.\n", iVar ); + Abc_Print( 0, "Cofactoring one variable with object ID %d.\n", iVar ); pTemp = Gia_ManDupCof( pAbc->pGia, iVar ); Abc_FrameUpdateGia( pAbc, pTemp ); } @@ -32203,10 +32478,11 @@ int Abc_CommandAbc9Cof( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &cof [-VL num] [-vh]\n" ); + Abc_Print( -2, "usage: &cof [-VLN num] [-vh]\n" ); Abc_Print( -2, "\t performs cofactoring w.r.t. variable(s)\n" ); Abc_Print( -2, "\t-V num : the zero-based ID of one variable to cofactor [default = %d]\n", iVar ); Abc_Print( -2, "\t-L num : cofactor vars with fanout count higher than this [default = %d]\n", nLimFan ); + Abc_Print( -2, "\t-N num : cofactoring the given number of last input variables [default = %d]\n", nVars ); 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; @@ -32232,8 +32508,9 @@ int Abc_CommandAbc9Trim( Abc_Frame_t * pAbc, int argc, char ** argv ) int fTrimCos = 1; int fDualOut = 0; int fPoFedByPi = 0; + int fPoFedByPo = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Viocdh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Viocpdh" ) ) != EOF ) { switch ( c ) { @@ -32257,6 +32534,9 @@ int Abc_CommandAbc9Trim( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'c': fPoFedByPi ^= 1; break; + case 'p': + fPoFedByPo ^= 1; + break; case 'd': fDualOut ^= 1; break; @@ -32278,16 +32558,23 @@ int Abc_CommandAbc9Trim( Abc_Frame_t * pAbc, int argc, char ** argv ) pTemp = Gia_ManDupTrimmed2( pTemp2 = pTemp ); Gia_ManStop( pTemp2 ); } + if ( fPoFedByPo ) + { + extern Gia_Man_t * Gia_ManDupTrimmed3( Gia_Man_t * p ); + pTemp = Gia_ManDupTrimmed3( pTemp2 = pTemp ); + Gia_ManStop( pTemp2 ); + } Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &trim [-V num] [-iocdh]\n" ); + Abc_Print( -2, "usage: &trim [-V num] [-iocpdh]\n" ); Abc_Print( -2, "\t removes PIs without fanout and PO driven by constants\n" ); Abc_Print( -2, "\t-V num : the value (0 or 1) of POs to remove [default = both]\n" ); Abc_Print( -2, "\t-i : toggle removing PIs [default = %s]\n", fTrimCis? "yes": "no" ); Abc_Print( -2, "\t-o : toggle removing POs [default = %s]\n", fTrimCos? "yes": "no" ); Abc_Print( -2, "\t-c : toggle additionally removing POs fed by PIs [default = %s]\n", fPoFedByPi? "yes": "no" ); + Abc_Print( -2, "\t-p : toggle additionally removing duplicated POs [default = %s]\n", fPoFedByPo? "yes": "no" ); Abc_Print( -2, "\t-d : toggle using dual-output miter [default = %s]\n", fDualOut? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -32309,18 +32596,22 @@ int Abc_CommandAbc9Dfs( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_Man_t * pTemp; int c; int fNormal = 0; - int fReverse = 0; + int fRevFans = 0; + int fRevOuts = 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "nrvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "nfovh" ) ) != EOF ) { switch ( c ) { case 'n': fNormal ^= 1; break; - case 'r': - fReverse ^= 1; + case 'f': + fRevFans ^= 1; + break; + case 'o': + fRevOuts ^= 1; break; case 'v': fVerbose ^= 1; @@ -32337,31 +32628,18 @@ int Abc_CommandAbc9Dfs( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } if ( fNormal ) - { pTemp = Gia_ManDupOrderAiger( pAbc->pGia ); - if ( fVerbose ) - Abc_Print( -1, "AIG objects are reordered as follows: CIs, ANDs, COs.\n" ); - } - else if ( fReverse ) - { - pTemp = Gia_ManDupOrderDfsReverse( pAbc->pGia ); - if ( fVerbose ) - Abc_Print( -1, "AIG objects are reordered in the reserve DFS order.\n" ); - } - else - { - pTemp = Gia_ManDupOrderDfs( pAbc->pGia ); - if ( fVerbose ) - Abc_Print( -1, "AIG objects are reordered in the DFS order.\n" ); - } + else + pTemp = Gia_ManDupOrderDfsReverse( pAbc->pGia, fRevFans, fRevOuts ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &dfs [-nrvh]\n" ); + Abc_Print( -2, "usage: &dfs [-nfovh]\n" ); Abc_Print( -2, "\t orders objects in the DFS order\n" ); Abc_Print( -2, "\t-n : toggle using normalized ordering [default = %s]\n", fNormal? "yes": "no" ); - Abc_Print( -2, "\t-r : toggle using reverse DFS ordering [default = %s]\n", fReverse? "yes": "no" ); + Abc_Print( -2, "\t-f : toggle using reverse fanin traversal order [default = %s]\n", fRevFans? "yes": "no" ); + Abc_Print( -2, "\t-o : toggle using reverse output traversal order [default = %s]\n", fRevOuts? "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; @@ -32514,6 +32792,184 @@ usage: SeeAlso [] ***********************************************************************/ +int Abc_CommandAbc9Sim2( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Gia_ManSimTwo( Gia_Man_t * p0, Gia_Man_t * p1, int nWords, int nRounds, int fVerbose ); + Gia_Man_t * pGias[2]; FILE * pFile; + char ** pArgvNew; int nArgcNew; + int c, RetValue = 0, fVerbose = 0, nWords = 16, nRounds = 10, RandSeed = 1, TimeLimit = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "WRNTvh" ) ) != EOF ) + { + switch ( c ) + { + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + nWords = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nWords < 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; + } + nRounds = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nRounds < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + RandSeed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( RandSeed < 0 ) + goto usage; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + TimeLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( TimeLimit < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew > 2 ) + { + Abc_Print( -1, "Abc_CommandAbc9Cec(): Wrong number of command-line arguments.\n" ); + return 1; + } + if ( nArgcNew == 2 ) + { + char * pFileNames[2] = { pArgvNew[0], pArgvNew[1] }, * pTemp; + int n; + for ( n = 0; n < 2; n++ ) + { + // fix the wrong symbol + for ( pTemp = pFileNames[n]; *pTemp; pTemp++ ) + if ( *pTemp == '>' ) + *pTemp = '\\'; + if ( (pFile = fopen( pFileNames[n], "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", pFileNames[n] ); + if ( (pFileNames[n] = Extra_FileGetSimilarName( pFileNames[n], ".aig", NULL, NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", pFileNames[n] ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + pGias[n] = Gia_AigerRead( pFileNames[n], 0, 0, 0 ); + if ( pGias[n] == NULL ) + { + Abc_Print( -1, "Reading AIGER from file \"%s\" has failed.\n", pFileNames[n] ); + return 0; + } + } + } + else + { + char * FileName, * pTemp; + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Cec(): There is no current AIG.\n" ); + return 1; + } + pGias[0] = pAbc->pGia; + if ( nArgcNew == 1 ) + FileName = pArgvNew[0]; + else + { + assert( nArgcNew == 0 ); + if ( pAbc->pGia->pSpec == NULL ) + { + Abc_Print( -1, "File name is not given on the command line.\n" ); + return 1; + } + FileName = pAbc->pGia->pSpec; + } + // fix the wrong symbol + for ( pTemp = FileName; *pTemp; pTemp++ ) + if ( *pTemp == '>' ) + *pTemp = '\\'; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", NULL, NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + pGias[1] = Gia_AigerRead( FileName, 0, 0, 0 ); + if ( pGias[1] == NULL ) + { + Abc_Print( -1, "Reading AIGER has failed.\n" ); + return 0; + } + } + if ( Gia_ManCiNum(pGias[0]) != Gia_ManCiNum(pGias[1]) ) + { + Abc_Print( -1, "The number of CIs does not match.\n" ); + return 1; + } + if ( Gia_ManCoNum(pGias[0]) != Gia_ManCoNum(pGias[1]) ) + { + Abc_Print( -1, "The number of COs does not match.\n" ); + return 1; + } + RetValue = Gia_ManSimTwo( pGias[0], pGias[1], nWords, nRounds, fVerbose ); + if ( pGias[0] != pAbc->pGia ) + Gia_ManStopP( &pGias[0] ); + Gia_ManStopP( &pGias[1] ); + return 0; + +usage: + Abc_Print( -2, "usage: &sim2 [-WRNT num] [-vh] <file1.aig> <file2.aig>\n" ); + Abc_Print( -2, "\t performs random of two circuits\n" ); + Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", nWords ); + Abc_Print( -2, "\t-R num : the number of simulation rounds [default = %d]\n", nRounds ); + Abc_Print( -2, "\t-N num : random number seed (1 <= num <= 1000) [default = %d]\n", RandSeed ); + Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", TimeLimit ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int Abc_CommandAbc9Sim3( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Ssw_RarSimulateGia( Gia_Man_t * p, Ssw_RarPars_t * pPars ); @@ -32837,9 +33293,108 @@ usage: SeeAlso [] ***********************************************************************/ +int Abc_CommandAbc9Iwls21Test( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManTestWordFile( Gia_Man_t * p, char * pFileName, char * pDumpFile, int fVerbose ); + int c, fVerbose = 0; + char * pDumpFile = NULL; + char ** pArgvNew; + int nArgcNew; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Dvh" ) ) != EOF ) + { + switch ( c ) + { + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by a file name.\n" ); + goto usage; + } + pDumpFile = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew == 2 ) + { + Gia_Man_t * pAig = Gia_AigerRead( pArgvNew[0], 0, 0, 0 ); + if ( pAig == NULL ) + { + Abc_Print( -1, "Reading AIGER from file \"%s\" has failed.\n", pArgvNew[0] ); + return 0; + } + if ( Gia_ManRegNum(pAig) > 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9Iwls21Test(): This command works only for combinational AIGs.\n" ); + return 0; + } + if ( Gia_ManCoNum(pAig) != 10 ) + { + Abc_Print( -1, "Abc_CommandAbc9Iwls21Test(): Expecting an AIG with 10 outputs.\n" ); + return 0; + } + Gia_ManTestWordFile( pAig, pArgvNew[1], pDumpFile, fVerbose ); + Gia_ManStop( pAig ); + return 0; + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Iwls21Test(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManCoNum(pAbc->pGia) != 10 ) + { + Abc_Print( -1, "Abc_CommandAbc9Iwls21Test(): Expecting an AIG with 10 outputs.\n" ); + return 0; + } + if ( nArgcNew != 1 ) + { + Abc_Print( -1, "Abc_CommandAbc9Iwls21Test(): Expecting data file name on the command line.\n" ); + return 0; + } + if ( Gia_ManRegNum(pAbc->pGia) > 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9Iwls21Test(): This command works only for combinational AIGs.\n" ); + return 0; + } + Vec_WrdFreeP( &pAbc->pGia->vSimsPi ); + Gia_ManTestWordFile( pAbc->pGia, pArgvNew[0], pDumpFile, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: &iwls21test [-vh] [-D file] <file1> <file2>\n" ); + Abc_Print( -2, "\t this command evaluates AIG for 2021 IWLS ML+LS Contest\n" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t-D file : file name to dump statistics [default = none]\n" ); + Abc_Print( -2, "\tfile1 : file with input AIG (or \"&read <file1.aig>; &iwls21test <file2>\" can be used)\n"); + Abc_Print( -2, "\tfile2 : file with CIFAR10 image data (https://www.cs.toronto.edu/~kriz/cifar.html)\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int Abc_CommandAbc9ReadSim( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Vec_Wrd_t * Gia_ManSimPatRead( char * pFileName ); int c, fOutputs = 0, nWords = 4, fVerbose = 0; char ** pArgvNew; int nArgcNew; @@ -32891,7 +33446,7 @@ int Abc_CommandAbc9ReadSim( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( fOutputs ) { Vec_WrdFreeP( &pAbc->pGia->vSimsPo ); - pAbc->pGia->vSimsPo = Gia_ManSimPatRead( pArgvNew[0] ); + pAbc->pGia->vSimsPo = Vec_WrdReadHex( pArgvNew[0], NULL, 1 ); if ( Vec_WrdSize(pAbc->pGia->vSimsPo) % Gia_ManCoNum(pAbc->pGia) != 0 ) { Vec_WrdFreeP( &pAbc->pGia->vSimsPo ); @@ -32905,7 +33460,7 @@ int Abc_CommandAbc9ReadSim( Abc_Frame_t * pAbc, int argc, char ** argv ) else { Vec_WrdFreeP( &pAbc->pGia->vSimsPi ); - pAbc->pGia->vSimsPi = Gia_ManSimPatRead( pArgvNew[0] ); + pAbc->pGia->vSimsPi = Vec_WrdReadHex( pArgvNew[0], NULL, 1 ); if ( Vec_WrdSize(pAbc->pGia->vSimsPi) % Gia_ManCiNum(pAbc->pGia) != 0 ) { Vec_WrdFreeP( &pAbc->pGia->vSimsPi ); @@ -32942,7 +33497,6 @@ usage: ***********************************************************************/ int Abc_CommandAbc9WriteSim( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Gia_ManSimPatWrite( char * pFileName, Vec_Wrd_t * vSimsIn, int nWords ); int c, fOutputs = 0, fVerbose = 0; char ** pArgvNew; int nArgcNew; @@ -32988,12 +33542,12 @@ int Abc_CommandAbc9WriteSim( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( fOutputs ) { assert( Vec_WrdSize(pAbc->pGia->vSimsPo) % Gia_ManCoNum(pAbc->pGia) == 0 ); - Gia_ManSimPatWrite( pArgvNew[0], pAbc->pGia->vSimsPo, Vec_WrdSize(pAbc->pGia->vSimsPo) / Gia_ManCoNum(pAbc->pGia) ); + Vec_WrdDumpHex( pArgvNew[0], pAbc->pGia->vSimsPo, Vec_WrdSize(pAbc->pGia->vSimsPo) / Gia_ManCoNum(pAbc->pGia), 1 ); } else { assert( Vec_WrdSize(pAbc->pGia->vSimsPi) % Gia_ManCiNum(pAbc->pGia) == 0 ); - Gia_ManSimPatWrite( pArgvNew[0], pAbc->pGia->vSimsPi, Vec_WrdSize(pAbc->pGia->vSimsPi) / Gia_ManCiNum(pAbc->pGia) ); + Vec_WrdDumpHex( pArgvNew[0], pAbc->pGia->vSimsPi, Vec_WrdSize(pAbc->pGia->vSimsPi) / Gia_ManCiNum(pAbc->pGia), 1 ); } return 0; @@ -34593,6 +35147,72 @@ usage: SeeAlso [] ***********************************************************************/ +int Abc_CommandAbc9Extract( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Abc_NtkShareXorGia( Gia_Man_t * p, int nMultiSize, int fAnd, int fVerbose ); + Gia_Man_t * pTemp; + int nMultiSize = 3; + int c, fAnds = 0; + int fVerbose = 0; + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "Kavh")) != EOF ) + { + switch (c) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nMultiSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMultiSize < 0 ) + goto usage; + break; + case 'a': + fAnds ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Shrink(): There is no AIG.\n" ); + return 1; + } + pTemp = Abc_NtkShareXorGia( pAbc->pGia, nMultiSize, fAnds, fVerbose ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &extract [-K <num>] [-vh]\n"); + Abc_Print( -2, "\t extract shared logic for XOR-rich circuits\n"); + Abc_Print( -2, "\t-K <num> : the minimum gate size to consider for extraction [default = %d]\n", nMultiSize ); + Abc_Print( -2, "\t-a : toogle extracting ANDs instead of XORs [default = %s]\n", fAnds? "yes": "no" ); + Abc_Print( -2, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int Abc_CommandAbc9Balance( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp = NULL; @@ -34780,6 +35400,170 @@ usage: SeeAlso [] ***********************************************************************/ +int Abc_CommandAbc9Resub( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManResub1( char * pFileName, int nNodes, int nSupp, int nDivs, int iChoice, int fUseXor, int fVerbose, int fVeryVerbose ); + extern Gia_Man_t * Gia_ManResub2( Gia_Man_t * pGia, int nNodes, int nSupp, int nDivs, int iChoice, int fUseXor, int fVerbose, int fVeryVerbose ); + Gia_Man_t * pTemp; + int nNodes = 0; + int nSupp = 0; + int nDivs = 0; + int c, fVerbose = 0; + int fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NSDvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( 1, "Command line switch \"-N\" should be followed by a floating point number.\n" ); + return 0; + } + nNodes = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNodes < 0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( 1, "Command line switch \"-S\" should be followed by a floating point number.\n" ); + return 0; + } + nSupp = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nSupp < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( 1, "Command line switch \"-D\" should be followed by a floating point number.\n" ); + return 0; + } + nDivs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nDivs < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc == globalUtilOptind + 1 ) + { + pTemp = Gia_ManResub1( argv[globalUtilOptind], nNodes, nSupp, nDivs, 0, 0, fVerbose, fVeryVerbose ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Resub(): There is no AIG.\n" ); + return 1; + } + pTemp = Gia_ManResub2( pAbc->pGia, nNodes, nSupp, nDivs, 0, 0, fVerbose, fVeryVerbose ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &resub [-NSD num] [-vwh]\n" ); + Abc_Print( -2, "\t performs AIG resubstitution\n" ); + Abc_Print( -2, "\t-N num : the limit on added nodes (num >= 0) [default = %d]\n", nNodes ); + Abc_Print( -2, "\t-S num : the limit on support size (num > 0) [default = %d]\n", nSupp ); + Abc_Print( -2, "\t-D num : the limit on divisor count (num > 0) [default = %d]\n", nDivs ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggles printing additional information [default = %s]\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Reshape( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManReshape1( Gia_Man_t * pGia, int fUseSimple, int fVerbose, int fVeryVerbose ); + extern Gia_Man_t * Gia_ManReshape2( Gia_Man_t * pGia, int fUseSimple, int fVerbose, int fVeryVerbose ); + Gia_Man_t * pTemp; + int fUseReshape1 = 0; + int fUseSimple = 0; + int c, fVerbose = 0; + int fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "asvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'a': + fUseReshape1 ^= 1; + break; + case 's': + fUseSimple ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Resub(): There is no AIG.\n" ); + return 1; + } + if ( fUseReshape1 ) + pTemp = Gia_ManReshape1( pAbc->pGia, fUseSimple, fVerbose, fVeryVerbose ); + else + pTemp = Gia_ManReshape2( pAbc->pGia, fUseSimple, fVerbose, fVeryVerbose ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &reshape [-asvwh]\n" ); + Abc_Print( -2, "\t performs AIG resubstitution\n" ); + Abc_Print( -2, "\t-a : toggles selecting the algorithm [default = %s]\n", fUseReshape1? "yes": "no" ); + Abc_Print( -2, "\t-s : toggles using simple method [default = %s]\n", fUseSimple? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggles printing additional information [default = %s]\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int Abc_CommandAbc9Syn2( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; @@ -35175,6 +35959,7 @@ usage: ***********************************************************************/ int Abc_CommandAbc9Miter( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern Gia_Man_t * Gia_ManPairWiseMiter( Gia_Man_t * p ); FILE * pFile; Gia_Man_t * pAux; Gia_Man_t * pSecond; @@ -35185,13 +35970,14 @@ int Abc_CommandAbc9Miter( Abc_Frame_t * pAbc, int argc, char ** argv ) int nInsDup = 0; int fDualOut = 0; int fSeq = 0; + int fPairWise= 0; int fTrans = 0; int fTransX = 0; int fConvert = 0; int fTransZ = 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Idstxyzvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Idsptxyzvh" ) ) != EOF ) { switch ( c ) { @@ -35212,6 +35998,9 @@ int Abc_CommandAbc9Miter( Abc_Frame_t * pAbc, int argc, char ** argv ) case 's': fSeq ^= 1; break; + case 'p': + fPairWise ^= 1; + break; case 't': fTrans ^= 1; break; @@ -35233,6 +36022,17 @@ int Abc_CommandAbc9Miter( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + if ( fPairWise ) + { + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Miter(): There is no AIG.\n" ); + return 1; + } + pAux = Gia_ManPairWiseMiter( pAbc->pGia ); + Abc_FrameUpdateGia( pAbc, pAux ); + return 0; + } if ( fTrans || fTransX || fTransZ || fConvert ) { if ( pAbc->pGia == NULL ) @@ -35306,11 +36106,12 @@ int Abc_CommandAbc9Miter( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &miter [-I num] [-dstxyzvh] <file>\n" ); + Abc_Print( -2, "usage: &miter [-I num] [-dsptxyzvh] <file>\n" ); Abc_Print( -2, "\t creates miter of two designs (current AIG vs. <file>)\n" ); Abc_Print( -2, "\t-I num : the number of last PIs to replicate [default = %d]\n", nInsDup ); Abc_Print( -2, "\t-d : toggle creating dual-output miter [default = %s]\n", fDualOut? "yes": "no" ); Abc_Print( -2, "\t-s : toggle creating sequential miter [default = %s]\n", fSeq? "yes": "no" ); + Abc_Print( -2, "\t-p : toggle creating pair-wise miter [default = %s]\n", fPairWise? "yes": "no" ); Abc_Print( -2, "\t-t : toggle XORing POs of dual-output miter [default = %s]\n", fTrans? "yes": "no" ); Abc_Print( -2, "\t-x : toggle XORing POs of two-word miter [default = %s]\n", fTransX? "yes": "no" ); Abc_Print( -2, "\t-y : toggle convering two-word miter into dual-output miter [default = %s]\n", fConvert? "yes": "no" ); @@ -35872,16 +36673,28 @@ usage: int Abc_CommandAbc9Sat( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Vec_Int_t * Cbs2_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ); + extern Vec_Int_t * Cbs3_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, int nRestarts, Vec_Str_t ** pvStatus, int fVerbose ); Cec_ParSat_t ParsSat, * pPars = &ParsSat; Gia_Man_t * pTemp; int c; - int fNewSolver = 0, fCSat = 0; + int fNewSolver = 0, fNewSolver2 = 0, fCSat = 0, f0Proved = 0, nRestarts = 1; Cec_ManSatSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "CSNanmtcxvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "JCRSNanmtcxyzvh" ) ) != EOF ) { switch ( c ) { + case 'J': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-J\" should be followed by an integer.\n" ); + goto usage; + } + pPars->SolverType = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->SolverType < 0 ) + goto usage; + break; case 'C': if ( globalUtilOptind >= argc ) { @@ -35893,6 +36706,17 @@ int Abc_CommandAbc9Sat( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nBTLimit < 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; + } + nRestarts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nRestarts < 0 ) + goto usage; + break; case 'S': if ( globalUtilOptind >= argc ) { @@ -35933,6 +36757,12 @@ int Abc_CommandAbc9Sat( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'x': fNewSolver ^= 1; break; + case 'y': + fNewSolver2 ^= 1; + break; + case 'z': + f0Proved ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -35951,10 +36781,12 @@ int Abc_CommandAbc9Sat( Abc_Frame_t * pAbc, int argc, char ** argv ) Vec_Str_t * vStatus; if ( fNewSolver ) vCounters = Cbs2_ManSolveMiterNc( pAbc->pGia, pPars->nBTLimit, &vStatus, pPars->fVerbose ); + else if ( fNewSolver2 ) + vCounters = Cbs3_ManSolveMiterNc( pAbc->pGia, pPars->nBTLimit, nRestarts, &vStatus, pPars->fVerbose ); else if ( pPars->fLearnCls ) vCounters = Tas_ManSolveMiterNc( pAbc->pGia, pPars->nBTLimit, &vStatus, pPars->fVerbose ); else if ( pPars->fNonChrono ) - vCounters = Cbs_ManSolveMiterNc( pAbc->pGia, pPars->nBTLimit, &vStatus, pPars->fVerbose ); + vCounters = Cbs_ManSolveMiterNc( pAbc->pGia, pPars->nBTLimit, &vStatus, f0Proved, pPars->fVerbose ); else vCounters = Cbs_ManSolveMiter( pAbc->pGia, pPars->nBTLimit, &vStatus, pPars->fVerbose ); Vec_IntFree( vCounters ); @@ -35962,7 +36794,7 @@ int Abc_CommandAbc9Sat( Abc_Frame_t * pAbc, int argc, char ** argv ) } else { - pTemp = Cec_ManSatSolving( pAbc->pGia, pPars ); + pTemp = Cec_ManSatSolving( pAbc->pGia, pPars, f0Proved ); Abc_FrameUpdateGia( pAbc, pTemp ); } if ( pAbc->pGia->vSeqModelVec ) @@ -35974,9 +36806,11 @@ int Abc_CommandAbc9Sat( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &sat [-CSN <num>] [-anmctxvh]\n" ); + Abc_Print( -2, "usage: &sat [-JCRSN <num>] [-anmctxzvh]\n" ); Abc_Print( -2, "\t performs SAT solving for the combinational outputs\n" ); + Abc_Print( -2, "\t-J num : the SAT solver type [default = %d]\n", pPars->SolverType ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); + Abc_Print( -2, "\t-R num : the max number of restarts at a node [default = %d]\n", nRestarts ); Abc_Print( -2, "\t-S num : the min number of variables to recycle the solver [default = %d]\n", pPars->nSatVarMax ); Abc_Print( -2, "\t-N num : the min number of calls to recycle the solver [default = %d]\n", pPars->nCallsRecycle ); Abc_Print( -2, "\t-a : toggle solving all outputs and saving counter-examples [default = %s]\n", pPars->fSaveCexes? "yes": "no" ); @@ -35985,6 +36819,8 @@ usage: Abc_Print( -2, "\t-c : toggle using circuit-based SAT solver [default = %s]\n", fCSat? "yes": "no" ); Abc_Print( -2, "\t-t : toggle using learning in curcuit-based solver [default = %s]\n", pPars->fLearnCls? "yes": "no" ); Abc_Print( -2, "\t-x : toggle using new solver [default = %s]\n", fNewSolver? "yes": "no" ); + Abc_Print( -2, "\t-y : toggle using new solver [default = %s]\n", fNewSolver2? "yes": "no" ); + Abc_Print( -2, "\t-z : toggle replacing proved cones by const0 [default = %s]\n", f0Proved? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -36070,18 +36906,29 @@ usage: ***********************************************************************/ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern void Cec4_ManSetParams( Cec_ParFra_t * pPars ); extern Gia_Man_t * Cec2_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ); extern Gia_Man_t * Cec3_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ); - Cec_ParFra_t ParsFra, * pPars = &ParsFra; - Gia_Man_t * pTemp; - int c, fUseAlgo = 0, fUseAlgoG = 0; - Cec_ManFraSetDefaultParams( pPars ); - pPars->fSatSweeping = 1; + extern Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ); + Cec_ParFra_t ParsFra, * pPars = &ParsFra; Gia_Man_t * pTemp; + int c, fUseAlgo = 0, fUseAlgoG = 0, fUseAlgoG2 = 0; + Cec4_ManSetParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WRILDCrmdckngwvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "JWRILDCNPrmdckngxwvh" ) ) != EOF ) { switch ( c ) { + case 'J': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-J\" should be followed by an integer.\n" ); + goto usage; + } + pPars->jType = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->jType < 0 ) + goto usage; + break; case 'W': if ( globalUtilOptind >= argc ) { @@ -36148,6 +36995,28 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nBTLimit < 0 ) goto usage; break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nCallsRecycle = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nCallsRecycle < 0 ) + goto usage; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nGenIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nGenIters < 0 ) + goto usage; + break; case 'r': pPars->fRewriting ^= 1; break; @@ -36169,6 +37038,9 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'g': fUseAlgoG ^= 1; break; + case 'x': + fUseAlgoG2 ^= 1; + break; case 'w': pPars->fVeryVerbose ^= 1; break; @@ -36188,20 +37060,25 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) pTemp = Cec2_ManSimulateTest( pAbc->pGia, pPars ); else if ( fUseAlgoG ) pTemp = Cec3_ManSimulateTest( pAbc->pGia, pPars ); + else if ( fUseAlgoG2 ) + pTemp = Cec4_ManSimulateTest( pAbc->pGia, pPars ); else pTemp = Cec_ManSatSweeping( pAbc->pGia, pPars, 0 ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &fraig [-WRILDC <num>] [-rmdckngwvh]\n" ); + Abc_Print( -2, "usage: &fraig [-JWRILDCNP <num>] [-rmdckngwvh]\n" ); Abc_Print( -2, "\t performs combinational SAT sweeping\n" ); + Abc_Print( -2, "\t-J num : the solver type [default = %d]\n", pPars->jType ); Abc_Print( -2, "\t-W num : the number of simulation words [default = %d]\n", pPars->nWords ); Abc_Print( -2, "\t-R num : the number of simulation rounds [default = %d]\n", pPars->nRounds ); Abc_Print( -2, "\t-I num : the number of sweeping iterations [default = %d]\n", pPars->nItersMax ); Abc_Print( -2, "\t-L num : the max number of levels of nodes to consider [default = %d]\n", pPars->nLevelMax ); Abc_Print( -2, "\t-D num : the max number of steps of speculative reduction [default = %d]\n", pPars->nDepthMax ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); + Abc_Print( -2, "\t-N num : the min number of calls to recycle the solver [default = %d]\n", pPars->nCallsRecycle ); + Abc_Print( -2, "\t-P num : the number of pattern generation iterations [default = %d]\n", pPars->nGenIters ); Abc_Print( -2, "\t-r : toggle the use of AIG rewriting [default = %s]\n", pPars->fRewriting? "yes": "no" ); Abc_Print( -2, "\t-m : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" ); Abc_Print( -2, "\t-d : toggle using double output miters [default = %s]\n", pPars->fDualOut? "yes": "no" ); @@ -36316,8 +37193,9 @@ int Abc_CommandAbc9Srm( Abc_Frame_t * pAbc, int argc, char ** argv ) int fSpeculate = 1; int fSkipSome = 0; int fDualOut = 0; + int fComb = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Adrsfvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Adrsfcvh" ) ) != EOF ) { switch ( c ) { @@ -36342,6 +37220,9 @@ int Abc_CommandAbc9Srm( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'f': fSkipSome ^= 1; break; + case 'c': + fComb ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -36356,6 +37237,16 @@ int Abc_CommandAbc9Srm( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9Srm(): There is no AIG.\n" ); return 1; } + if ( fComb ) + { + extern int Cec4_ManSimulateOnlyTest( Gia_Man_t * p, int fVerbose ); + int Result = Cec4_ManSimulateOnlyTest( pAbc->pGia, fVerbose ); + extern Gia_Man_t * Gia_ManCombSpecReduce( Gia_Man_t * p ); + pTemp = Gia_ManCombSpecReduce( pAbc->pGia ); + Abc_FrameUpdateGia( pAbc, pTemp ); + Result = 0; + return 0; + } sprintf(pFileName, "gsrm%s.aig", fSpeculate? "" : "s" ); sprintf(pFileName2, "gsyn%s.aig", fSpeculate? "" : "s" ); pTemp = Gia_ManSpecReduce( pAbc->pGia, fDualOut, fSynthesis, fSpeculate, fSkipSome, fVerbose ); @@ -36388,13 +37279,14 @@ int Abc_CommandAbc9Srm( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &srm [-A file] [-drsfvh]\n" ); - Abc_Print( -2, "\t writes speculatively reduced model into file \"%s\"\n", pFileName ); + Abc_Print( -2, "usage: &srm [-A file] [-drsfcvh]\n" ); + Abc_Print( -2, "\t derives or writes speculatively reduced model into file \"%s\"\n", pFileName ); Abc_Print( -2, "\t-A file : file name for dumping speculative-reduced model [default = \"gsrm.aig\"]\n" ); Abc_Print( -2, "\t-d : toggle creating dual-output miter [default = %s]\n", fDualOut? "yes": "no" ); Abc_Print( -2, "\t-r : toggle writing reduced network for synthesis [default = %s]\n", fSynthesis? "yes": "no" ); Abc_Print( -2, "\t-s : toggle using speculation at the internal nodes [default = %s]\n", fSpeculate? "yes": "no" ); Abc_Print( -2, "\t-f : toggle filtering to remove redundant equivalences [default = %s]\n", fSkipSome? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle using combinational speculation [default = %s]\n", fComb? "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; @@ -36771,10 +37663,10 @@ int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv ) FILE * pFile; Gia_Man_t * pGias[2] = {NULL, NULL}, * pMiter; char ** pArgvNew; - int c, nArgcNew, fMiter = 0, fDualOutput = 0, fDumpMiter = 0; + int c, nArgcNew, fUseSim = 0, fUseNew = 0, fMiter = 0, fDualOutput = 0, fDumpMiter = 0; Cec_ManCecSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "CTnmdasvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "CTnmdasxtvwh" ) ) != EOF ) { switch ( c ) { @@ -36815,9 +37707,18 @@ int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv ) case 's': pPars->fSilent ^= 1; break; + case 'x': + fUseNew ^= 1; + break; + case 't': + fUseSim ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; case 'h': goto usage; default: @@ -36846,13 +37747,46 @@ int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv ) } else { - Gia_Man_t * pTemp; + abctime clk = Abc_Clock(); + Gia_Obj_t * pObj; int i; if ( !pPars->fSilent ) Abc_Print( 1, "Assuming the current network is a single-output miter.\n" ); - pTemp = Gia_ManDemiterToDual( pAbc->pGia ); - pAbc->Status = Cec_ManVerify( pTemp, pPars ); - ABC_SWAP( Abc_Cex_t *, pAbc->pGia->pCexComb, pTemp->pCexComb ); - Gia_ManStop( pTemp ); + if ( fUseSim ) + { + abctime clk = Abc_Clock(); + extern int Gia_ManCheckSimEquiv( Gia_Man_t * p, int fVerbose ); + int Status = Gia_ManCheckSimEquiv( pAbc->pGia, pPars->fVerbose ); + if ( Status == 1 ) + Abc_Print( 1, "Networks are equivalent. " ); + else if ( Status == 0 ) + Abc_Print( 1, "Networks are NOT equivalent. " ); + else + Abc_Print( 1, "Networks are UNDECIDED. " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return 0; + } + // handle the case when the output is disproved by an all-0 primary input pattern + ABC_FREE( pAbc->pGia->pCexComb ); + Gia_ManSetPhase( pAbc->pGia ); + Gia_ManForEachCo( pAbc->pGia, pObj, i ) + if ( pObj->fPhase ) + { + pAbc->pGia->pCexComb = Abc_CexAlloc( 0, Gia_ManCiNum(pAbc->pGia), 1 ); + if ( !pPars->fSilent ) + { + Abc_Print( 1, "Networks are NOT EQUIVALENT. Output %d trivially differs (different phase). ", i ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + pAbc->Status = 0;// satisfiable + break; + } + if ( pAbc->pGia->pCexComb == NULL ) + { + Gia_Man_t * pTemp = Gia_ManDemiterToDual( pAbc->pGia ); + pAbc->Status = Cec_ManVerify( pTemp, pPars ); + ABC_SWAP( Abc_Cex_t *, pAbc->pGia->pCexComb, pTemp->pCexComb ); + Gia_ManStop( pTemp ); + } } Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb ); return 0; @@ -36931,7 +37865,7 @@ int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv ) } } // compute the miter - pMiter = Gia_ManMiter( pGias[0], pGias[1], 0, 1, 0, 0, pPars->fVerbose ); + pMiter = Gia_ManMiter( pGias[0], pGias[1], 0, !fUseNew, 0, 0, pPars->fVerbose ); if ( pMiter ) { if ( fDumpMiter ) @@ -36939,8 +37873,46 @@ int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( 0, "The verification miter is written into file \"%s\".\n", "cec_miter.aig" ); Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0, 0 ); } - pAbc->Status = Cec_ManVerify( pMiter, pPars ); - Abc_FrameReplaceCex( pAbc, &pGias[0]->pCexComb ); + if ( pGias[0]->vSimsPi ) + { + pMiter->vSimsPi = Vec_WrdDup(pGias[0]->vSimsPi); + pMiter->nSimWords = pGias[0]->nSimWords; + } + if ( fUseSim && Gia_ManCiNum(pMiter) > 40 ) + { + Abc_Print( -1, "This type of CEC can only be applied to AIGs with no more than 40 inputs.\n" ); + return 0; + } + if ( fUseSim ) + { + abctime clk = Abc_Clock(); + extern int Gia_ManCheckSimEquiv( Gia_Man_t * p, int fVerbose ); + int Status = Gia_ManCheckSimEquiv( pMiter, pPars->fVerbose ); + if ( Status == 1 ) + Abc_Print( 1, "Networks are equivalent. " ); + else if ( Status == 0 ) + Abc_Print( 1, "Networks are NOT equivalent. " ); + else + Abc_Print( 1, "Networks are UNDECIDED. " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + else if ( fUseNew ) + { + abctime clk = Abc_Clock(); + extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); + Gia_Man_t * pNew = Cec4_ManSimulateTest3( pMiter, pPars->nBTLimit, pPars->fVerbose ); + if ( Gia_ManAndNum(pNew) == 0 ) + Abc_Print( 1, "Networks are equivalent. " ); + else + Abc_Print( 1, "Networks are UNDECIDED. " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Gia_ManStop( pNew ); + } + else + { + pAbc->Status = Cec_ManVerify( pMiter, pPars ); + Abc_FrameReplaceCex( pAbc, &pGias[0]->pCexComb ); + } Gia_ManStop( pMiter ); } if ( pGias[0] != pAbc->pGia ) @@ -36949,7 +37921,7 @@ int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &cec [-CT num] [-nmdasvh]\n" ); + Abc_Print( -2, "usage: &cec [-CT num] [-nmdasxtvwh]\n" ); Abc_Print( -2, "\t new combinational equivalence checker\n" ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", pPars->TimeLimit ); @@ -36958,7 +37930,10 @@ usage: Abc_Print( -2, "\t-d : toggle using dual output miter [default = %s]\n", fDualOutput? "yes":"no"); Abc_Print( -2, "\t-a : toggle writing dual-output miter [default = %s]\n", fDumpMiter? "yes":"no"); Abc_Print( -2, "\t-s : toggle silent operation [default = %s]\n", pPars->fSilent ? "yes":"no"); + Abc_Print( -2, "\t-x : toggle using new solver [default = %s]\n", fUseNew? "yes":"no"); + Abc_Print( -2, "\t-t : toggle using simulation [default = %s]\n", fUseSim? "yes":"no"); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes":"no"); + Abc_Print( -2, "\t-w : toggle printing SAT solver statistics [default = %s]\n", pPars->fVeryVerbose? "yes":"no"); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -39302,7 +40277,7 @@ int Abc_CommandAbc9Mf( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_Man_t * pNew; int c; Mf_ManSetDefaultPars( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFARLEDWaekmcgvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFARLEDWaekmclgvwh" ) ) != EOF ) { switch ( c ) { @@ -39426,6 +40401,9 @@ int Abc_CommandAbc9Mf( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'c': pPars->fGenCnf ^= 1; break; + case 'l': + pPars->fGenLit ^= 1; + break; case 'g': pPars->fPureAig ^= 1; break; @@ -39478,6 +40456,7 @@ usage: Abc_Print( -2, "\t-k : toggles coarsening the subject graph [default = %s]\n", pPars->fCoarsen? "yes": "no" ); Abc_Print( -2, "\t-m : toggles cut minimization [default = %s]\n", pPars->fCutMin? "yes": "no" ); Abc_Print( -2, "\t-c : toggles mapping for CNF generation [default = %s]\n", pPars->fGenCnf? "yes": "no" ); + Abc_Print( -2, "\t-l : toggles mapping for literals [default = %s]\n", pPars->fGenLit? "yes": "no" ); Abc_Print( -2, "\t-g : toggles generating AIG without mapping [default = %s]\n", pPars->fPureAig? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggles very verbose output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); @@ -40314,6 +41293,365 @@ usage: SeeAlso [] ***********************************************************************/ +int Abc_CommandAbc9LNetRead( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Vec_WrdReadTest( char * pFileName ); + extern void Gia_ManReadSimInfoInputs( char * pFileName, char * pFileOut1, int fVerbose ); + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + default: + goto usage; + } + } + if ( argc == globalUtilOptind + 2 ) // read 1 file, write 1 file + { + Gia_ManReadSimInfoInputs( argv[globalUtilOptind], argv[globalUtilOptind+1], fVerbose ); + return 0; + } + if ( strstr(argv[globalUtilOptind], ".v") ) + { + Gia_Man_t * pNew = Vec_WrdReadTest( argv[globalUtilOptind] ); + if ( pNew == NULL ) + { + printf( "Cannot read network from file \"%s\".\n", argv[globalUtilOptind] ); + return 0; + } + Abc_FrameUpdateGia( pAbc, pNew ); + } + return 0; + +usage: + Abc_Print( -2, "usage: &lnetread [-vh] <file> <file2>\n" ); + Abc_Print( -2, "\t reads and converts the network or the simulation data\n" ); + Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : prints the command usage\n"); + Abc_Print( -2, "\t<file> : input file name with simulation information\n"); + Abc_Print( -2, "\t<file2> : output file name with simulation information\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9LNetSim( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManSimInfoPassTest( Gia_Man_t * p, char * pFileName, char * pFileName2, int fVerbose ); + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Empty GIA network.\n" ); + return 1; + } + if ( argc != globalUtilOptind + 2 ) + { + Abc_Print( -1, "Expecting two file names on the command line.\n" ); + return 1; + } + Gia_ManSimInfoPassTest( pAbc->pGia, argv[globalUtilOptind], argv[globalUtilOptind+1], fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: &lnetsim [-vh] <file> <file2>\n" ); + Abc_Print( -2, "\t performs specialized AIG simulation\n" ); + Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : prints the command usage\n"); + Abc_Print( -2, "\t<file> : input file name with simulation information\n"); + Abc_Print( -2, "\t<file2> : output file name with simulation information\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9LNetEval( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManSimInfoEval( Gia_Man_t * p, char * pFileName, char * pFileName2, int nOuts, int fVerbose ); + int c, nOuts = -1, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ovh" ) ) != EOF ) + { + switch ( c ) + { + case 'O': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-O\" should be followed by a positive integer.\n" ); + goto usage; + } + nOuts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Empty GIA network.\n" ); + return 1; + } + if ( argc != globalUtilOptind + 2 ) + { + Abc_Print( -1, "Expecting two file names on the command line.\n" ); + return 1; + } + Gia_ManSimInfoEval( pAbc->pGia, argv[globalUtilOptind], argv[globalUtilOptind+1], nOuts, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: &lneteval [-O num] [-vh] <file> <file2>\n" ); + Abc_Print( -2, "\t performs testing of the AIG on the simulation data\n" ); + Abc_Print( -2, "\t-O num : the output group size [default = %d]\n", nOuts ); + Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : prints the command usage\n"); + Abc_Print( -2, "\t<file> : file name with simulation information\n"); + Abc_Print( -2, "\t<file2> : file name with simulation information\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9LNetOpt( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManPerformLNetOpt( Gia_Man_t * p, int fTryNew, char * pFileName, int nIns, int nOuts, int Thresh, int nRounds, int fVerbose ); + extern Gia_Man_t * Gia_ManPerformLNetOptNew( Gia_Man_t * p, char * pFileName, int nIns, int nOuts, int Thresh, int nRounds, int fVerbose ); + Gia_Man_t * pTemp; + char * pFileName = NULL; + int c, nIns = 6, nOuts = 2, Limit = 0, nRounds = 20, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IORXvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + nIns = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'O': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-O\" should be followed by a positive integer.\n" ); + goto usage; + } + nOuts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by a positive integer.\n" ); + goto usage; + } + Limit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'X': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-X\" should be followed by a positive integer.\n" ); + goto usage; + } + nRounds = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + default: + goto usage; + } + } + if ( argc > globalUtilOptind + 1 ) + { + return 0; + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Empty GIA network.\n" ); + return 1; + } + if ( argc == globalUtilOptind + 1 ) + { + FILE * pFile = fopen( argv[globalUtilOptind], "rb" ); + if ( pFile == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9BCore(): Cannot open file \"%s\" for reading the simulation information.\n", argv[globalUtilOptind] ); + return 0; + } + fclose( pFile ); + pFileName = argv[globalUtilOptind]; + } + pTemp = Gia_ManPerformLNetOptNew( pAbc->pGia, pFileName, nIns, nOuts, Limit, nRounds, fVerbose ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &lnetopt [-IORX num] [-vh] <file>\n" ); + Abc_Print( -2, "\t performs specialized AIG optimization\n" ); + Abc_Print( -2, "\t-I num : the input support size [default = %d]\n", nIns ); + Abc_Print( -2, "\t-O num : the output group size [default = %d]\n", nOuts ); + Abc_Print( -2, "\t-R num : patterns are cares starting this value [default = %d]\n", Limit ); + Abc_Print( -2, "\t-X num : the number of optimization rounds [default = %d]\n", nRounds ); + Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : prints the command usage\n"); + Abc_Print( -2, "\t<file> : file name with simulation information\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9LNetMap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Gia_ManPerformLNetMap( Gia_Man_t * p, int GroupSize, int fUseFixed, int fTryNew, int fVerbose ); + Abc_Ntk_t * pTemp; + char * pFileName = NULL; + int c, fTryNew = 1, nIns = 6, nOuts = 2, fUseFixed = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IOfxvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + nIns = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'O': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-O\" should be followed by a positive integer.\n" ); + goto usage; + } + nOuts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'f': + fUseFixed ^= 1; + break; + case 'x': + fTryNew ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Empty GIA network.\n" ); + return 1; + } + if ( argc == globalUtilOptind + 1 ) + { + FILE * pFile = fopen( argv[globalUtilOptind], "rb" ); + if ( pFile == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9BCore(): Cannot open file \"%s\" for reading the simulation information.\n", argv[globalUtilOptind] ); + return 0; + } + fclose( pFile ); + pFileName = argv[globalUtilOptind]; + } + pTemp = Gia_ManPerformLNetMap( pAbc->pGia, nOuts, fUseFixed, fTryNew, fVerbose ); + Abc_FrameReplaceCurrentNetwork( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &lnetmap [-IO num] [-fxvh] <file>\n" ); + Abc_Print( -2, "\t performs specialized LUT mapping\n" ); + Abc_Print( -2, "\t-I num : the input support size [default = %d]\n", nIns ); + Abc_Print( -2, "\t-O num : the output group size [default = %d]\n", nOuts ); + Abc_Print( -2, "\t-f : toggles using fixed primitives [default = %s]\n", fUseFixed? "yes": "no" ); + Abc_Print( -2, "\t-x : toggles using another computation [default = %s]\n", fTryNew? "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"); + Abc_Print( -2, "\t<file> : file name with simulation information\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int Abc_CommandAbc9Unmap( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_ManTestStruct( Gia_Man_t * p ); @@ -40675,7 +42013,7 @@ int Abc_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults Dch_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptfremvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptfremgcxvh" ) ) != EOF ) { switch ( c ) { @@ -40733,6 +42071,15 @@ int Abc_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'm': fMinLevel ^= 1; break; + case 'g': + pPars->fUseGia ^= 1; + break; + case 'c': + pPars->fUseCSat ^= 1; + break; + case 'x': + pPars->fUseNew ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -40772,7 +42119,7 @@ int Abc_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &dch [-WCS num] [-sptfremvh]\n" ); + Abc_Print( -2, "usage: &dch [-WCS num] [-sptfremgcxvh]\n" ); Abc_Print( -2, "\t computes structural choices using a new approach\n" ); Abc_Print( -2, "\t-W num : the max number of simulation words [default = %d]\n", pPars->nWords ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); @@ -40784,6 +42131,9 @@ usage: Abc_Print( -2, "\t-r : toggle skipping choices with redundant support [default = %s]\n", pPars->fSkipRedSupp? "yes": "no" ); Abc_Print( -2, "\t-e : toggle computing and merging equivalences [default = %s]\n", fEquiv? "yes": "no" ); Abc_Print( -2, "\t-m : toggle minimizing logic level after merging equivalences [default = %s]\n", fMinLevel? "yes": "no" ); + Abc_Print( -2, "\t-g : toggle using GIA to prove equivalences [default = %s]\n", pPars->fUseGia? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle using circuit-based SAT vs. MiniSat [default = %s]\n", pPars->fUseCSat? "yes": "no" ); + Abc_Print( -2, "\t-x : toggle using new choice computation [default = %s]\n", pPars->fUseNew? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -42083,6 +43433,64 @@ usage: SeeAlso [] ***********************************************************************/ +int Abc_CommandAbc9Compare( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_Iso4TestTwo( Gia_Man_t * pGia0, Gia_Man_t * pGia1 ); + Gia_Man_t * pGia0, * pGia1; + char ** pArgvNew; int nArgcNew; + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 2 ) + { + Abc_Print( -1, "Abc_CommandAbc9Compare(): This command expects two AIG file names on the command line.\n" ); + return 1; + } + pGia0 = Gia_AigerRead( pArgvNew[0], 0, 0, 0 ); + pGia1 = Gia_AigerRead( pArgvNew[1], 0, 0, 0 ); + if ( pGia0 == NULL || pGia1 == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Compare(): Reading input files did not work.\n" ); + return 1; + } + Gia_Iso4TestTwo( pGia0, pGia1 ); + Gia_ManStop( pGia0 ); + Gia_ManStop( pGia1 ); + return 0; + +usage: + Abc_Print( -2, "usage: &compare <file1> <file2> [-vh]\n" ); + Abc_Print( -2, "\t compared two AIGs for structural similarity\n" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int Abc_CommandAbc9CexInfo( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Bmc_CexTest( Gia_Man_t * p, Abc_Cex_t * pCex, int fVerbose ); @@ -44409,6 +45817,7 @@ int Abc_CommandAbc9SatClp( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; } vSop = Bmc_CollapseOne( pAbc->pGia, nCubeLim, nBTLimit, fCanon, 0, fVerbose ); + printf( "%s\n", Vec_StrArray(vSop) ); Vec_StrFree( vSop ); return 0; @@ -45703,7 +47112,7 @@ int Abc_CommandAbc9Mfs( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->nDepthMax = 100; pPars->nWinSizeMax = 2000; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCNdaebvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCNdaeblvwh" ) ) != EOF ) { switch ( c ) { @@ -45796,6 +47205,9 @@ int Abc_CommandAbc9Mfs( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'b': pPars->fAllBoxes ^= 1; break; + case 'l': + pPars->fUseDcs ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -45835,12 +47247,21 @@ int Abc_CommandAbc9Mfs( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; } */ - pTemp = Gia_ManPerformMfs( pAbc->pGia, pPars ); + if ( Gia_ManRegNum(pAbc->pGia) == 0 ) + pTemp = Gia_ManPerformMfs( pAbc->pGia, pPars ); + else + { + int nRegs = Gia_ManRegNum(pAbc->pGia); + pAbc->pGia->nRegs = 0; + pTemp = Gia_ManPerformMfs( pAbc->pGia, pPars ); + Gia_ManSetRegNum( pAbc->pGia, nRegs ); + Gia_ManSetRegNum( pTemp, nRegs ); + } Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &mfs [-WFDMLCN <num>] [-daebvwh]\n" ); + Abc_Print( -2, "usage: &mfs [-WFDMLCN <num>] [-daeblvwh]\n" ); Abc_Print( -2, "\t performs don't-care-based optimization of logic networks\n" ); Abc_Print( -2, "\t-W <num> : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nTfoLevMax ); Abc_Print( -2, "\t-F <num> : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nFanoutMax ); @@ -45853,6 +47274,7 @@ usage: Abc_Print( -2, "\t-a : toggle minimizing area or area+edges [default = %s]\n", pPars->fArea? "area": "area+edges" ); Abc_Print( -2, "\t-e : toggle high-effort resubstitution [default = %s]\n", pPars->fMoreEffort? "yes": "no" ); Abc_Print( -2, "\t-b : toggle preserving all white boxes [default = %s]\n", pPars->fAllBoxes? "yes": "no" ); + Abc_Print( -2, "\t-l : toggle deriving don't-cares [default = %s]\n", pPars->fUseDcs? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -46043,13 +47465,35 @@ usage: ***********************************************************************/ int Abc_CommandAbc9DeepSyn( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Gia_Man_t * Gia_ManDeepSyn( Gia_Man_t * pGia, int TimeOut, int nAnds, int Seed, int fVerbose ); - Gia_Man_t * pTemp; int c, TimeOut = 0, nAnds = 0, Seed = 0, fVerbose = 0; + extern Gia_Man_t * Gia_ManDeepSyn( Gia_Man_t * pGia, int nIters, int nNoImpr, int TimeOut, int nAnds, int Seed, int fUseTwo, int fVerbose ); + Gia_Man_t * pTemp; int c, nIters = 1, nNoImpr = ABC_INFINITY, TimeOut = 0, nAnds = 0, Seed = 0, fUseTwo = 0, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "TASvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "IJTAStvh" ) ) != EOF ) { switch ( c ) { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'J': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-J\" should be followed by an integer.\n" ); + goto usage; + } + nNoImpr = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNoImpr < 0 ) + goto usage; + break; case 'T': if ( globalUtilOptind >= argc ) { @@ -46083,6 +47527,9 @@ int Abc_CommandAbc9DeepSyn( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( Seed < 0 ) goto usage; break; + case 't': + fUseTwo ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -46097,16 +47544,19 @@ int Abc_CommandAbc9DeepSyn( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9DeepSyn(): There is no AIG.\n" ); return 0; } - pTemp = Gia_ManDeepSyn( pAbc->pGia, TimeOut, nAnds, Seed, fVerbose ); + pTemp = Gia_ManDeepSyn( pAbc->pGia, nIters, nNoImpr, TimeOut, nAnds, Seed, fUseTwo, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &deepsyn [-TAS <num>] [-vh]\n" ); + Abc_Print( -2, "usage: &deepsyn [-IJTAS <num>] [-tvh]\n" ); Abc_Print( -2, "\t performs synthesis\n" ); + Abc_Print( -2, "\t-I <num> : the number of iterations [default = %d]\n", nIters ); + Abc_Print( -2, "\t-J <num> : the number of steps without improvements [default = %d]\n", nNoImpr ); Abc_Print( -2, "\t-T <num> : the timeout in seconds (0 = no timeout) [default = %d]\n", TimeOut ); Abc_Print( -2, "\t-A <num> : the number of nodes to stop (0 = no limit) [default = %d]\n", nAnds ); - Abc_Print( -2, "\t-S <num> : user-specified random seed (0 <= num <= 100) [default = %d]\n", Seed ); + Abc_Print( -2, "\t-S <num> : user-specified random seed (0 <= num <= 100) [default = %d]\n", Seed ); + Abc_Print( -2, "\t-t : toggle using two-input LUTs [default = %s]\n", fUseTwo? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -46123,6 +47573,107 @@ usage: SeeAlso [] ***********************************************************************/ +int Abc_CommandAbc9StochSyn( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManStochSyn( int nMaxSize, int nIters, int TimeOut, int Seed, int fVerbose, char * pScript ); + int c, nMaxSize = 1000, nIters = 10, TimeOut = 0, Seed = 0, fVerbose = 0; char * pScript; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NITSvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nMaxSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMaxSize < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + TimeOut = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( TimeOut < 0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Seed < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9StochSyn(): There is no AIG.\n" ); + return 0; + } + if ( argc != globalUtilOptind + 1 ) + { + printf( "Expecting a synthesis script in quotes on the command line (for example: \"&st; &dch; &if\").\n" ); + goto usage; + } + pScript = Abc_UtilStrsav( argv[globalUtilOptind] ); + Gia_ManStochSyn( nMaxSize, nIters, TimeOut, Seed, fVerbose, pScript ); + ABC_FREE( pScript ); + return 0; + +usage: + Abc_Print( -2, "usage: &stochsyn [-NITS <num>] [-tvh] <script>\n" ); + Abc_Print( -2, "\t performs stochastic synthesis\n" ); + Abc_Print( -2, "\t-N <num> : the max partition size (in AIG nodes or LUTs) [default = %d]\n", nMaxSize ); + Abc_Print( -2, "\t-I <num> : the number of iterations [default = %d]\n", nIters ); + Abc_Print( -2, "\t-T <num> : the timeout in seconds (0 = no timeout) [default = %d]\n", TimeOut ); + Abc_Print( -2, "\t-S <num> : user-specified random seed (0 <= num <= 100) [default = %d]\n", Seed ); + Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t<script> : synthesis script to use for each partition\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int Abc_CommandAbc9CexCut( Abc_Frame_t * pAbc, int argc, char ** argv ) { return -1; @@ -47779,6 +49330,10 @@ usage: ***********************************************************************/ int Abc_CommandAbc9Test( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern Gia_Man_t * Gia_ManPerformNewResub( Gia_Man_t * p, int nWinCount, int nCutSize, int nProcs, int fVerbose ); + extern void Gia_RsbEnumerateWindows( Gia_Man_t * p, int nInputsMax, int nLevelsMax ); + extern int Gia_ManSumTotalOfSupportSizes( Gia_Man_t * p ); + extern void Abc_Tt6MinTest2( Gia_Man_t * p ); int c, fVerbose = 0; int nFrames = 5; int fSwitch = 0; @@ -47834,13 +49389,13 @@ int Abc_CommandAbc9Test( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } -// if ( pAbc->pGia == NULL ) -// { -// Abc_Print( -1, "Abc_CommandAbc9Test(): There is no AIG.\n" ); -// return 1; -// } -// Abc_FrameUpdateGia( pAbc, Abc_Procedure(pAbc->pGia) ); -// Gia_SimQualityTest( pAbc->pGia ); + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Test(): There is no AIG.\n" ); + return 1; + } + Abc_FrameUpdateGia( pAbc, Gia_ManPerformNewResub(pAbc->pGia, 100, 6, 1, 1) ); +// printf( "AIG in \"%s\" has the sum of output support sizes equal to %d.\n", pAbc->pGia->pSpec, Gia_ManSumTotalOfSupportSizes(pAbc->pGia) ); return 0; usage: Abc_Print( -2, "usage: &test [-FW num] [-svh]\n" ); diff --git a/src/base/abci/abcBalance.c b/src/base/abci/abcBalance.c index 552cba7f..185ef9c1 100644 --- a/src/base/abci/abcBalance.c +++ b/src/base/abci/abcBalance.c @@ -266,7 +266,7 @@ Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_ if ( vSuper->nSize < 2 ) printf( "BUG!\n" ); // sort the new nodes by level in the decreasing order - Vec_PtrSort( vSuper, (int (*)(void))Abc_NodeCompareLevelsDecrease ); + Vec_PtrSort( vSuper, (int (*)(const void *, const void *))Abc_NodeCompareLevelsDecrease ); // balance the nodes assert( vSuper->nSize > 1 ); while ( vSuper->nSize > 1 ) diff --git a/src/base/abci/abcCollapse.c b/src/base/abci/abcCollapse.c index ca54d542..136712cb 100644 --- a/src/base/abci/abcCollapse.c +++ b/src/base/abci/abcCollapse.c @@ -195,7 +195,16 @@ Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk, int fReverse ) Extra_ProgressBarStop( pProgress ); return pNtkNew; } -Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fReverse, int fVerbose ) +void Abc_NtkDumpVariableOrder( Abc_Ntk_t * pNtk ) +{ + DdManager * dd = (DdManager *)Abc_NtkGlobalBddMan( pNtk ); + FILE * pFile = fopen( "order.txt", "wb" ); int i; + for ( i = 0; i < dd->size; i++ ) + fprintf( pFile, "%d ", dd->invperm[i] ); + fprintf( pFile, "\n" ); + fclose( pFile ); +} +Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fReverse, int fDumpOrder, int fVerbose ) { Abc_Ntk_t * pNtkNew; abctime clk = Abc_Clock(); @@ -210,6 +219,8 @@ Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, i printf( "Shared BDD size = %6d nodes. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); ABC_PRT( "BDD construction time", Abc_Clock() - clk ); } + if ( fDumpOrder ) + Abc_NtkDumpVariableOrder( pNtk ); // create the new network pNtkNew = Abc_NtkFromGlobalBdds( pNtk, fReverse ); @@ -236,7 +247,7 @@ Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, i #else -Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fReverse, int fVerbose ) +Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fReverse, int fDumpOrder, int fVerbose ) { return NULL; } diff --git a/src/base/abci/abcDar.c b/src/base/abci/abcDar.c index 56eb139a..483f65b9 100644 --- a/src/base/abci/abcDar.c +++ b/src/base/abci/abcDar.c @@ -91,7 +91,7 @@ void Abc_CollectTopOr( Abc_Obj_t * pObj, Vec_Ptr_t * vSuper ) if ( Abc_ObjIsComplement(pObj) ) { Abc_CollectTopOr_rec( Abc_ObjNot(pObj), vSuper ); - Vec_PtrUniqify( vSuper, (int (*)())Abc_ObjCompareById ); + Vec_PtrUniqify( vSuper, (int (*)(const void *, const void *))Abc_ObjCompareById ); } else Vec_PtrPush( vSuper, Abc_ObjNot(pObj) ); @@ -858,6 +858,7 @@ Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p, int fFindEnables, int fUseBuffs Gia_LutForEachFanin( p, i, iFan, k ) Abc_ObjAddFanin( pObjNew, Abc_NtkObj(pNtkNew, Gia_ObjValue(Gia_ManObj(p, iFan))) ); pObjNew->pData = Abc_ObjHopFromGia( (Hop_Man_t *)pNtkNew->pManFunc, p, i, vReflect ); + pObjNew->fPersist = Gia_ObjLutIsMux(p, i) && Gia_ObjLutSize(p, i) == 3; pObj->Value = Abc_ObjId( pObjNew ); } Vec_PtrFree( vReflect ); @@ -1650,6 +1651,7 @@ Abc_Ntk_t * Abc_NtkDChoice( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, in ***********************************************************************/ Abc_Ntk_t * Abc_NtkDch( Abc_Ntk_t * pNtk, Dch_Pars_t * pPars ) { + extern Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ); extern Gia_Man_t * Dar_NewChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fLightSynth, int fVerbose ); extern Aig_Man_t * Cec_ComputeChoices( Gia_Man_t * pGia, Dch_Pars_t * pPars ); @@ -1661,23 +1663,28 @@ Abc_Ntk_t * Abc_NtkDch( Abc_Ntk_t * pNtk, Dch_Pars_t * pPars ) pMan = Abc_NtkToDar( pNtk, 0, 0 ); if ( pMan == NULL ) return NULL; -clk = Abc_Clock(); - if ( pPars->fSynthesis ) - pGia = Dar_NewChoiceSynthesis( pMan, 1, 1, pPars->fPower, pPars->fLightSynth, pPars->fVerbose ); - else + if ( pPars->fUseNew ) + pMan = Dar_ManChoiceNew( pMan, pPars ); + else { - pGia = Gia_ManFromAig( pMan ); - Aig_ManStop( pMan ); - } +clk = Abc_Clock(); + if ( pPars->fSynthesis ) + pGia = Dar_NewChoiceSynthesis( pMan, 1, 1, pPars->fPower, pPars->fLightSynth, pPars->fVerbose ); + else + { + pGia = Gia_ManFromAig( pMan ); + Aig_ManStop( pMan ); + } pPars->timeSynth = Abc_Clock() - clk; - if ( pPars->fUseGia ) - pMan = Cec_ComputeChoices( pGia, pPars ); - else - { - pMan = Gia_ManToAigSkip( pGia, 3 ); - Gia_ManStop( pGia ); - pMan = Dch_ComputeChoices( pTemp = pMan, pPars ); - Aig_ManStop( pTemp ); + if ( pPars->fUseGia ) + pMan = Cec_ComputeChoices( pGia, pPars ); + else + { + pMan = Gia_ManToAigSkip( pGia, 3 ); + Gia_ManStop( pGia ); + pMan = Dch_ComputeChoices( pTemp = pMan, pPars ); + Aig_ManStop( pTemp ); + } } pNtkAig = Abc_NtkFromDarChoices( pNtk, pMan ); Aig_ManStop( pMan ); diff --git a/src/base/abci/abcDress2.c b/src/base/abci/abcDress2.c index 1b1eb9bf..e7adb41f 100644 --- a/src/base/abci/abcDress2.c +++ b/src/base/abci/abcDress2.c @@ -21,6 +21,7 @@ #include "base/abc/abc.h" #include "aig/aig/aig.h" #include "proof/dch/dch.h" +#include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START @@ -274,6 +275,32 @@ Vec_Ptr_t * Abc_NtkDressMapIds( Aig_Man_t * pMiter, Abc_Ntk_t * pNtk1, Abc_Ntk_t /**Function************************************************************* + Synopsis [Alternative way to compute equivalences.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ComputeEquivalences2( Aig_Man_t * pMiter, Dch_Pars_t * pPars ) +{ + extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); + Gia_Man_t * pGia = Gia_ManFromAigSimple(pMiter); + Gia_Man_t * pNew = Cec4_ManSimulateTest3( pGia, pPars->nBTLimit, pPars->fVerbose ); + int i, k; + ABC_FREE( pMiter->pReprs ); + pMiter->pReprs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pMiter) ); + Gia_ManForEachClass( pGia, i ) + Gia_ClassForEachObj1( pGia, i, k ) + pMiter->pReprs[k] = Aig_ManObj( pMiter, i ); + Gia_ManStop( pGia ); + Gia_ManStop( pNew ); +} + +/**Function************************************************************* + Synopsis [Computes equivalence classes of objects in pNtk1 and pNtk2.] Description [Returns the array (Vec_Ptr_t) of integer arrays (Vec_Int_t). @@ -307,7 +334,7 @@ Vec_Ptr_t * Abc_NtkDressComputeEquivs( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int pPars->nBTLimit = nConflictLimit; pPars->fVerbose = fVerbose; // perform SAT sweeping - Dch_ComputeEquivalences( pMiter, pPars ); + Dch_ComputeEquivalences2( pMiter, pPars ); // now, pMiter is annotated with the equivl class info // convert this info into the resulting array vRes = Abc_NtkDressMapIds( pMiter, pNtk1, pNtk2 ); diff --git a/src/base/abci/abcEspresso.c b/src/base/abci/abcEspresso.c index 2da389da..9296b1e7 100644 --- a/src/base/abci/abcEspresso.c +++ b/src/base/abci/abcEspresso.c @@ -58,7 +58,7 @@ void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose ) Abc_NtkMapToSop(pNtk); else if ( Abc_NtkHasBdd(pNtk) ) { - if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY) ) + if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY, 1) ) { printf( "Abc_NtkEspresso(): Converting to SOPs has failed.\n" ); return; diff --git a/src/base/abci/abcExtract.c b/src/base/abci/abcExtract.c index 1b247841..870bc7dc 100644 --- a/src/base/abci/abcExtract.c +++ b/src/base/abci/abcExtract.c @@ -19,6 +19,7 @@ ***********************************************************************/ #include "base/abc/abc.h" +#include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START @@ -741,7 +742,21 @@ Abc_Ntk_t * Abc_NtkShareXor( Abc_Ntk_t * pNtk, int nMultiSize, int fAnd, int fVe Abc_ShaManStop( p ); return pNtkNew; } - +Gia_Man_t * Abc_NtkShareXorGia( Gia_Man_t * p, int nMultiSize, int fAnd, int fVerbose ) +{ + extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); + extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); + Aig_Man_t * pMan = Gia_ManToAig( p, 0 ); + Abc_Ntk_t * pNtk = Abc_NtkFromAigPhase( pMan ); + Abc_Ntk_t * pNtkNew = Abc_NtkShareXor( pNtk, nMultiSize, fAnd, fVerbose ); + Aig_Man_t * pAig = Abc_NtkToDar( pNtkNew, 0, 0 ); + Gia_Man_t * pNew = Gia_ManFromAig( pAig ); + Abc_NtkDelete( pNtkNew ); + Abc_NtkDelete( pNtk ); + Aig_ManStop( pAig ); + Aig_ManStop( pMan ); + return pNew; +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/base/abci/abcFx.c b/src/base/abci/abcFx.c index 60461a4a..487aee3c 100644 --- a/src/base/abci/abcFx.c +++ b/src/base/abci/abcFx.c @@ -201,7 +201,7 @@ void Abc_NtkFxInsert( Abc_Ntk_t * pNtk, Vec_Wec_t * vCubes ) // quit if nothing changes if ( iNodeMax < Abc_NtkObjNumMax(pNtk) ) { - printf( "The network is unchanged by fast extract.\n" ); + //printf( "The network is unchanged by fast extract.\n" ); return; } // create new nodes diff --git a/src/base/abci/abcFxu.c b/src/base/abci/abcFxu.c index 8da306bf..99b3a5eb 100644 --- a/src/base/abci/abcFxu.c +++ b/src/base/abci/abcFxu.c @@ -88,7 +88,7 @@ int Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p ) if ( Abc_NtkIsSopLogic(pNtk) ) { // to make sure the SOPs are SCC-free // Abc_NtkSopToBdd(pNtk); -// Abc_NtkBddToSop(pNtk); +// Abc_NtkBddToSop(pNtk, 1); } // get the network in the SOP form if ( !Abc_NtkToSop(pNtk, -1, ABC_INFINITY) ) diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c index ab88c5e2..491e2c14 100644 --- a/src/base/abci/abcIf.c +++ b/src/base/abci/abcIf.c @@ -230,9 +230,13 @@ If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)If_ManConst1( pIfMan ); Abc_NtkForEachCi( pNtk, pNode, i ) { - pNode->pCopy = (Abc_Obj_t *)If_ManCreateCi( pIfMan ); + If_Obj_t * pIfObj = If_ManCreateCi( pIfMan ); + pNode->pCopy = (Abc_Obj_t *)pIfObj; // transfer logic level information Abc_ObjIfCopy(pNode)->Level = pNode->Level; + // mark the largest level + if ( pIfMan->nLevelMax < (int)pIfObj->Level ) + pIfMan->nLevelMax = (int)pIfObj->Level; } // load the AIG into the mapper diff --git a/src/base/abci/abcIvy.c b/src/base/abci/abcIvy.c index 5dc125d0..c680f85a 100644 --- a/src/base/abci/abcIvy.c +++ b/src/base/abci/abcIvy.c @@ -91,7 +91,7 @@ Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc ) assert( !Abc_NtkIsNetlist(pNtk) ); if ( Abc_NtkIsBddLogic(pNtk) ) { - if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY) ) + if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY, 1) ) { printf( "Abc_NtkIvyBefore(): Converting to SOPs has failed.\n" ); return NULL; @@ -601,7 +601,7 @@ int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars ) printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit ); fflush( stdout ); } - pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0, 0 ); + pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0, 0, 0 ); if ( pNtk ) { Abc_NtkDelete( pNtkTemp ); @@ -640,7 +640,7 @@ Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk ) assert( !Abc_NtkIsNetlist(pNtk) ); if ( Abc_NtkIsBddLogic(pNtk) ) { - if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY) ) + if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY, 1) ) { Vec_IntFree( vInit ); printf( "Abc_NtkIvy(): Converting to SOPs has failed.\n" ); diff --git a/src/base/abci/abcLut.c b/src/base/abci/abcLut.c index edc2b7de..49c74e6b 100644 --- a/src/base/abci/abcLut.c +++ b/src/base/abci/abcLut.c @@ -783,6 +783,166 @@ int Abc_NodeDecomposeStep( Abc_ManScl_t * p ) return 1; } +/**Function************************************************************* + + Synopsis [Performs specialized mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static word s__Truths6[6] = { + ABC_CONST(0xAAAAAAAAAAAAAAAA), + ABC_CONST(0xCCCCCCCCCCCCCCCC), + ABC_CONST(0xF0F0F0F0F0F0F0F0), + ABC_CONST(0xFF00FF00FF00FF00), + ABC_CONST(0xFFFF0000FFFF0000), + ABC_CONST(0xFFFFFFFF00000000) +}; +word Abc_ObjComputeTruth( Abc_Obj_t * pObj, Vec_Int_t * vSupp ) +{ + int Index; word t0, t1, tc; + assert( Vec_IntSize(vSupp) <= 6 ); + if ( (Index = Vec_IntFind(vSupp, Abc_ObjId(pObj))) >= 0 ) + return s__Truths6[Index]; + assert( Abc_ObjIsNode(pObj) ); + if ( Abc_ObjFaninNum(pObj) == 0 ) + return Abc_NodeIsConst0(pObj) ? (word)0 : ~(word)0; + assert( Abc_ObjFaninNum(pObj) == 3 ); + t0 = Abc_ObjComputeTruth( Abc_ObjFanin(pObj, 2), vSupp ); + t1 = Abc_ObjComputeTruth( Abc_ObjFanin(pObj, 1), vSupp ); + tc = Abc_ObjComputeTruth( Abc_ObjFanin(pObj, 0), vSupp ); + return (tc & t1) | (~tc & t0); +} +Abc_Obj_t * Abc_NtkSpecialMap_rec( Abc_Ntk_t * pNew, Abc_Obj_t * pObj, Vec_Wec_t * vSupps, Vec_Int_t * vCover ) +{ + if ( pObj->pCopy ) + return pObj->pCopy; + if ( Abc_ObjFaninNum(pObj) == 0 ) + return NULL; + assert( Abc_ObjFaninNum(pObj) == 3 ); + if ( pObj->fMarkA || pObj->fMarkB ) + { + Abc_Obj_t * pFan0 = Abc_NtkSpecialMap_rec( pNew, Abc_ObjFanin(pObj, 2), vSupps, vCover ); + Abc_Obj_t * pFan1 = Abc_NtkSpecialMap_rec( pNew, Abc_ObjFanin(pObj, 1), vSupps, vCover ); + Abc_Obj_t * pFanC = Abc_NtkSpecialMap_rec( pNew, Abc_ObjFanin(pObj, 0), vSupps, vCover ); + if ( pFan0 == NULL ) + pFan0 = Abc_NodeIsConst0(Abc_ObjFanin(pObj, 2)) ? Abc_NtkCreateNodeConst0(pNew) : Abc_NtkCreateNodeConst1(pNew); + if ( pFan1 == NULL ) + pFan1 = Abc_NodeIsConst0(Abc_ObjFanin(pObj, 1)) ? Abc_NtkCreateNodeConst0(pNew) : Abc_NtkCreateNodeConst1(pNew); + pObj->pCopy = Abc_NtkCreateNodeMux( pNew, pFanC, pFan1, pFan0 ); + pObj->pCopy->fMarkA = pObj->fMarkA; + pObj->pCopy->fMarkB = pObj->fMarkB; + } + else + { + Abc_Obj_t * pTemp; int i; word Truth; + Vec_Int_t * vSupp = Vec_WecEntry( vSupps, Abc_ObjId(pObj) ); + Abc_NtkForEachObjVec( vSupp, pObj->pNtk, pTemp, i ) + Abc_NtkSpecialMap_rec( pNew, pTemp, vSupps, vCover ); + pObj->pCopy = Abc_NtkCreateNode( pNew ); + Abc_NtkForEachObjVec( vSupp, pObj->pNtk, pTemp, i ) + Abc_ObjAddFanin( pObj->pCopy, pTemp->pCopy ); + Truth = Abc_ObjComputeTruth( pObj, vSupp ); + pObj->pCopy->pData = Abc_SopCreateFromTruthIsop( (Mem_Flex_t *)pNew->pManFunc, Vec_IntSize(vSupp), &Truth, vCover ); + assert( Abc_SopGetVarNum((char *)pObj->pCopy->pData) == Vec_IntSize(vSupp) ); + } + return pObj->pCopy; +} +Abc_Ntk_t * Abc_NtkSpecialMapping( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Abc_Ntk_t * pNtkNew; + Vec_Int_t * vCover = Vec_IntAlloc( 1 << 16 ); + Vec_Wec_t * vSupps = Vec_WecStart( Abc_NtkObjNumMax(pNtk) ); + Abc_Obj_t * pObj, * pFan0, * pFan1, * pFanC; int i, Count[2] = {0}; + Abc_NtkForEachCi( pNtk, pObj, i ) + Vec_IntPush( Vec_WecEntry(vSupps, i), i ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + Vec_Int_t * vSupp = Vec_WecEntry(vSupps, i); + if ( Abc_ObjFaninNum(pObj) == 0 ) + continue; + assert( Abc_ObjFaninNum(pObj) == 3 ); + pFan0 = Abc_ObjFanin( pObj, 2 ); + pFan1 = Abc_ObjFanin( pObj, 1 ); + pFanC = Abc_ObjFanin0( pObj ); + assert( Abc_ObjIsCi(pFanC) ); + if ( pFan0->fMarkA && pFan1->fMarkA ) + { + pObj->fMarkB = 1; + Vec_IntPush( vSupp, Abc_ObjId(pObj) ); + continue; + } + Vec_IntTwoMerge2( Vec_WecEntry(vSupps, Abc_ObjId(pFan0)), Vec_WecEntry(vSupps, Abc_ObjId(pFan1)), vSupp ); + assert( Vec_IntFind(vSupp, Abc_ObjId(pFanC)) == -1 ); + Vec_IntPushOrder( vSupp, Abc_ObjId(pFanC) ); + if ( Vec_IntSize(vSupp) <= 6 ) + continue; + Vec_IntClear( vSupp ); + if ( !pFan0->fMarkA && !pFan1->fMarkA ) + { + pObj->fMarkA = 1; + Vec_IntPush( vSupp, Abc_ObjId(pObj) ); + } + else + { + Vec_IntPushOrder( vSupp, Abc_ObjId(pFan0) ); + Vec_IntPushOrder( vSupp, Abc_ObjId(pFan1) ); + Vec_IntPushOrder( vSupp, Abc_ObjId(pFanC) ); + } + } + + if ( fVerbose ) + { + Abc_NtkForEachNode( pNtk, pObj, i ) + { + printf( "Node %4d : ", i ); + if ( pObj->fMarkA ) + printf( " MarkA " ); + else + printf( " " ); + if ( pObj->fMarkB ) + printf( " MarkB " ); + else + printf( " " ); + Vec_IntPrint( Vec_WecEntry(vSupps, i) ); + } + } + + Abc_NtkCleanCopy( pNtk ); + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + Abc_NtkForEachCo( pNtk, pObj, i ) + if ( Abc_ObjFaninNum(Abc_ObjFanin0(pObj)) == 0 ) + Abc_ObjFanin0(pObj)->pCopy = Abc_NodeIsConst0(Abc_ObjFanin0(pObj)) ? Abc_NtkCreateNodeConst0(pNtkNew) : Abc_NtkCreateNodeConst1(pNtkNew); + else + Abc_NtkSpecialMap_rec( pNtkNew, Abc_ObjFanin0(pObj), vSupps, vCover ); + Abc_NtkFinalize( pNtk, pNtkNew ); + Abc_NtkCleanMarkAB( pNtk ); + Vec_WecFree( vSupps ); + Vec_IntFree( vCover ); + + Abc_NtkForEachNode( pNtkNew, pObj, i ) + { + Count[0] += pObj->fMarkA, + Count[1] += pObj->fMarkB; + pObj->fPersist = pObj->fMarkA | pObj->fMarkB; + pObj->fMarkA = pObj->fMarkB = 0; + } + //printf( "Total = %3d. Nodes = %3d. MarkA = %3d. MarkB = %3d.\n", Abc_NtkNodeNum(pNtkNew), + // Abc_NtkNodeNum(pNtkNew) - Count[0] - Count[1], Count[0], Count[1] ); + + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkSpecialMapping: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abcLutmin.c b/src/base/abci/abcLutmin.c index 2ac44060..7bac74bf 100644 --- a/src/base/abci/abcLutmin.c +++ b/src/base/abci/abcLutmin.c @@ -610,7 +610,7 @@ Abc_Obj_t * Abc_NtkBddDecompose( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int nLu // cofactor w.r.t. the bound set variables vCofs = Abc_NtkBddCofactors( dd, (DdNode *)pNode->pData, nLutSize ); vUniq = Vec_PtrDup( vCofs ); - Vec_PtrUniqify( vUniq, (int (*)())Vec_PtrSortCompare ); + Vec_PtrUniqify( vUniq, (int (*)(const void *, const void *))Vec_PtrSortCompare ); // only perform decomposition with it is support reduring with two less vars if( Vec_PtrSize(vUniq) > (1 << (nLutSize-2)) ) { @@ -739,7 +739,7 @@ Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtkInit, int nLutSize, int fVerbose ) else pNtkNew = Abc_NtkStrash( pNtkInit, 0, 1, 0 ); // collapse the network - pNtkNew = Abc_NtkCollapse( pTemp = pNtkNew, 10000, 0, 1, 0, 0 ); + pNtkNew = Abc_NtkCollapse( pTemp = pNtkNew, 10000, 0, 1, 0, 0, 0 ); Abc_NtkDelete( pTemp ); if ( pNtkNew == NULL ) return NULL; diff --git a/src/base/abci/abcMap.c b/src/base/abci/abcMap.c index 5389b669..8f5e4ee2 100644 --- a/src/base/abci/abcMap.c +++ b/src/base/abci/abcMap.c @@ -32,8 +32,8 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, float * pSwitching, int fVerbose ); -static Abc_Ntk_t * Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk, int fUseBuffs ); +extern Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, float * pSwitching, int fVerbose ); +extern Abc_Ntk_t * Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk, int fUseBuffs ); static Abc_Obj_t * Abc_NodeFromMap_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase ); static Abc_Obj_t * Abc_NodeFromMapPhase_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase ); @@ -612,7 +612,7 @@ Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk ) // duplicate the network pNtkNew2 = Abc_NtkDup( pNtk ); pNtkNew = Abc_NtkMulti( pNtkNew2, 0, 20, 0, 0, 1, 0 ); - if ( !Abc_NtkBddToSop( pNtkNew, -1, ABC_INFINITY ) ) + if ( !Abc_NtkBddToSop( pNtkNew, -1, ABC_INFINITY, 1 ) ) { printf( "Abc_NtkFromMapSuperChoice(): Converting to SOPs has failed.\n" ); return NULL; diff --git a/src/base/abci/abcMffc.c b/src/base/abci/abcMffc.c index 1d64df5c..55f39252 100644 --- a/src/base/abci/abcMffc.c +++ b/src/base/abci/abcMffc.c @@ -1141,7 +1141,7 @@ Vec_Ptr_t * Abc_NktMffcServer( Abc_Ntk_t * pNtk, int nInMax, int nOutMax ) // sort by their MFFC size Vec_PtrForEachEntry( Abc_Obj_t *, vPivots, pObj, i ) pObj->iTemp = Vec_IntSize((Vec_Int_t *)Vec_PtrEntry(vVolumes, Abc_ObjId(pObj))); - Vec_PtrSort( vPivots, (int (*)(void))Abc_NodeCompareVolumeDecrease ); + Vec_PtrSort( vPivots, (int (*)(const void *, const void *))Abc_NodeCompareVolumeDecrease ); // create marks vMarks = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); Vec_PtrForEachEntry( Abc_Obj_t *, vPivots, pObj, i ) diff --git a/src/base/abci/abcMiter.c b/src/base/abci/abcMiter.c index 81b032d4..6086fc61 100644 --- a/src/base/abci/abcMiter.c +++ b/src/base/abci/abcMiter.c @@ -863,7 +863,7 @@ void Abc_NtkAddFrame( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame ) { int fVerbose = 0; int NodeBef = Abc_NtkNodeNum(pNtkFrames); - char Buffer[10]; + char Buffer[16]; Abc_Obj_t * pNode, * pLatch; int i; // create the prefix to be added to the node names @@ -1008,7 +1008,7 @@ Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFram void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes, AddFrameMapping addFrameMapping, void* arg ) { /* - char Buffer[10]; + char Buffer[16]; Abc_Obj_t * pNode, * pNodeNew, * pLatch; Abc_Obj_t * pConst1, * pConst1New; int i; diff --git a/src/base/abci/abcNpnSave.c b/src/base/abci/abcNpnSave.c index 0e2d13d5..3dd97432 100644 --- a/src/base/abci/abcNpnSave.c +++ b/src/base/abci/abcNpnSave.c @@ -564,7 +564,7 @@ void Npn_ManWrite( Npn_Man_t * p, char * pFileName ) for ( i = 0; i < p->nBins; i++ ) for ( pEntry = Npn_ManObj(p, p->pBins[i]); pEntry; pEntry = Npn_ManObj(p, pEntry->iNext) ) Vec_PtrPush( vEntries, pEntry ); - Vec_PtrSort( vEntries, (int (*)())Npn_ManCompareEntries ); + Vec_PtrSort( vEntries, (int (*)(const void *, const void *))Npn_ManCompareEntries ); Vec_PtrForEachEntry( Npn_Obj_t *, vEntries, pEntry, i ) { Extra_PrintHexadecimal( pFile, (unsigned *)&pEntry->uTruth, 6 ); diff --git a/src/base/abci/abcNtbdd.c b/src/base/abci/abcNtbdd.c index d3a19d83..cbf4bbb8 100644 --- a/src/base/abci/abcNtbdd.c +++ b/src/base/abci/abcNtbdd.c @@ -34,7 +34,7 @@ ABC_NAMESPACE_IMPL_START #ifdef ABC_USE_CUDD -static int Abc_NtkBddToMuxesPerformGlo( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int Limit ); + int Abc_NtkBddToMuxesPerformGlo( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int Limit, int fReorder, int fUseAdd ); static void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); static Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew ); static Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * pNtkNew, st__table * tBdd2Node ); @@ -129,13 +129,13 @@ Abc_Ntk_t * Abc_NtkDeriveFromBdd( void * dd0, void * bFunc, char * pNamePo, Vec_ SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk, int fGlobal, int Limit ) +Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk, int fGlobal, int Limit, int fUseAdd ) { Abc_Ntk_t * pNtkNew; pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); if ( fGlobal ) { - if ( !Abc_NtkBddToMuxesPerformGlo( pNtk, pNtkNew, Limit ) ) + if ( !Abc_NtkBddToMuxesPerformGlo( pNtk, pNtkNew, Limit, 0, fUseAdd ) ) { Abc_NtkDelete( pNtkNew ); return NULL; @@ -237,8 +237,10 @@ Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * { Abc_Obj_t * pNodeNew, * pNodeNew0, * pNodeNew1, * pNodeNewC; assert( !Cudd_IsComplement(bFunc) ); - if ( bFunc == b1 ) + if ( bFunc == b1 || bFunc == a1 ) return Abc_NtkCreateNodeConst1(pNtkNew); + if ( bFunc == a0 ) + return Abc_NtkCreateNodeConst0(pNtkNew); if ( st__lookup( tBdd2Node, (char *)bFunc, (char **)&pNodeNew ) ) return pNodeNew; // solve for the children nodes @@ -265,13 +267,14 @@ Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * SeeAlso [] ***********************************************************************/ -int Abc_NtkBddToMuxesPerformGlo( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int Limit ) +int Abc_NtkBddToMuxesPerformGlo( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int Limit, int fReorder, int fUseAdd ) { DdManager * dd; + Vec_Ptr_t * vAdds = fUseAdd ? Vec_PtrAlloc(100) : NULL; Abc_Obj_t * pObj, * pObjNew; int i; st__table * tBdd2Node; assert( Abc_NtkIsStrash(pNtk) ); - dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, Limit, 1, 1, 0, 0 ); + dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, Limit, 1, fReorder, 0, 0 ); if ( dd == NULL ) { printf( "Construction of global BDDs has failed.\n" ); @@ -286,16 +289,32 @@ int Abc_NtkBddToMuxesPerformGlo( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int Limi // complement the global functions Abc_NtkForEachCo( pNtk, pObj, i ) { - DdNode * bFunc = Abc_ObjGlobalBdd(pObj); - pObjNew = Abc_NodeBddToMuxes_rec( dd, Cudd_Regular(bFunc), pNtkNew, tBdd2Node ); - if ( Cudd_IsComplement(bFunc) ) - pObjNew = Abc_NtkCreateNodeInv( pNtkNew, pObjNew ); + DdNode * bFunc = (DdNode *)Abc_ObjGlobalBdd(pObj); + if ( fUseAdd ) + { + DdNode * aFunc = Cudd_BddToAdd( dd, bFunc ); Cudd_Ref( aFunc ); + pObjNew = Abc_NodeBddToMuxes_rec( dd, aFunc, pNtkNew, tBdd2Node ); + Vec_PtrPush( vAdds, aFunc ); + } + else + { + pObjNew = Abc_NodeBddToMuxes_rec( dd, Cudd_Regular(bFunc), pNtkNew, tBdd2Node ); + if ( Cudd_IsComplement(bFunc) ) + pObjNew = Abc_NtkCreateNodeInv( pNtkNew, pObjNew ); + } Abc_ObjAddFanin( pObj->pCopy, pObjNew ); } // cleanup st__free_table( tBdd2Node ); Abc_NtkFreeGlobalBdds( pNtk, 0 ); + if ( vAdds ) + { + DdNode * aTemp; + Vec_PtrForEachEntry( DdNode *, vAdds, aTemp, i ) + Cudd_RecursiveDeref( dd, aTemp ); + Vec_PtrFree( vAdds ); + } Extra_StopManager( dd ); Abc_NtkCleanCopy( pNtk ); return 1; @@ -410,6 +429,7 @@ void * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fDropInter if ( fReorder ) { Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); +// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); Cudd_AutodynDisable( dd ); } // Cudd_PrintInfo( dd, stdout ); @@ -662,7 +682,7 @@ ABC_PRT( "Time", Abc_Clock() - clk ); #else double Abc_NtkSpacePercentage( Abc_Obj_t * pNode ) { return 0.0; } -Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk, int fGlobal, int Limit ) { return NULL; } +Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk, int fGlobal, int Limit, int fUseAdd ) { return NULL; } #endif diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c index ad5fba91..44d5c2c3 100644 --- a/src/base/abci/abcPrint.c +++ b/src/base/abci/abcPrint.c @@ -453,6 +453,15 @@ void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDum // if ( Abc_NtkHasSop(pNtk) ) // printf( "The total number of cube pairs = %d.\n", Abc_NtkGetCubePairNum(pNtk) ); + if ( 0 ) + { + FILE * pTable = fopen( "stats.txt", "a+" ); + if ( Abc_NtkIsStrash(pNtk) ) + fprintf( pTable, "%s ", pNtk->pName ); + fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); + fclose( pTable ); + } + fflush( stdout ); if ( pNtk->pExdc ) Abc_NtkPrintStats( pNtk->pExdc, fFactored, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf, fSkipSmall, fPrintMem ); @@ -1399,7 +1408,7 @@ void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary, int fUpdateProfile ) // transform logic functions from BDD to SOP if ( (fHasBdds = Abc_NtkIsBddLogic(pNtk)) ) { - if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY) ) + if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY, 1) ) { printf( "Abc_NtkPrintGates(): Converting to SOPs has failed.\n" ); return; diff --git a/src/base/abci/abcProve.c b/src/base/abci/abcProve.c index 03722926..b14c0827 100644 --- a/src/base/abci/abcProve.c +++ b/src/base/abci/abcProve.c @@ -201,7 +201,7 @@ int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pPars ) fflush( stdout ); } clk = Abc_Clock(); - pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0, 0 ); + pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0, 0, 0 ); if ( pNtk ) { Abc_NtkDelete( pNtkTemp ); diff --git a/src/base/abci/abcReorder.c b/src/base/abci/abcReorder.c index cf8759c7..8557be1e 100644 --- a/src/base/abci/abcReorder.c +++ b/src/base/abci/abcReorder.c @@ -84,7 +84,7 @@ void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ) reo_man * p; Abc_Obj_t * pNode; int i; - Abc_NtkRemoveDupFanins( pNtk ); + //Abc_NtkRemoveDupFanins( pNtk ); Abc_NtkMinimumBase( pNtk ); p = Extra_ReorderInit( Abc_NtkGetFaninMax(pNtk), 100 ); Abc_NtkForEachNode( pNtk, pNode, i ) diff --git a/src/base/abci/abcStrash.c b/src/base/abci/abcStrash.c index e4868d7e..d54957a6 100644 --- a/src/base/abci/abcStrash.c +++ b/src/base/abci/abcStrash.c @@ -548,25 +548,27 @@ Abc_Obj_t * Abc_NtkTopmost_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int Leve Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ) { Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObjNew, * pObjPo; - int LevelCut; + Abc_Obj_t * pObjNew, * pObj; + int LevelCut, i; assert( Abc_NtkIsStrash(pNtk) ); - assert( Abc_NtkCoNum(pNtk) == 1 ); // get the cutoff level LevelCut = Abc_MaxInt( 0, Abc_AigLevel(pNtk) - nLevels ); // start the network pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); - Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); // create PIs below the cut and nodes above the cut Abc_NtkCleanCopy( pNtk ); - pObjNew = Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(Abc_NtkPo(pNtk, 0)), LevelCut ); - pObjNew = Abc_ObjNotCond( pObjNew, Abc_ObjFaninC0(Abc_NtkPo(pNtk, 0)) ); + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pObjNew = Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(pObj), LevelCut ); + pObjNew = Abc_ObjNotCond( pObjNew, Abc_ObjFaninC0(pObj) ); + Abc_ObjAddFanin( (pObj->pCopy = Abc_NtkCreatePo(pNtkNew)), pObjNew ); + } // add the PO node and name - pObjPo = Abc_NtkCreatePo(pNtkNew); - Abc_ObjAddFanin( pObjPo, pObjNew ); Abc_NtkAddDummyPiNames( pNtkNew ); - Abc_ObjAssignName( pObjPo, Abc_ObjName(Abc_NtkPo(pNtk, 0)), NULL ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); // make sure everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { @@ -578,6 +580,74 @@ Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ) } +/**Function************************************************************* + + Synopsis [Copies the bottommost levels of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkBottommost_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int LevelCut ) +{ + assert( !Abc_ObjIsComplement(pNode) ); + if ( pNode->pCopy ) + return pNode->pCopy; + Abc_NtkBottommost_rec( pNtkNew, Abc_ObjFanin0(pNode), LevelCut ); + Abc_NtkBottommost_rec( pNtkNew, Abc_ObjFanin1(pNode), LevelCut ); + if ( pNode->Level > (unsigned)LevelCut ) + return NULL; + return pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); +} + +/**Function************************************************************* + + Synopsis [Copies the topmost levels of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkBottommost( Abc_Ntk_t * pNtk, int nLevels ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pObjNew; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + assert( nLevels >= 0 ); + // start the network + pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + // create PIs below the cut and nodes above the cut + Abc_NtkCleanCopy( pNtk ); + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy = Abc_NtkCreatePi( pNtkNew ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_NtkBottommost_rec( pNtkNew, Abc_ObjFanin0(pObj), nLevels ); + // add POs to nodes without fanout + Abc_NtkForEachNode( pNtkNew, pObjNew, i ) + if ( Abc_ObjFanoutNum(pObjNew) == 0 ) + Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pObjNew ); + Abc_NtkAddDummyPiNames( pNtkNew ); + Abc_NtkAddDummyPoNames( pNtkNew ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkBottommost: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + + /**Function************************************************************* @@ -642,7 +712,7 @@ Vec_Ptr_t * Abc_NodeGetSuper( Abc_Obj_t * pNode ) Vec_PtrFree( vSuper ); vSuper = vFront; // uniquify and return the frontier - Vec_PtrUniqify( vSuper, (int (*)())Vec_CompareNodeIds ); + Vec_PtrUniqify( vSuper, (int (*)(const void *, const void *))Vec_CompareNodeIds ); return vSuper; } diff --git a/src/base/abci/abcSweep.c b/src/base/abci/abcSweep.c index e970ac38..3306a6af 100644 --- a/src/base/abci/abcSweep.c +++ b/src/base/abci/abcSweep.c @@ -619,7 +619,7 @@ int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose ) nNodesOld = Abc_NtkNodeNum(pNtk); Abc_NtkCleanup( pNtk, 0 ); // prepare nodes for sweeping - Abc_NtkRemoveDupFanins(pNtk); + //Abc_NtkRemoveDupFanins(pNtk); Abc_NtkMinimumBase(pNtk); // collect sweepable nodes vNodes = Vec_PtrAlloc( 100 ); @@ -649,7 +649,7 @@ int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose ) Abc_NodeComplementInput( pFanout, pNode ); Abc_ObjPatchFanin( pFanout, pNode, pDriver ); } - Abc_NodeRemoveDupFanins( pFanout ); + //Abc_NodeRemoveDupFanins( pFanout ); Abc_NodeMinimumBase( pFanout ); // check if the fanout should be added if ( Abc_ObjFaninNum(pFanout) < 2 ) @@ -888,7 +888,7 @@ int Abc_NtkReplaceAutonomousLogic( Abc_Ntk_t * pNtk ) Vec_PtrPush( vNodes, pFanin ); } } - Vec_PtrUniqify( vNodes, (int (*)(void))Abc_ObjPointerCompare ); + Vec_PtrUniqify( vNodes, (int (*)(const void *, const void *))Abc_ObjPointerCompare ); // replace these nodes by the PIs Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { diff --git a/src/base/abci/abcTiming.c b/src/base/abci/abcTiming.c index ae0e7f45..84cda931 100644 --- a/src/base/abci/abcTiming.c +++ b/src/base/abci/abcTiming.c @@ -24,9 +24,11 @@ #include "base/main/main.h" #include "map/mio/mio.h" + ABC_NAMESPACE_IMPL_START + //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// @@ -187,8 +189,9 @@ void Abc_NtkTimeSetDefaultRequired( Abc_Ntk_t * pNtk, float Rise, float Fall ) pNtk->pManTime->tReqDef.Rise = Rise; pNtk->pManTime->tReqDef.Fall = Fall; // set the required times for each output - Abc_NtkForEachCo( pNtk, pObj, i ) - Abc_NtkTimeSetRequired( pNtk, Abc_ObjId(pObj), Rise, Fall ); + Abc_NtkForEachCo( pNtk, pObj, i ){ + Abc_NtkTimeSetRequired( pNtk, Abc_ObjId(pObj), Rise, Fall ); + } } /**Function************************************************************* @@ -206,6 +209,7 @@ void Abc_NtkTimeSetArrival( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall { Vec_Ptr_t * vTimes; Abc_Time_t * pTime; + if ( pNtk->pManTime == NULL ) pNtk->pManTime = Abc_ManTimeStart(pNtk); Abc_ManTimeExpand( pNtk->pManTime, ObjId + 1, 1 ); @@ -214,6 +218,8 @@ void Abc_NtkTimeSetArrival( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall pTime = (Abc_Time_t *)vTimes->pArray[ObjId]; pTime->Rise = Rise; pTime->Fall = Fall; + + } void Abc_NtkTimeSetRequired( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ) { @@ -473,6 +479,7 @@ Abc_ManTime_t * Abc_ManTimeStart( Abc_Ntk_t * pNtk ) { int fUseZeroDefaultOutputRequired = 1; Abc_ManTime_t * p; + Abc_Time_t* pTime; Abc_Obj_t * pObj; int i; p = pNtk->pManTime = ABC_ALLOC( Abc_ManTime_t, 1 ); memset( p, 0, sizeof(Abc_ManTime_t) ); @@ -480,16 +487,49 @@ Abc_ManTime_t * Abc_ManTimeStart( Abc_Ntk_t * pNtk ) p->vReqs = Vec_PtrAlloc( 0 ); // set default default input=arrivals (assumed to be 0) // set default default output-requireds (can be either 0 or +infinity, based on the flag) - p->tReqDef.Rise = fUseZeroDefaultOutputRequired ? 0 : ABC_INFINITY; - p->tReqDef.Fall = fUseZeroDefaultOutputRequired ? 0 : ABC_INFINITY; + // extend manager Abc_ManTimeExpand( p, Abc_NtkObjNumMax(pNtk) + 1, 0 ); // set the default timing for CIs - Abc_NtkForEachCi( pNtk, pObj, i ) - Abc_NtkTimeSetArrival( pNtk, Abc_ObjId(pObj), p->tArrDef.Rise, p->tArrDef.Rise ); - // set the default timing for COs - Abc_NtkForEachCo( pNtk, pObj, i ) - Abc_NtkTimeSetRequired( pNtk, Abc_ObjId(pObj), p->tReqDef.Rise, p->tReqDef.Rise ); + Abc_NtkForEachCi( pNtk, pObj, i ){ + + //get the constrained value, if there is one + Vec_Ptr_t * vTimes; + vTimes = pNtk->pManTime->vArrs; + pTime = (Abc_Time_t *)vTimes->pArray[Abc_ObjId(pObj)]; + //unconstrained arrival defaults. Note that + //unconstrained value in vTimes set to -ABC_INFINITY. + if (pTime && + (!(p-> tArrDef.Fall == -ABC_INFINITY || + p-> tArrDef.Rise != -ABC_INFINITY )) + ){ + p->tArrDef.Fall = pTime -> Fall; + p->tArrDef.Rise = pTime -> Rise; + } + else { + //use the default arrival time 0 (implicit in memset 0, above). + p->tArrDef.Rise = 0; + p->tArrDef.Fall = 0; + } + Abc_NtkTimeSetArrival( pNtk, Abc_ObjId(pObj), p->tArrDef.Rise, p->tArrDef.Rise ); + } + + + Abc_NtkForEachCo( pNtk, pObj, i ){ + Vec_Ptr_t * vTimes; + vTimes = pNtk->pManTime->vArrs; + pTime = (Abc_Time_t *)vTimes->pArray[Abc_ObjId(pObj)]; + if (pTime){ + p->tReqDef.Fall = pTime -> Fall; + p->tReqDef.Rise = pTime -> Rise; + } + else{ + //use the default + p->tReqDef.Rise = fUseZeroDefaultOutputRequired ? 0 : ABC_INFINITY; + p->tReqDef.Fall = fUseZeroDefaultOutputRequired ? 0 : ABC_INFINITY; + } + Abc_NtkTimeSetRequired( pNtk, Abc_ObjId(pObj), p->tReqDef.Rise, p->tReqDef.Rise ); + } return p; } @@ -571,6 +611,8 @@ void Abc_ManTimeDup( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ) pNtkNew->pManTime->tOutLoad = ABC_ALLOC( Abc_Time_t, Abc_NtkCiNum(pNtkOld) ); memcpy( pNtkNew->pManTime->tOutLoad, pNtkOld->pManTime->tOutLoad, sizeof(Abc_Time_t) * Abc_NtkCoNum(pNtkOld) ); } + + } /**Function************************************************************* diff --git a/src/base/abci/abcUnreach.c b/src/base/abci/abcUnreach.c index ae4bc84b..5a20e5d8 100644 --- a/src/base/abci/abcUnreach.c +++ b/src/base/abci/abcUnreach.c @@ -342,7 +342,7 @@ Abc_Ntk_t * Abc_NtkConstructExdc( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUn Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); // transform the network to the SOP representation - if ( !Abc_NtkBddToSop( pNtkNew, -1, ABC_INFINITY ) ) + if ( !Abc_NtkBddToSop( pNtkNew, -1, ABC_INFINITY, 1 ) ) { printf( "Abc_NtkConstructExdc(): Converting to SOPs has failed.\n" ); return NULL; diff --git a/src/base/abci/abcVerify.c b/src/base/abci/abcVerify.c index 7199c529..f3e86746 100644 --- a/src/base/abci/abcVerify.c +++ b/src/base/abci/abcVerify.c @@ -781,6 +781,8 @@ void Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pMode Abc_NtkForEachCi( pNtk1, pNode, i ) pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)i; // print the model + if ( Vec_PtrSize(vNodes) ) + { pNode = (Abc_Obj_t *)Vec_PtrEntry( vNodes, 0 ); if ( Abc_ObjIsCi(pNode) ) { @@ -790,6 +792,7 @@ void Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pMode printf( " %s=%d", Abc_ObjName(pNode), pModel[(int)(ABC_PTRINT_T)pNode->pCopy] ); } } + } printf( "\n" ); Vec_PtrFree( vNodes ); } diff --git a/src/base/acb/acb.h b/src/base/acb/acb.h index 9aed414c..0a188d0f 100644 --- a/src/base/acb/acb.h +++ b/src/base/acb/acb.h @@ -1019,6 +1019,12 @@ static inline void Acb_ManPrintStats( Acb_Man_t * p, int nModules, int fVerbose extern Vec_Int_t * Acb_ObjCollectTfi( Acb_Ntk_t * p, int iObj, int fTerm ); extern Vec_Int_t * Acb_ObjCollectTfo( Acb_Ntk_t * p, int iObj, int fTerm ); +extern Vec_Int_t * Acb_ObjCollectTfiVec( Acb_Ntk_t * p, Vec_Int_t * vObjs ); +extern Vec_Int_t * Acb_ObjCollectTfoVec( Acb_Ntk_t * p, Vec_Int_t * vObjs ); +extern int Acb_NtkCountPiBuffers( Acb_Ntk_t * p, Vec_Int_t * vObjs ); +extern int Acb_NtkCountPoDrivers( Acb_Ntk_t * p, Vec_Int_t * vObjs ); +extern int Acb_NtkFindMffcSize( Acb_Ntk_t * p, Vec_Int_t * vObjsRefed, Vec_Int_t * vObjsDerefed, int nGates[5] ); + extern int Acb_ObjComputeLevelD( Acb_Ntk_t * p, int iObj ); extern int Acb_NtkComputeLevelD( Acb_Ntk_t * p, Vec_Int_t * vTfo ); extern void Acb_NtkUpdateLevelD( Acb_Ntk_t * p, int iObj ); diff --git a/src/base/acb/acbFunc.c b/src/base/acb/acbFunc.c index 8f72a00f..3c0bb5f0 100644 --- a/src/base/acb/acbFunc.c +++ b/src/base/acb/acbFunc.c @@ -35,8 +35,6 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -#define ACB_LAST_NAME_ID 14 - typedef enum { ACB_NONE = 0, // 0: unused ACB_MODULE, // 1: "module" @@ -52,6 +50,8 @@ typedef enum { ACB_NOR, // 11: "nor" ACB_XOR, // 12: "xor" ACB_XNOR, // 13: "xnor" + ACB_MUX, // 14: "_HMUX" + ACB_DC, // 15: "_DC" ACB_UNUSED // 14: unused } Acb_KeyWords_t; @@ -70,6 +70,8 @@ static inline char * Acb_Num2Name( int i ) if ( i == 11 ) return "nor"; if ( i == 12 ) return "xor"; if ( i == 13 ) return "xnor"; + if ( i == 14 ) return "_HMUX"; + if ( i == 15 ) return "_DC"; return NULL; } @@ -83,6 +85,8 @@ static inline int Acb_Type2Oper( int i ) if ( i == 11 ) return ABC_OPER_BIT_NOR; if ( i == 12 ) return ABC_OPER_BIT_XOR; if ( i == 13 ) return ABC_OPER_BIT_NXOR; + if ( i == 14 ) return ABC_OPER_BIT_MUX; + if ( i == 15 ) return ABC_OPER_TRI; assert( 0 ); return -1; } @@ -91,6 +95,7 @@ static inline char * Acb_Oper2Name( int i ) { if ( i == ABC_OPER_CONST_F ) return "const0"; if ( i == ABC_OPER_CONST_T ) return "const1"; + if ( i == ABC_OPER_CONST_X ) return "constX"; if ( i == ABC_OPER_BIT_BUF ) return "buf"; if ( i == ABC_OPER_BIT_INV ) return "not"; if ( i == ABC_OPER_BIT_AND ) return "and"; @@ -99,6 +104,8 @@ static inline char * Acb_Oper2Name( int i ) if ( i == ABC_OPER_BIT_NOR ) return "nor"; if ( i == ABC_OPER_BIT_XOR ) return "xor"; if ( i == ABC_OPER_BIT_NXOR ) return "xnor"; + if ( i == ABC_OPER_BIT_MUX ) return "mux"; + if ( i == ABC_OPER_TRI ) return "_DC"; assert( 0 ); return NULL; } @@ -138,15 +145,28 @@ char * pLibStr[25] = { "GATE zero 0 O=CONST0;\n" "GATE one 0 O=CONST1;\n" }; -void Acb_IntallLibrary() +char * pLibStr2[25] = { + "GATE buf 1 O=a; PIN * INV 1 999 1.0 0.0 1.0 0.0\n" + "GATE inv 1 O=!a; PIN * INV 1 999 1.0 0.0 1.0 0.0\n" + "GATE and2 1 O=a*b; PIN * INV 1 999 1.0 0.0 1.0 0.0\n" + "GATE or2 1 O=a+b; PIN * INV 1 999 1.0 0.0 1.0 0.0\n" + "GATE nand2 1 O=!(a*b); PIN * INV 1 999 1.0 0.0 1.0 0.0\n" + "GATE nor2 1 O=!(a+b); PIN * INV 1 999 1.0 0.0 1.0 0.0\n" + "GATE xor 1 O=!a*b+a*!b; PIN * INV 1 999 1.0 0.0 1.0 0.0\n" + "GATE xnor 1 O=a*b+!a*!b; PIN * INV 1 999 1.0 0.0 1.0 0.0\n" + "GATE zero 0 O=CONST0;\n" + "GATE one 0 O=CONST1;\n" +}; +void Acb_IntallLibrary( int f2Ins ) { extern Mio_Library_t * Mio_LibraryReadBuffer( char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int fVerbose ); Mio_Library_t * pLib; int i; // create library string Vec_Str_t * vLibStr = Vec_StrAlloc( 1000 ); - for ( i = 0; pLibStr[i]; i++ ) - Vec_StrAppend( vLibStr, pLibStr[i] ); + char ** ppLibStr = f2Ins ? pLibStr2 : pLibStr; + for ( i = 0; ppLibStr[i]; i++ ) + Vec_StrAppend( vLibStr, ppLibStr[i] ); Vec_StrPush( vLibStr, '\0' ); // create library pLib = Mio_LibraryReadBuffer( Vec_StrArray(vLibStr), 0, NULL, 0 ); @@ -190,17 +210,78 @@ Vec_Int_t * Acb_VerilogSimpleLex( char * pFileName, Abc_Nam_t * pNames ) Vec_Int_t * vBuffer = Vec_IntAlloc( 1000 ); char * pBuffer = Extra_FileReadContents( pFileName ); char * pToken, * pStart, * pLimit = pBuffer + strlen(pBuffer); + int i, iToken, RLeft = -1, RRight = -1; if ( pBuffer == NULL ) return NULL; Acb_VerilogRemoveComments( pBuffer ); pToken = strtok( pBuffer, " \n\r\t(),;=" ); while ( pToken ) { - int iToken = Abc_NamStrFindOrAdd( pNames, pToken, NULL ); + if ( 0 ) + { + if ( !strcmp(pToken, "assign") ) + { + int fBuffer = 0; + int nToks = 0, pToks[4]; + while ( 1 ) + { + pToken = strtok( NULL, " \n\r\t(),=~&" ); + if ( pToken[0] == ';' ) + break; + if ( pToken[strlen(pToken)-1] == ';' ) + { + pToken[strlen(pToken)-1] = 0; + assert( nToks < 3 ); + pToks[nToks++] = Abc_NamStrFindOrAdd( pNames, pToken, NULL ); + fBuffer = 1; + break; + } + else + { + assert( nToks < 3 ); + pToks[nToks++] = Abc_NamStrFindOrAdd( pNames, pToken, NULL ); + } + } + assert( nToks == 2 || nToks == 3 ); + Vec_IntPush( vBuffer, fBuffer ? ACB_AND : ACB_NAND ); + Vec_IntPush( vBuffer, pToks[0] ); + Vec_IntPush( vBuffer, pToks[1] ); + Vec_IntPush( vBuffer, nToks == 3 ? pToks[2] : pToks[1] ); + pToken = strtok( NULL, " \n\r\t(),;=" ); + continue; + } + } + + if ( pToken[0] == '[' ) + { + assert( RLeft == -1 ); + RLeft = atoi(pToken+1); + RRight = atoi(strstr(pToken,":")+1); + pToken = strtok( NULL, " \n\r\t(),;=" ); + continue; + } + if ( pToken[0] == '\\' ) + pToken++; if ( !strcmp(pToken, "assign") ) - Vec_IntPush( vBuffer, ACB_BUF ); + iToken = ACB_BUF; else - Vec_IntPush( vBuffer, iToken ); + iToken = Abc_NamStrFindOrAdd( pNames, pToken, NULL ); + if ( iToken < ACB_UNUSED ) + RLeft = RRight = -1; + else if ( RLeft != -1 ) + { + char Buffer[1000]; + assert( strlen(pToken) < 990 ); + for ( i = RRight; i <= RLeft; i++ ) + { + sprintf( Buffer, "%s[%d]", pToken, i ); + iToken = Abc_NamStrFindOrAdd( pNames, Buffer, NULL ); + Vec_IntPush( vBuffer, iToken ); + } + pToken = strtok( NULL, " \n\r\t(),;=" ); + continue; + } + Vec_IntPush( vBuffer, iToken ); if ( iToken >= ACB_BUF && iToken < ACB_UNUSED ) { for ( pStart = pToken; pStart < pLimit && *pStart != '\n'; pStart++ ) @@ -245,14 +326,11 @@ void * Acb_VerilogSimpleParse( Vec_Int_t * vBuffer, Abc_Nam_t * pNames ) vCur = vOutputs; else if ( Token == ACB_WIRE ) vCur = vWires; - else if ( Token >= ACB_BUF && Token <= ACB_XNOR ) + else if ( Token >= ACB_BUF && Token < ACB_UNUSED ) { - //char * pToken = Abc_NamStr(pNames, Vec_IntEntry(vBuffer, i+1)); Vec_IntPush( vTypes, Token ); Vec_IntPush( vTypes, Vec_IntSize(vFanins) ); vCur = vFanins; - //if ( pToken[1] == 'z' && pToken[2] == '_' && pToken[3] == 'g' && pToken[4] == '_' ) - // i++; } else Vec_IntPush( vCur, Token ); @@ -288,6 +366,8 @@ void * Acb_VerilogSimpleParse( Vec_Int_t * vBuffer, Abc_Nam_t * pNames ) Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CONST_F, 0, 0, 0, 0, 0, NULL, 1, &Token, NULL ); // no fanins if ( (Token = Abc_NamStrFind(pNames, "1\'b1")) ) Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CONST_T, 0, 0, 0, 0, 0, NULL, 1, &Token, NULL ); // no fanins + if ( (Token = Abc_NamStrFind(pNames, "1\'bx")) ) + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CONST_X, 0, 0, 0, 0, 0, NULL, 1, &Token, NULL ); // no fanins Vec_IntForEachEntryDouble( vTypes, Token, Size, i ) if ( Token > 0 ) { @@ -309,6 +389,182 @@ void * Acb_VerilogSimpleParse( Vec_Int_t * vBuffer, Abc_Nam_t * pNames ) /**Function************************************************************* + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_FileSimpleParse_rec( Gia_Man_t * pNew, int Token, Vec_Int_t * vMapType, Vec_Int_t * vTypes, Vec_Int_t * vFanins, Vec_Int_t * vMap ) +{ + int nFanins, * pFanins, pLits[16]; + int i, Type, Size, Place = Vec_IntEntry( vMapType, Token ); + int iLit = Vec_IntEntry( vMap, Token ); + if ( iLit >= 0 ) + return iLit; + Place = Vec_IntEntry( vMapType, Token ); + assert( Place >= 0 ); + Type = Vec_IntEntry( vTypes, Place ); + Size = Vec_IntEntry( vTypes, Place+1 ); + nFanins = Vec_IntEntry(vTypes, Place+3) - Size - 1; + pFanins = Vec_IntEntryP(vFanins, Size+1); + assert( nFanins > 0 && nFanins < 16 ); + for ( i = 0; i < nFanins; i++ ) + Gia_FileSimpleParse_rec( pNew, pFanins[i], vMapType, vTypes, vFanins, vMap ); + for ( i = 0; i < nFanins; i++ ) + pLits[i] = Vec_IntEntry( vMap, pFanins[i] ); + if ( nFanins == 1 ) + { + assert( Type == ACB_BUF || Type == ACB_NOT ); + iLit = Abc_LitNotCond( pLits[0], Type == ACB_NOT ); + iLit = Gia_ManAppendAnd2( pNew, iLit, iLit ); + } + else + { + iLit = pLits[0]; + if ( Type == ACB_AND || Type == ACB_NAND ) + for ( i = 1; i < nFanins; i++ ) + iLit = Gia_ManAppendAnd2( pNew, iLit, pLits[i] ); + else if ( Type == ACB_OR || Type == ACB_NOR ) + for ( i = 1; i < nFanins; i++ ) + iLit = Gia_ManAppendOr2( pNew, iLit, pLits[i] ); + else if ( Type == ACB_XOR || Type == ACB_XNOR ) + for ( i = 1; i < nFanins; i++ ) + iLit = Gia_ManAppendXor2( pNew, iLit, pLits[i] ); + else assert( 0 ); + iLit = Abc_LitNotCond( iLit, (Type == ACB_NAND || Type == ACB_NOR || Type == ACB_XNOR) ); + } + Vec_IntWriteEntry( vMap, Token, iLit ); + return iLit; +} +Gia_Man_t * Gia_FileSimpleParse( Vec_Int_t * vBuffer, Abc_Nam_t * pNames, int fNames, char * pFileW ) +{ + Gia_Man_t * pNew = NULL; + Vec_Int_t * vInputs = Vec_IntAlloc(100); + Vec_Int_t * vOutputs = Vec_IntAlloc(100); + Vec_Int_t * vWires = Vec_IntAlloc(100); + Vec_Int_t * vTypes = Vec_IntAlloc(100); + Vec_Int_t * vFanins = Vec_IntAlloc(100); + Vec_Int_t * vCur = NULL; + Vec_Int_t * vMap = Vec_IntStartFull( Abc_NamObjNumMax(pNames) ); + Vec_Int_t * vMapType = Vec_IntStartFull( Abc_NamObjNumMax(pNames) ); + int i, iLit, Token, Size; + char Buffer[1000]; + assert( Vec_IntEntry(vBuffer, 0) == ACB_MODULE ); + Vec_IntForEachEntryStart( vBuffer, Token, i, 2 ) + { + if ( vCur == NULL && Token >= ACB_UNUSED ) + continue; + if ( Token == ACB_ENDMODULE ) + break; + if ( Token == ACB_INPUT ) + vCur = vInputs; + else if ( Token == ACB_OUTPUT ) + vCur = vOutputs; + else if ( Token == ACB_WIRE ) + vCur = vWires; + else if ( Token >= ACB_BUF && Token < ACB_UNUSED ) + { + Vec_IntPush( vTypes, Token ); + Vec_IntPush( vTypes, Vec_IntSize(vFanins) ); + vCur = vFanins; + } + else if ( pFileW && vCur == vWires && Abc_NamStr(pNames, Token)[0] == 't' ) + Vec_IntPush( vInputs, Token ); + else + Vec_IntPush( vCur, Token ); + } + Vec_IntPush( vTypes, -1 ); + Vec_IntPush( vTypes, Vec_IntSize(vFanins) ); + // map types + Vec_IntForEachEntryDouble( vTypes, Token, Size, i ) + if ( Token > 0 ) + Vec_IntWriteEntry( vMapType, Vec_IntEntry(vFanins, Size), i ); + // create design + pNew = Gia_ManStart( 10000 ); + pNew->pName = Abc_UtilStrsav( Abc_NamStr(pNames, Vec_IntEntry(vBuffer, 1)) ); + pNew->fGiaSimple = 1; + if ( (Token = Abc_NamStrFind(pNames, "1\'b0")) ) + Vec_IntWriteEntry( vMap, Token, 0 ); + if ( (Token = Abc_NamStrFind(pNames, "1\'b1")) ) + Vec_IntWriteEntry( vMap, Token, 1 ); + if ( (Token = Abc_NamStrFind(pNames, "1\'bx")) ) + Vec_IntWriteEntry( vMap, Token, 0 ); + if ( (Token = Abc_NamStrFind(pNames, "1\'bz")) ) + Vec_IntWriteEntry( vMap, Token, 0 ); + Vec_IntForEachEntry( vInputs, Token, i ) + Gia_ManAppendCi(pNew); + Vec_IntForEachEntry( vInputs, Token, i ) + Vec_IntWriteEntry( vMap, Token, Gia_ManAppendAnd2(pNew, Gia_ManCiLit(pNew, i), Gia_ManCiLit(pNew, i)) ); + Vec_IntForEachEntry( vOutputs, Token, i ) + Gia_FileSimpleParse_rec( pNew, Token, vMapType, vTypes, vFanins, vMap ); + Vec_IntForEachEntry( vOutputs, Token, i ) + Gia_ManAppendCo( pNew, Vec_IntEntry(vMap, Token) ); + // create names + if ( fNames ) + { + pNew->vPolars = Vec_BitStart( Gia_ManObjNum(pNew) ); + pNew->vNamesNode = Vec_PtrStart( Gia_ManObjNum(pNew) ); + Vec_IntForEachEntry( vMap, iLit, Token ) + { + if ( iLit == -1 || !Gia_ObjIsAnd(Gia_ManObj(pNew, Abc_Lit2Var(iLit))) ) + continue; + sprintf( Buffer, "%c_%s", Abc_LitIsCompl(iLit) ? 'c' : 'd', Abc_NamStr(pNames, Token) ); + assert( Vec_PtrEntry(pNew->vNamesNode, Abc_Lit2Var(iLit)) == NULL ); + Vec_PtrWriteEntry( pNew->vNamesNode, Abc_Lit2Var(iLit), Abc_UtilStrsav(Buffer) ); + Vec_BitWriteEntry( pNew->vPolars, Abc_Lit2Var(iLit), Abc_LitIsCompl(iLit) ); + } + } + else + { + Gia_Man_t * pTemp; + pNew = Gia_ManDupDfsRehash( pTemp = pNew ); + Gia_ManStop( pTemp ); + } + pNew->vNamesIn = Vec_PtrAlloc( Vec_IntSize(vInputs) ); + Vec_IntForEachEntry( vInputs, Token, i ) + Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Abc_NamStr(pNames, Token)) ); + pNew->vNamesOut = Vec_PtrAlloc( Vec_IntSize(vOutputs) ); + Vec_IntForEachEntry( vOutputs, Token, i ) + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Abc_NamStr(pNames, Token)) ); + if ( pFileW && fNames ) + { + extern Vec_Int_t * Acb_ReadWeightMap( char * pFileName, Abc_Nam_t * pNames ); + Vec_Int_t * vT2W = Acb_ReadWeightMap( pFileW, pNames ); + assert( pNew->vWeights == NULL ); + pNew->vWeights = Vec_IntStartFull( Gia_ManObjNum(pNew) ); + Vec_IntForEachEntry( vMap, iLit, Token ) + if ( iLit != -1 && Vec_IntEntry(vT2W, Token) != -1 ) + Vec_IntWriteEntry( pNew->vWeights, Abc_Lit2Var(iLit), Vec_IntEntry(vT2W, Token) ); + Vec_IntFree( vT2W ); + } + // cleanup + Vec_IntFree( vInputs ); + Vec_IntFree( vOutputs ); + Vec_IntFree( vWires ); + Vec_IntFree( vTypes ); + Vec_IntFree( vFanins ); + Vec_IntFree( vMap ); + Vec_IntFree( vMapType ); + return pNew; +} +Gia_Man_t * Gia_FileSimpleRead( char * pFileName, int fNames, char * pFileW ) +{ + Abc_Nam_t * pNames = Acb_VerilogStartNames(); + Vec_Int_t * vBuffer = Acb_VerilogSimpleLex( pFileName, pNames ); + Gia_Man_t * pNew = vBuffer ? Gia_FileSimpleParse( vBuffer, pNames, fNames, pFileW ) : NULL; + assert( pNew->pSpec == NULL ); + pNew->pSpec = Abc_UtilStrsav( pFileName ); + Abc_NamDeref( pNames ); + Vec_IntFree( vBuffer ); + return pNew; +} + +/**Function************************************************************* + Synopsis [Read weights of nodes from the weight file.] Description [] @@ -355,10 +611,18 @@ Vec_Int_t * Acb_ReadWeightMap( char * pFileName, Abc_Nam_t * pNames ) SeeAlso [] ***********************************************************************/ +char ** Acb_PrepareNames( Abc_Nam_t * p ) +{ + char ** ppRes = ABC_CALLOC( char *, Abc_NamObjNumMax(p) ); + int i; + for ( i = 0; i < Abc_NamObjNumMax(p); i++ ) + ppRes[i] = Abc_NamStr( p, i ); + return ppRes; +} Acb_Ntk_t * Acb_VerilogSimpleRead( char * pFileName, char * pFileNameW ) { extern Acb_Ntk_t * Acb_NtkFromNdr( char * pFileName, void * pModule, Abc_Nam_t * pNames, Vec_Int_t * vWeights, int nNameIdMax ); - Acb_Ntk_t * pNtk; + Acb_Ntk_t * pNtk; Abc_Nam_t * pNames = Acb_VerilogStartNames(); Vec_Int_t * vBuffer = Acb_VerilogSimpleLex( pFileName, pNames ); void * pModule = vBuffer ? Acb_VerilogSimpleParse( vBuffer, pNames ) : NULL; @@ -373,7 +637,12 @@ Acb_Ntk_t * Acb_VerilogSimpleRead( char * pFileName, char * pFileNameW ) printf( "Cannot read weight file \"%s\".\n", pFileNameW ); return NULL; } -// Ndr_ModuleWriteVerilog( "iccad17/unit1/test.v", pModule, pNameStrs ); + if ( 0 ) + { + char ** ppNames = Acb_PrepareNames(pNames); + Ndr_WriteVerilog( Extra_FileNameGenericAppend(pFileName, "_ndr.v"), pModule, ppNames, 1 ); + ABC_FREE( ppNames ); + } pNtk = Acb_NtkFromNdr( pFileName, pModule, pNames, vWeights, Abc_NamObjNumMax(pNames) ); Ndr_Delete( pModule ); Vec_IntFree( vBuffer ); @@ -381,6 +650,11 @@ Acb_Ntk_t * Acb_VerilogSimpleRead( char * pFileName, char * pFileNameW ) Abc_NamDeref( pNames ); return pNtk; } +void Acb_VerilogSimpleReadTest( char * pFileName ) +{ + Acb_Ntk_t * p = Acb_VerilogSimpleRead( pFileName, NULL ); + Acb_NtkFree( p ); +} /**Function************************************************************* @@ -440,7 +714,10 @@ void Acb_VerilogSimpleWrite( Acb_Ntk_t * p, char * pFileName ) { assert( Acb_ObjType(p, iObj) == ABC_OPER_CONST_F || Acb_ObjType(p, iObj) == ABC_OPER_CONST_T ); fprintf( pFile, " %s (", Acb_Oper2Name( ABC_OPER_BIT_BUF ) ); - fprintf( pFile, " 1\'b%d", Acb_ObjType(p, iObj) == ABC_OPER_CONST_T ); + if ( Acb_ObjType(p, iObj) == ABC_OPER_CONST_X ) + fprintf( pFile, " 1\'bx" ); + else + fprintf( pFile, " 1\'b%d", Acb_ObjType(p, iObj) == ABC_OPER_CONST_T ); fprintf( pFile, " );\n" ); } @@ -579,12 +856,18 @@ Vec_Int_t * Acb_NtkFindDivsCis( Acb_Ntk_t * p, Vec_Int_t * vSupp ) printf( "Divisors are %d support variables (CIs in the TFO of the targets).\n", Vec_IntSize(vSupp) ); return vDivs; } -Vec_Int_t * Acb_NtkFindDivs( Acb_Ntk_t * p, Vec_Int_t * vSupp, Vec_Bit_t * vBlock, int fVerbose ) +Vec_Int_t * Acb_NtkFindDivs( Acb_Ntk_t * p, Vec_Int_t * vSupp, Vec_Bit_t * vBlock, int fUnitW, int fVerbose ) { int fPrintWeights = 0; int nDivLimit = 5000; int i, iObj; Vec_Int_t * vDivs = Vec_IntAlloc( 1000 ); + if ( fUnitW ) + { + Acb_NtkForEachNode( p, iObj ) + if ( Acb_ObjWeight(p, iObj) > 0 ) + Vec_IntWriteEntry( &p->vObjWeight, iObj, 1 ); + } // mark inputs Acb_NtkIncTravId( p ); Acb_NtkForEachCiVec( vSupp, p, iObj, i ) @@ -754,6 +1037,31 @@ Gia_Man_t * Acb_NtkToGia( Acb_Ntk_t * p, Vec_Int_t * vSupp, Vec_Int_t * vNodes, Gia_ManStop( pOne ); return pNew; } +int Acb_NtkSaveNames( Acb_Ntk_t * p, Vec_Int_t * vSupp, Vec_Int_t * vNodes, Vec_Int_t * vRoots, Vec_Int_t * vDivs, Vec_Int_t * vTargets, Gia_Man_t * pNew ) +{ + int i, iObj; + assert( pNew->vNamesIn == NULL ); + + pNew->vNamesIn = Vec_PtrAlloc( Gia_ManCiNum(pNew) ); + Acb_NtkForEachCiVec( vSupp, p, iObj, i ) + Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Acb_ObjNameStr(p, iObj)) ); + if ( vTargets ) + Vec_IntForEachEntry( vTargets, iObj, i ) + Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Acb_ObjNameStr(p, iObj)) ); + + pNew->vNamesOut = Vec_PtrAlloc( Gia_ManCoNum(pNew) ); + Acb_NtkForEachCoDriverVec( vRoots, p, iObj, i ) + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Acb_ObjNameStr(p, iObj)) ); + if ( vDivs ) + Vec_IntForEachEntry( vDivs, iObj, i ) + { + char Buffer[100]; + assert( strlen(Acb_ObjNameStr(p, iObj)) < 90 ); + sprintf( Buffer, "%s_%d", Acb_ObjNameStr(p, iObj), Acb_ObjWeight(p, iObj) ); + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); + } + return 1; +} /**Function************************************************************* @@ -825,6 +1133,21 @@ void Vec_IntPermute( Vec_Int_t * p ) } } +void Vec_IntPermute2( Vec_Int_t * p ) +{ + int i, nSize = Vec_IntSize( p ); + int * pArray = Vec_IntArray( p ); + srand( time(NULL) ); + for ( i = 0; i < nSize-1; i++ ) + { + if ( rand() % 3 == 0 ) + { + printf( "Permuting %d and %d\n", i, i+1 ); + ABC_SWAP( int, pArray[i], pArray[i+1] ); + } + } +} + void Acb_PrintPatterns( Vec_Wrd_t * vPats, int nPats, Vec_Int_t * vWeights ) { int i, k, Entry, nDivs = Vec_IntSize(vWeights); @@ -1541,7 +1864,7 @@ char * Acb_EnumerateSatAssigns( sat_solver * pSat, int PivotVar, int FreeVar, Ve { if ( iMint == 1000 ) { - //if ( Vec_IntSize(vDivVars) == 0 ) + if ( Vec_IntSize(vDivVars) == 0 ) { printf( "Assuming constant 0 function.\n" ); Vec_StrClear( vTempSop ); @@ -1897,34 +2220,66 @@ Vec_Ptr_t * Acb_GenerateSignalNames( Acb_Ntk_t * p, Vec_Int_t * vDivs, Vec_Int_t Vec_StrFree( vStr ); return vRes; } +Vec_Int_t * Acb_GetUsedDivs( Vec_Int_t * vDivs, Vec_Int_t * vUsed ) +{ + int i, iObj; + Vec_Int_t * vRes = Vec_IntAlloc( Vec_IntSize(vUsed) ); + Vec_IntForEachEntryInVec( vDivs, vUsed, iObj, i ) + Vec_IntPush( vRes, iObj ); + return vRes; +} +Vec_Ptr_t * Acb_SignalNames( Acb_Ntk_t * p, Vec_Int_t * vObjs ) +{ + Vec_Ptr_t * vNames = Vec_PtrAlloc( Vec_IntSize(vObjs) ); + int i, iObj; + Vec_IntForEachEntry( vObjs, iObj, i ) + Vec_PtrPush( vNames, Acb_ObjNameStr(p, iObj) ); + return vNames; +} Vec_Str_t * Acb_GeneratePatch( Acb_Ntk_t * p, Vec_Int_t * vDivs, Vec_Int_t * vUsed, Vec_Ptr_t * vSops, Vec_Ptr_t * vGias, Vec_Int_t * vTars ) { + extern int Acb_NtkCollectMfsGates( char * pFileName, Vec_Ptr_t * vNamesRefed, Vec_Ptr_t * vNamesDerefed, int nGates1[5] ); extern Vec_Wec_t * Abc_SopSynthesize( Vec_Ptr_t * vSops ); extern Vec_Wec_t * Abc_GiaSynthesize( Vec_Ptr_t * vGias, Gia_Man_t * pMulti ); Vec_Wec_t * vGates = vGias ? Abc_GiaSynthesize(vGias, NULL) : Abc_SopSynthesize(vSops); Vec_Int_t * vGate; int nOuts = vGias ? Vec_PtrSize(vGias) : Vec_PtrSize(vSops); int i, k, iObj, nWires = Vec_WecSize(vGates) - Vec_IntSize(vUsed) - nOuts, fFirst = 1; + int nGates1[5] = {0}, nGates0[5] = {0}; Vec_Ptr_t * vNames = Acb_GenerateSignalNames( p, vDivs, vUsed, nWires, vTars, vGates ); Vec_Str_t * vStr = Vec_StrAlloc( 100 ); - - int nInvs = 0, nBufs = 0, nNodes = 0, nConst = 0; + Vec_Int_t * vSup = Acb_GetUsedDivs( vDivs, vUsed ); + Vec_Ptr_t * vSpN = Acb_SignalNames( p, vSup ); + Vec_Int_t * vTfi = Acb_ObjCollectTfiVec( p, vSup ); + Vec_Int_t * vTfo = Acb_ObjCollectTfoVec( p, vTars ); + int nPiCount = Acb_NtkCountPiBuffers( p, vSup ); + int nPoCount = Acb_NtkCountPoDrivers( p, vTars ); + int nMffc = Abc_FrameReadSpecName() ? Acb_NtkCollectMfsGates( Abc_FrameReadSpecName(), vSpN, Abc_FrameReadSignalNames(), nGates1 ) : 0; + Vec_PtrFree( vSpN ); + Vec_IntFree( vSup ); Vec_WecForEachLevelStartStop( vGates, vGate, i, Vec_IntSize(vUsed), Vec_IntSize(vUsed)+nWires ) { if ( Vec_IntSize(vGate) > 2 ) { char * pName = Acb_Oper2Name(Vec_IntEntry(vGate, 0)); if ( !strcmp(pName, "buf") ) - nBufs++; + nGates0[2]++; else if ( !strcmp(pName, "not") ) - nInvs++; + nGates0[3]++; else - nNodes++; + nGates0[4] += Vec_IntSize(vGate) - 3; } else - nConst++; + nGates0[Vec_IntEntry(vGate, 0) == ABC_OPER_CONST_T]++; } - Vec_StrPrintF( vStr, "// Patch statistics: in = %d out = %d gate = %d (const = %d buf = %d inv = %d other = %d)\n\n", - Vec_IntSize(vUsed), nOuts, nWires, nConst, nBufs, nInvs, nNodes ); + + Vec_StrPrintF( vStr, "// Patch : in = %d out = %d : pi_in = %d po_out = %d : tfi = %d tfo = %d\n", Vec_IntSize(vUsed), nOuts, nPiCount, nPoCount, Vec_IntSize(vTfi), Vec_IntSize(vTfo) ); + Vec_StrPrintF( vStr, "// Added : gate =%4d : c0 =%2d c1 =%2d buf =%3d inv =%3d two-input =%4d\n", nWires, nGates0[0], nGates0[1], nGates0[2], nGates0[3], nGates0[4] ); + if ( Abc_FrameReadSpecName() ) + Vec_StrPrintF( vStr, "// Removed : gate =%4d : c0 =%2d c1 =%2d buf =%3d inv =%3d two-input =%4d\n", nMffc, nGates1[0], nGates1[1], nGates1[2], nGates1[3], nGates1[4] ); + if ( Abc_FrameReadSpecName() ) + Vec_StrPrintF( vStr, "// TOTAL : gate =%4d : c0 =%2d c1 =%2d buf =%3d inv =%3d two-input =%4d\n", nWires-nMffc, nGates0[0]-nGates1[0], nGates0[1]-nGates1[1], nGates0[2]-nGates1[2], nGates0[3]-nGates1[3], nGates0[4]-nGates1[4] ); + Vec_StrPrintF( vStr, "\n" ); + Vec_StrAppend( vStr, "module patch (" ); assert( Vec_IntSize(vTars) == nOuts ); @@ -1980,8 +2335,17 @@ Vec_Str_t * Acb_GeneratePatch( Acb_Ntk_t * p, Vec_Int_t * vDivs, Vec_Int_t * vUs Vec_PtrFreeFree( vNames ); Vec_WecFree( vGates ); - printf( "Synthesized patch with %d inputs, %d outputs and %d gates (const = %d buf = %d inv = %d other = %d).\n", - Vec_IntSize(vUsed), nOuts, nWires, nConst, nBufs, nInvs, nNodes ); +// printf( "Synthesized patch with %d inputs, %d outputs and %d gates (const = %d buf = %d inv = %d other = %d).\n", +// Vec_IntSize(vUsed), nOuts, nWires, nConst, nBufs, nInvs, nNodes ); +// printf( "Summary of the results\n" ); + printf( "\n" ); + printf( "Patch : in = %d out = %d : pi_in = %d po_out = %d : tfi = %d tfo = %d\n", Vec_IntSize(vUsed), nOuts, nPiCount, nPoCount, Vec_IntSize(vTfi), Vec_IntSize(vTfo) ); + printf( "Added : gate =%4d : c0 =%2d c1 =%2d buf =%3d inv =%3d two-input =%4d\n", nWires, nGates0[0], nGates0[1], nGates0[2], nGates0[3], nGates0[4] ); + if ( Abc_FrameReadSpecName() ) + printf( "Removed : gate =%4d : c0 =%2d c1 =%2d buf =%3d inv =%3d two-input =%4d\n", nMffc, nGates1[0], nGates1[1], nGates1[2], nGates1[3], nGates1[4] ); + if ( Abc_FrameReadSpecName() ) + printf( "TOTAL : gate =%4d : c0 =%2d c1 =%2d buf =%3d inv =%3d two-input =%4d\n", nWires-nMffc, nGates0[0]-nGates1[0], nGates0[1]-nGates1[1], nGates0[2]-nGates1[2], nGates0[3]-nGates1[3], nGates0[4]-nGates1[4] ); + printf( "\n" ); return vStr; } @@ -2040,7 +2404,7 @@ Vec_Str_t * Acb_GeneratePatch2( Gia_Man_t * pGia, Vec_Ptr_t * vIns, Vec_Ptr_t * extern Vec_Wec_t * Abc_GiaSynthesize( Vec_Ptr_t * vGias, Gia_Man_t * pMulti ); Vec_Wec_t * vGates = Abc_GiaSynthesize( NULL, pGia ); Vec_Int_t * vGate; int nIns = Vec_PtrSize(vIns), nOuts = Vec_PtrSize(vOuts); char * pName; - int i, k, iObj, nWires = Vec_WecSize(vGates) - nIns - nOuts, fFirst = 1; + int i, k, iObj, nWires = Vec_WecSize(vGates) - nIns - nOuts, nTwoIns = 0, fFirst = 1; Vec_Ptr_t * vNames = Acb_GenerateSignalNames2( vGates, vIns, vOuts ); Vec_Str_t * vStr = Vec_StrAlloc( 100 ); @@ -2049,7 +2413,7 @@ Vec_Str_t * Acb_GeneratePatch2( Gia_Man_t * pGia, Vec_Ptr_t * vIns, Vec_Ptr_t * Vec_PtrForEachEntry( char *, vOuts, pName, i ) Vec_StrPrintF( vStr, "%s %s", i ? ",":"", pName ); Vec_PtrForEachEntry( char *, vIns, pName, i ) - Vec_StrPrintF( vStr, ", %s", pName ); + Vec_StrPrintF( vStr, ", %s%s", i ? "":" ", pName ); Vec_StrAppend( vStr, " );\n\n" ); Vec_StrAppend( vStr, " output" ); @@ -2071,8 +2435,9 @@ Vec_Str_t * Acb_GeneratePatch2( Gia_Man_t * pGia, Vec_Ptr_t * vIns, Vec_Ptr_t * if ( !strncmp(pName, "ww", 2) ) Vec_StrPrintF( vStr, "%s %s", fFirst ? "":",", pName ), fFirst = 0; } - Vec_StrAppend( vStr, ";\n\n" ); + Vec_StrAppend( vStr, ";\n" ); } + Vec_StrAppend( vStr, "\n" ); // create internal nodes Vec_WecForEachLevelStartStop( vGates, vGate, i, nIns, nIns+nWires ) @@ -2083,6 +2448,7 @@ Vec_Str_t * Acb_GeneratePatch2( Gia_Man_t * pGia, Vec_Ptr_t * vIns, Vec_Ptr_t * Vec_IntForEachEntryStart( vGate, iObj, k, 1 ) Vec_StrPrintF( vStr, "%s %s", k > 1 ? ",":"", (char *)Vec_PtrEntry(vNames, iObj) ); Vec_StrAppend( vStr, " );\n" ); + nTwoIns += Vec_IntSize(vGate) - 3; } else { @@ -2098,14 +2464,14 @@ Vec_Str_t * Acb_GeneratePatch2( Gia_Man_t * pGia, Vec_Ptr_t * vIns, Vec_Ptr_t * Vec_PtrFreeFree( vNames ); Vec_WecFree( vGates ); - printf( "Synthesized patch with %d inputs, %d outputs and %d gates.\n", nIns, nOuts, nWires ); + printf( "Synthesized patch with %d inputs, %d outputs and %d gates (including %d two-input gates).\n", nIns, nOuts, nWires, nTwoIns ); return vStr; } -void Acb_GenerateFile2( Gia_Man_t * pGia, Vec_Ptr_t * vIns, Vec_Ptr_t * vOuts, char * pFileName, char * pFileNameOut ) +void Acb_GenerateFile2( Gia_Man_t * pGia, Vec_Ptr_t * vIns, Vec_Ptr_t * vOuts, char * pFileName, char * pFileNameOut, int fSkipMffc ) { extern void Acb_GenerateFilePatch( Vec_Str_t * p, char * pFileNamePatch ); extern void Acb_GenerateFileOut( Vec_Str_t * vPatchLine, char * pFileNameF, char * pFileNameOut, Vec_Str_t * vPatch ); - extern void Acb_NtkInsert( char * pFileNameIn, char * pFileNameOut, Vec_Ptr_t * vNames, int fNumber ); + extern void Acb_NtkInsert( char * pFileNameIn, char * pFileNameOut, Vec_Ptr_t * vNames, int fNumber, int fSkipMffc ); Vec_Str_t * vInst = Acb_GenerateInstance2( vIns, vOuts ); Vec_Str_t * vPatch = Acb_GeneratePatch2( pGia, vIns, vOuts ); //printf( "%s", Vec_StrArray(vPatch) ); @@ -2113,7 +2479,7 @@ void Acb_GenerateFile2( Gia_Man_t * pGia, Vec_Ptr_t * vIns, Vec_Ptr_t * vOuts, c // generate output files Acb_GenerateFilePatch( vPatch, "patch.v" ); printf( "Finished dumping patch file \"%s\".\n", "patch.v" ); - Acb_NtkInsert( pFileName, "temp.v", vOuts, 0 ); + Acb_NtkInsert( pFileName, "temp.v", vOuts, 0, fSkipMffc ); printf( "Finished dumping intermediate file \"%s\".\n", "temp.v" ); Acb_GenerateFileOut( vInst, "temp.v", pFileNameOut, vPatch ); printf( "Finished dumping the resulting file \"%s\".\n", pFileNameOut ); @@ -2479,7 +2845,7 @@ Vec_Ptr_t * Acb_TransformPatchFunctions( Vec_Ptr_t * vSops, Vec_Wec_t * vSupps, Vec_IntWriteEntry( vMap, iVar, Vec_IntSize(vUsed) ); Vec_IntPush( vUsed, iVar ); } - printf( "The number of used variables %d (out of %d).\n", Vec_IntSum(vPres), Vec_IntSize(vPres) ); + //printf( "The number of used variables %d (out of %d).\n", Vec_IntSum(vPres), Vec_IntSize(vPres) ); // remap SOPs Vec_WecForEachLevel( vSupps, vLevel, i ) { @@ -2505,13 +2871,14 @@ Vec_Ptr_t * Acb_TransformPatchFunctions( Vec_Ptr_t * vSops, Vec_Wec_t * vSupps, SeeAlso [] ***********************************************************************/ -int Acb_NtkEcoPerform( Acb_Ntk_t * pNtkF, Acb_Ntk_t * pNtkG, char * pFileName[4], int fCisOnly, int fCheck, int fVerbose, int fVeryVerbose ) +int Acb_NtkEcoPerform( Acb_Ntk_t * pNtkF, Acb_Ntk_t * pNtkG, char * pFileName[4], int nTimeout, int fCisOnly, int fInputs, int fCheck, int fUnitW, int fVerbose, int fVeryVerbose ) { extern Gia_Man_t * Abc_SopSynthesizeOne( char * pSop, int fClp ); + abctime clkStart = Abc_Clock(); abctime clk = Abc_Clock(); int nTargets = Vec_IntSize(&pNtkF->vTargets); - int TimeOut = fCisOnly ? 0 : 60; // 60 seconds + int TimeOut = fCisOnly ? 0 : 120; // 60 seconds int RetValue = 1; // compute various sets of nodes @@ -2520,7 +2887,7 @@ int Acb_NtkEcoPerform( Acb_Ntk_t * pNtkF, Acb_Ntk_t * pNtkG, char * pFileName[4] Vec_Int_t * vSuppF = Acb_NtkFindSupp( pNtkF, vRoots ); Vec_Int_t * vSuppG = Acb_NtkFindSupp( pNtkG, vRoots ); Vec_Int_t * vSupp = Vec_IntTwoMerge( vSuppF, vSuppG ); - Vec_Int_t * vDivs = fCisOnly ? Acb_NtkFindDivsCis( pNtkF, vSupp ) : Acb_NtkFindDivs( pNtkF, vSupp, vBlock, fVerbose ); + Vec_Int_t * vDivs = (fCisOnly || fInputs) ? Acb_NtkFindDivsCis( pNtkF, vSupp ) : Acb_NtkFindDivs( pNtkF, vSupp, vBlock, fUnitW, fVerbose ); Vec_Int_t * vNodesF = Acb_NtkFindNodes( pNtkF, vRoots, vDivs ); Vec_Int_t * vNodesG = Acb_NtkFindNodes( pNtkG, vRoots, NULL ); @@ -2543,6 +2910,10 @@ int Acb_NtkEcoPerform( Acb_Ntk_t * pNtkF, Acb_Ntk_t * pNtkG, char * pFileName[4] char * pSop = NULL; int i; +// int Value = Acb_NtkSaveNames( pNtkF, vSupp, vNodesF, vRoots, vDivs, &pNtkF->vTargets, pGiaF ); +// Gia_AigerWrite( pGiaF, pFileBase, 0, 0, 0 ); +// return 0; + if ( fVerbose ) { printf( "The number of targets = %d.\n", nTargets ); @@ -2622,6 +2993,14 @@ int Acb_NtkEcoPerform( Acb_Ntk_t * pNtkF, Acb_Ntk_t * pNtkG, char * pFileName[4] RetValue = 0; goto cleanup; } + if ( nTimeout && (Abc_Clock() - clkStart)/CLOCKS_PER_SEC >= nTimeout ) + { + Vec_IntFreeP( &vSupp ); + ABC_FREE( pSop ); + printf( "The target computation timed out after %d seconds.\n", nTimeout ); + RetValue = 0; + goto cleanup; + } // add new function to the miter pOne = Abc_SopSynthesizeOne( pSop, 1 ); @@ -2683,6 +3062,16 @@ int Acb_NtkEcoPerform( Acb_Ntk_t * pNtkF, Acb_Ntk_t * pNtkG, char * pFileName[4] if ( pFileName[3] == NULL ) Acb_GenerateFilePatch( vPatch, "patch.v" ); Acb_GenerateFileOut( vInst, pFileName[0], pFileName[3] ? pFileName[3] : (char *)"out.v", vPatch ); printf( "Finished dumping resulting file \"%s\".\n\n", pFileName[3] ? pFileName[3] : "out.v" ); +/* + { + char * pFileBase = Extra_FileNameGenericAppend( pFileName[0], "_patch.v" ); + Acb_GenerateFilePatch( vPatch, pFileBase ); + pFileBase = Extra_FileNameGenericAppend( pFileName[0], "_out.v" ); + Acb_GenerateFileOut( vInst, pFileName[0], pFileName[3] ? pFileName[3] : pFileBase, vPatch ); + Acb_GenerateFileOut( vInst, pFileName[0], pFileName[3] ? pFileName[3] : "out.v", vPatch ); + printf( "Finished dumping resulting file \"%s\".\n\n", pFileName[3] ? pFileName[3] : pFileBase ); + } +*/ //Gia_AigerWrite( pGiaG, "test.aig", 0, 0, 0 ); cleanup: // cleanup @@ -2734,7 +3123,7 @@ void Acb_NtkTestRun2( char * pFileNames[3], int fVerbose ) Acb_Ntk_t * pNtk = Acb_VerilogSimpleRead( pFileNames[0], pFileNames[2] ); Acb_VerilogSimpleWrite( pNtk, pFileNameOut ); Acb_ManFree( pNtk->pDesign ); - Acb_IntallLibrary(); + Acb_IntallLibrary( 0 ); } /**Function************************************************************* @@ -2748,7 +3137,7 @@ void Acb_NtkTestRun2( char * pFileNames[3], int fVerbose ) SeeAlso [] ***********************************************************************/ -void Acb_NtkRunEco( char * pFileNames[4], int fCheck, int fRandom, int fVerbose, int fVeryVerbose ) +void Acb_NtkRunEco( char * pFileNames[4], int nTimeout, int fCheck, int fRandom, int fInputs, int fUnitW, int fVerbose, int fVeryVerbose ) { char Command[1000]; int Result = 1; Acb_Ntk_t * pNtkF = Acb_VerilogSimpleRead( pFileNames[0], pFileNames[2] ); @@ -2768,12 +3157,12 @@ void Acb_NtkRunEco( char * pFileNames[4], int fCheck, int fRandom, int fVerbose, assert( Acb_NtkCiNum(pNtkF) == Acb_NtkCiNum(pNtkG) ); assert( Acb_NtkCoNum(pNtkF) == Acb_NtkCoNum(pNtkG) ); - Acb_IntallLibrary(); + Acb_IntallLibrary( Abc_FrameReadSignalNames() != NULL ); - if ( !Acb_NtkEcoPerform( pNtkF, pNtkG, pFileNames, 0, fCheck, fVerbose, fVeryVerbose ) ) + if ( !Acb_NtkEcoPerform( pNtkF, pNtkG, pFileNames, nTimeout, 0, fInputs, fCheck, fUnitW, fVerbose, fVeryVerbose ) ) { // printf( "General computation timed out. Trying inputs only.\n\n" ); -// if ( !Acb_NtkEcoPerform( pNtkF, pNtkG, pFileNames, 1, fCheck, fVerbose, fVeryVerbose ) ) +// if ( !Acb_NtkEcoPerform( pNtkF, pNtkG, pFileNames, nTimeout, 1, fInputs, fCheck, fUnitW, fVerbose, fVeryVerbose ) ) // printf( "Input-only computation also timed out.\n\n" ); printf( "Computation did not succeed.\n" ); Result = 0; diff --git a/src/base/acb/acbTest.c b/src/base/acb/acbTest.c index fa632ca0..1faea72a 100644 --- a/src/base/acb/acbTest.c +++ b/src/base/acb/acbTest.c @@ -19,6 +19,11 @@ ***********************************************************************/ #include "acb.h" +#include "aig/saig/saig.h" +#include "aig/gia/giaAig.h" +#include "base/abc/abc.h" +#include "proof/fraig/fraig.h" +#include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START @@ -26,6 +31,8 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +static int fForceZero = 0; + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -41,8 +48,612 @@ ABC_NAMESPACE_IMPL_START SeeAlso [] ***********************************************************************/ +void Gia_ManSimTry( Gia_Man_t * pF, Gia_Man_t * pG ) +{ + int i, j, n, nWords = 500; + Vec_Wrd_t * vSimsF, * vSimsG; + Abc_Random(1); + Vec_WrdFreeP( &pF->vSimsPi ); + Vec_WrdFreeP( &pG->vSimsPi ); + pF->vSimsPi = Vec_WrdStartRandom( Gia_ManCiNum(pF) * nWords ); + pG->vSimsPi = Vec_WrdDup( pF->vSimsPi ); + vSimsF = Gia_ManSimPatSim( pF ); + vSimsG = Gia_ManSimPatSim( pG ); + assert( Gia_ManObjNum(pF) * nWords == Vec_WrdSize(vSimsF) ); + for ( i = 0; i < Gia_ManCoNum(pF)/2; i++ ) + { + Gia_Obj_t * pObjFb = Gia_ManCo( pF, 2*i+0 ); + Gia_Obj_t * pObjFx = Gia_ManCo( pF, 2*i+1 ); + Gia_Obj_t * pObjGb = Gia_ManCo( pG, 2*i+0 ); + Gia_Obj_t * pObjGx = Gia_ManCo( pG, 2*i+1 ); + word * pSimFb = Vec_WrdEntryP(vSimsF, Gia_ObjId(pF, pObjFb)*nWords); + word * pSimFx = Vec_WrdEntryP(vSimsF, Gia_ObjId(pF, pObjFx)*nWords); + word * pSimGb = Vec_WrdEntryP(vSimsG, Gia_ObjId(pG, pObjGb)*nWords); + word * pSimGx = Vec_WrdEntryP(vSimsG, Gia_ObjId(pG, pObjGx)*nWords); + + int nBitsFx = Abc_TtCountOnesVec(pSimFx, nWords); + int nBitsF1 = Abc_TtCountOnesVecMask(pSimFx, pSimFb, nWords, 1); + int nBitsF0 = nWords*64 - nBitsFx - nBitsF1; + + int nBitsGx = Abc_TtCountOnesVec(pSimGx, nWords); + int nBitsG1 = Abc_TtCountOnesVecMask(pSimGx, pSimGb, nWords, 1); + int nBitsG0 = nWords*64 - nBitsGx - nBitsG1; + + printf( "Output %4d : ", i ); + + printf( " RF : " ); + printf( "0 =%7.3f %% ", 100.0*nBitsF0/64/nWords ); + printf( "1 =%7.3f %% ", 100.0*nBitsF1/64/nWords ); + printf( "X =%7.3f %% ", 100.0*nBitsFx/64/nWords ); + + printf( " GF : " ); + printf( "0 =%7.3f %% ", 100.0*nBitsG0/64/nWords ); + printf( "1 =%7.3f %% ", 100.0*nBitsG1/64/nWords ); + printf( "X =%7.3f %% ", 100.0*nBitsGx/64/nWords ); + + printf( "\n" ); + if ( i == 20 ) + break; + } + + printf( "\n" ); + for ( j = 0; j < 20; j++ ) + { + for ( n = 0; n < 2; n++ ) + { + for ( i = 0; i < Gia_ManCoNum(pF)/2; i++ ) + { + Gia_Obj_t * pObjFb = Gia_ManCo( pF, 2*i+0 ); + Gia_Obj_t * pObjFx = Gia_ManCo( pF, 2*i+1 ); + Gia_Obj_t * pObjGb = Gia_ManCo( pG, 2*i+0 ); + Gia_Obj_t * pObjGx = Gia_ManCo( pG, 2*i+1 ); + word * pSimFb = Vec_WrdEntryP(vSimsF, Gia_ObjId(pF, pObjFb)*nWords); + word * pSimFx = Vec_WrdEntryP(vSimsF, Gia_ObjId(pF, pObjFx)*nWords); + word * pSimGb = Vec_WrdEntryP(vSimsG, Gia_ObjId(pG, pObjGb)*nWords); + word * pSimGx = Vec_WrdEntryP(vSimsG, Gia_ObjId(pG, pObjGx)*nWords); + word * pSimb = n ? pSimGb : pSimFb; + word * pSimx = n ? pSimGx : pSimFx; + if ( Abc_TtGetBit(pSimx, j) ) + printf( "x" ); + else if ( Abc_TtGetBit(pSimb, j) ) + printf( "1" ); + else + printf( "0" ); + } + printf( "\n" ); + } + printf( "\n" ); + } + + Vec_WrdFree( vSimsF ); + Vec_WrdFree( vSimsG ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDualNot( Gia_Man_t * p, int LitA[2], int LitZ[2] ) +{ + LitZ[0] = Abc_LitNot(LitA[0]); + LitZ[1] = LitA[1]; + + if ( fForceZero ) LitZ[0] = Gia_ManHashAnd( p, LitZ[0], Abc_LitNot(LitZ[1]) ); +} +// computes Z = XOR(A, B) where A, B, Z belong to {0,1,x} encoded as 0=00, 1=01, x=1- +void Gia_ManDualXor2( Gia_Man_t * p, int LitA[2], int LitB[2], int LitZ[2] ) +{ + LitZ[0] = Gia_ManHashXor( p, LitA[0], LitB[0] ); + LitZ[1] = Gia_ManHashOr( p, LitA[1], LitB[1] ); + + if ( fForceZero ) LitZ[0] = Gia_ManHashAnd( p, LitZ[0], Abc_LitNot(LitZ[1]) ); +} +void Gia_ManDualXorN( Gia_Man_t * p, int * pLits, int n, int LitZ[2] ) +{ + int i; + LitZ[0] = 0; + LitZ[1] = 0; + for ( i = 0; i < n; i++ ) + { + LitZ[0] = Gia_ManHashXor( p, LitZ[0], pLits[2*i] ); + LitZ[1] = Gia_ManHashOr ( p, LitZ[1], pLits[2*i+1] ); + } +} +// computes Z = AND(A, B) where A, B, Z belong to {0,1,x} encoded as 0=00, 1=01, z=1- +void Gia_ManDualAnd2( Gia_Man_t * p, int LitA[2], int LitB[2], int LitZ[2] ) +{ + int ZeroA = Gia_ManHashAnd( p, Abc_LitNot(LitA[0]), Abc_LitNot(LitA[1]) ); + int ZeroB = Gia_ManHashAnd( p, Abc_LitNot(LitB[0]), Abc_LitNot(LitB[1]) ); + int ZeroZ = Gia_ManHashOr( p, ZeroA, ZeroB ); + LitZ[0] = Gia_ManHashAnd( p, LitA[0], LitB[0] ); + LitZ[1] = Gia_ManHashAnd( p, Gia_ManHashOr( p, LitA[1], LitB[1] ), Abc_LitNot(ZeroZ) ); + + //LitZ[0] = Gia_ManHashAnd( p, Gia_ManHashAnd(p, LitA[0], Abc_LitNot(LitA[1])), Gia_ManHashAnd(p, LitB[0], Abc_LitNot(LitB[1])) ); + //LitZ[1] = Gia_ManHashAnd( p, Gia_ManHashOr(p, LitA[0], LitA[1]), Gia_ManHashOr(p, LitB[0], LitB[1]) ); + //LitZ[1] = Gia_ManHashAnd( p, LitZ[1], Abc_LitNot(LitZ[0]) ); +} +void Gia_ManDualAndN( Gia_Man_t * p, int * pLits, int n, int LitZ[2] ) +{ + int i, LitZero = 0, LitOne = 0; + LitZ[0] = 1; + for ( i = 0; i < n; i++ ) + { + int Lit = Gia_ManHashAnd( p, Abc_LitNot(pLits[2*i]), Abc_LitNot(pLits[2*i+1]) ); + LitZero = Gia_ManHashOr( p, LitZero, Lit ); + LitOne = Gia_ManHashOr( p, LitOne, pLits[2*i+1] ); + LitZ[0] = Gia_ManHashAnd( p, LitZ[0], pLits[2*i] ); + } + LitZ[1] = Gia_ManHashAnd( p, LitOne, Abc_LitNot(LitZero) ); + + if ( fForceZero ) LitZ[0] = Gia_ManHashAnd( p, LitZ[0], Abc_LitNot(LitZ[1]) ); +} +/* +module _DC(O, C, D); + output O; + input C, D; + assign O = D ? 1'bx : C; +endmodule +*/ +void Gia_ManDualDc( Gia_Man_t * p, int LitC[2], int LitD[2], int LitZ[2] ) +{ + LitZ[0] = LitC[0]; +// LitZ[0] = Gia_ManHashMux( p, LitD[0], 0, LitC[0] ); + LitZ[1] = Gia_ManHashOr(p, Gia_ManHashOr(p,LitD[0],LitD[1]), LitC[1] ); + + if ( fForceZero ) LitZ[0] = Gia_ManHashAnd( p, LitZ[0], Abc_LitNot(LitZ[1]) ); +} +void Gia_ManDualMux( Gia_Man_t * p, int LitC[2], int LitT[2], int LitE[2], int LitZ[2] ) +{ +/* + // total logic size: 18 nodes + int Xnor = Gia_ManHashXor( p, Abc_LitNot(LitT[0]), LitE[0] ); + int Cond = Gia_ManHashAnd( p, Abc_LitNot(LitT[1]), Abc_LitNot(LitE[1]) ); + int pTempE[2], pTempT[2]; + pTempE[0] = Gia_ManHashMux( p, LitC[0], LitT[0], LitE[0] ); + pTempE[1] = Gia_ManHashMux( p, LitC[0], LitT[1], LitE[1] ); + //pTempT[0] = LitT[0]; + pTempT[0] = Gia_ManHashAnd( p, LitT[0], LitE[0] ); + pTempT[1] = Gia_ManHashAnd( p, Cond, Xnor ); + LitZ[0] = Gia_ManHashMux( p, LitC[1], pTempT[0], pTempE[0] ); + LitZ[1] = Gia_ManHashMux( p, LitC[1], pTempT[1], pTempE[1] ); +*/ + // total logic size: 14 nodes + int Xnor = Gia_ManHashXor( p, Abc_LitNot(LitT[0]), LitE[0] ); + int Cond = Gia_ManHashAnd( p, Abc_LitNot(LitT[1]), Abc_LitNot(LitE[1]) ); + int XVal1 = Abc_LitNot( Gia_ManHashAnd( p, Cond, Xnor ) ); + int XVal0 = Gia_ManHashMux( p, LitC[0], LitT[1], LitE[1] ); + LitZ[0] = Gia_ManHashMux( p, LitC[0], LitT[0], LitE[0] ); + LitZ[1] = Gia_ManHashMux( p, LitC[1], XVal1, XVal0 ); + + if ( fForceZero ) LitZ[0] = Gia_ManHashAnd( p, LitZ[0], Abc_LitNot(LitZ[1]) ); +} +int Gia_ManDualCompare( Gia_Man_t * p, int LitF[2], int LitS[2] ) +{ + int iMiter = Gia_ManHashXor( p, LitF[0], LitS[0] ); + iMiter = Gia_ManHashOr( p, LitF[1], iMiter ); + iMiter = Gia_ManHashAnd( p, Abc_LitNot(LitS[1]), iMiter ); + return iMiter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Acb_ObjToGiaDual( Gia_Man_t * pNew, Acb_Ntk_t * p, int iObj, Vec_Int_t * vTemp, Vec_Int_t * vCopies, int pRes[2] ) +{ + //char * pName = Abc_NamStr( p->pDesign->pStrs, Acb_ObjName(p, iObj) ); + int * pFanin, iFanin, k, Type; + assert( !Acb_ObjIsCio(p, iObj) ); + Vec_IntClear( vTemp ); + Acb_ObjForEachFaninFast( p, iObj, pFanin, iFanin, k ) + { + int * pLits = Vec_IntEntryP( vCopies, 2*iFanin ); + assert( pLits[0] >= 0 && pLits[1] >= 0 ); + Vec_IntPushTwo( vTemp, pLits[0], pLits[1] ); + } + Type = Acb_ObjType( p, iObj ); + if ( Type == ABC_OPER_CONST_F ) + { + pRes[0] = 0; + pRes[1] = 0; + return; + } + if ( Type == ABC_OPER_CONST_T ) + { + pRes[0] = 1; + pRes[1] = 0; + return; + } + if ( Type == ABC_OPER_CONST_X ) + { + pRes[0] = 0; + pRes[1] = 1; + return; + } + if ( Type == ABC_OPER_BIT_BUF ) + { + pRes[0] = Vec_IntEntry(vTemp, 0); + pRes[1] = Vec_IntEntry(vTemp, 1); + return; + } + if ( Type == ABC_OPER_BIT_INV ) + { + Gia_ManDualNot( pNew, Vec_IntArray(vTemp), pRes ); + return; + } + if ( Type == ABC_OPER_TRI ) + { + // in the file inputs are ordered as follows: _DC \n6_5[9] ( .O(\108 ), .C(\96 ), .D(\107 )); + // in this code, we expect them as follows: void Gia_ManDualDc( Gia_Man_t * p, int LitC[2], int LitD[2], int LitZ[2] ) + assert( Vec_IntSize(vTemp) == 4 ); + Gia_ManDualDc( pNew, Vec_IntArray(vTemp), Vec_IntArray(vTemp) + 2, pRes ); + return; + } + if ( Type == ABC_OPER_BIT_MUX ) + { + // in the file inputs are ordered as follows: _HMUX \U$1 ( .O(\282 ), .I0(1'b1), .I1(\277 ), .S(\281 )); + // in this code, we expect them as follows: void Gia_ManDualMux( Gia_Man_t * p, int LitC[2], int LitT[2], int LitE[2], int LitZ[2] ) + assert( Vec_IntSize(vTemp) == 6 ); + ABC_SWAP( int, Vec_IntArray(vTemp)[0], Vec_IntArray(vTemp)[4] ); + ABC_SWAP( int, Vec_IntArray(vTemp)[1], Vec_IntArray(vTemp)[5] ); + Gia_ManDualMux( pNew, Vec_IntArray(vTemp), Vec_IntArray(vTemp) + 2, Vec_IntArray(vTemp) + 4, pRes ); + return; + } + if ( Type == ABC_OPER_BIT_AND || Type == ABC_OPER_BIT_NAND ) + { + Gia_ManDualAndN( pNew, Vec_IntArray(vTemp), Vec_IntSize(vTemp)/2, pRes ); + if ( Type == ABC_OPER_BIT_NAND ) + pRes[0] = Abc_LitNot( pRes[0] ); + return; + } + if ( Type == ABC_OPER_BIT_OR || Type == ABC_OPER_BIT_NOR ) + { + int * pArray = Vec_IntArray( vTemp ); + for ( k = 0; k < Vec_IntSize(vTemp)/2; k++ ) + pArray[2*k] = Abc_LitNot( pArray[2*k] ); + Gia_ManDualAndN( pNew, pArray, Vec_IntSize(vTemp)/2, pRes ); + if ( Type == ABC_OPER_BIT_OR ) + pRes[0] = Abc_LitNot( pRes[0] ); + return; + } + if ( Type == ABC_OPER_BIT_XOR || Type == ABC_OPER_BIT_NXOR ) + { + assert( Vec_IntSize(vTemp) == 4 ); + Gia_ManDualXor2( pNew, Vec_IntArray(vTemp), Vec_IntArray(vTemp) + 2, pRes ); + if ( Type == ABC_OPER_BIT_NXOR ) + pRes[0] = Abc_LitNot( pRes[0] ); + return; + } + assert( 0 ); +} +Gia_Man_t * Acb_NtkGiaDeriveDual( Acb_Ntk_t * p ) +{ + extern Vec_Int_t * Acb_NtkFindNodes2( Acb_Ntk_t * p ); + Gia_Man_t * pNew, * pOne; + Vec_Int_t * vFanins, * vNodes; + Vec_Int_t * vCopies = Vec_IntStartFull( 2*Acb_NtkObjNum(p) ); + int i, iObj, * pLits; + pNew = Gia_ManStart( 5 * Acb_NtkObjNum(p) ); + pNew->pName = Abc_UtilStrsav(Acb_NtkName(p)); + Gia_ManHashAlloc( pNew ); + pLits = Vec_IntEntryP( vCopies, 0 ); + pLits[0] = 0; + pLits[1] = 0; + Acb_NtkForEachCi( p, iObj, i ) + { + pLits = Vec_IntEntryP( vCopies, 2*iObj ); + pLits[0] = Gia_ManAppendCi(pNew); + pLits[1] = 0; + } + vFanins = Vec_IntAlloc( 4 ); + vNodes = Acb_NtkFindNodes2( p ); + Vec_IntForEachEntry( vNodes, iObj, i ) + { + pLits = Vec_IntEntryP( vCopies, 2*iObj ); + Acb_ObjToGiaDual( pNew, p, iObj, vFanins, vCopies, pLits ); + } + Vec_IntFree( vNodes ); + Vec_IntFree( vFanins ); + Acb_NtkForEachCo( p, iObj, i ) + { + pLits = Vec_IntEntryP( vCopies, 2*Acb_ObjFanin(p, iObj, 0) ); + Gia_ManAppendCo( pNew, pLits[0] ); + Gia_ManAppendCo( pNew, pLits[1] ); + } + Vec_IntFree( vCopies ); + pNew = Gia_ManCleanup( pOne = pNew ); + Gia_ManStop( pOne ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Acb_NtkGiaDeriveMiter( Gia_Man_t * pOne, Gia_Man_t * pTwo, int Type ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + assert( Gia_ManCiNum(pOne) == Gia_ManCiNum(pTwo) ); + assert( Gia_ManCoNum(pOne) == Gia_ManCoNum(pTwo) ); + pNew = Gia_ManStart( Gia_ManObjNum(pOne) + Gia_ManObjNum(pTwo) + 5*Gia_ManCoNum(pOne)/2 ); + pNew->pName = Abc_UtilStrsav( "miter" ); + pNew->pSpec = NULL; + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(pOne)->Value = 0; + Gia_ManConst0(pTwo)->Value = 0; + Gia_ManForEachCi( pOne, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachCi( pTwo, pObj, i ) + pObj->Value = Gia_ManCi(pOne, i)->Value; + Gia_ManForEachAnd( pOne, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachAnd( pTwo, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( pOne, pObj, i ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + Gia_ManForEachCo( pTwo, pObj, i ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + if ( Type == 0 ) // only main circuit + { + for ( i = 0; i < Gia_ManCoNum(pOne); i += 2 ) + { + int pLitsF[2] = { Gia_ManCo(pOne, i)->Value, Gia_ManCo(pOne, i+1)->Value }; + int pLitsS[2] = { Gia_ManCo(pTwo, i)->Value, Gia_ManCo(pTwo, i+1)->Value }; + Gia_ManAppendCo( pNew, pLitsF[0] ); + Gia_ManAppendCo( pNew, pLitsS[0] ); + } + } + else if ( Type == 1 ) // only shadow circuit + { + for ( i = 0; i < Gia_ManCoNum(pOne); i += 2 ) + { + int pLitsF[2] = { Gia_ManCo(pOne, i)->Value, Gia_ManCo(pOne, i+1)->Value }; + int pLitsS[2] = { Gia_ManCo(pTwo, i)->Value, Gia_ManCo(pTwo, i+1)->Value }; + Gia_ManAppendCo( pNew, pLitsF[1] ); + Gia_ManAppendCo( pNew, pLitsS[1] ); + } + } + else // comparator of the two + { + for ( i = 0; i < Gia_ManCoNum(pOne); i += 2 ) + { + int pLitsF[2] = { Gia_ManCo(pOne, i)->Value, Gia_ManCo(pOne, i+1)->Value }; + int pLitsS[2] = { Gia_ManCo(pTwo, i)->Value, Gia_ManCo(pTwo, i+1)->Value }; + Gia_ManAppendCo( pNew, Gia_ManDualCompare( pNew, pLitsF, pLitsS ) ); + } + } + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Acb_OutputFile( char * pFileName, Acb_Ntk_t * pNtkF, int * pModel ) +{ + char * pFileName0 = pFileName? pFileName : "output"; + FILE * pFile = fopen( pFileName0, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open results file \"%s\".\n", pFileName0 ); + return; + } + if ( pModel == NULL ) + fprintf( pFile, "EQ\n" ); + else + { + /* + NEQ + in 1 + a 1 + b 0 + */ + int i, iObj; + fprintf( pFile, "NEQ\n" ); + Acb_NtkForEachPi( pNtkF, iObj, i ) + fprintf( pFile, "%s %d\n", Acb_ObjNameStr(pNtkF, iObj), pModel[i] ); + } + fclose( pFile ); + printf( "Produced output file \"%s\".\n\n", pFileName0 ); +} +int * Acb_NtkSolve( Gia_Man_t * p ) +{ + extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); + Aig_Man_t * pMan = Gia_ManToAig( p, 0 ); + Abc_Ntk_t * pNtkTemp = Abc_NtkFromAigPhase( pMan ); + Prove_Params_t Params, * pParams = &Params; + Prove_ParamsSetDefault( pParams ); + pParams->fUseRewriting = 1; + pParams->fVerbose = 0; + Aig_ManStop( pMan ); + if ( pNtkTemp ) + { + abctime clk = Abc_Clock(); + int RetValue = Abc_NtkIvyProve( &pNtkTemp, pParams ); + int * pModel = pNtkTemp->pModel; + pNtkTemp->pModel = NULL; + Abc_NtkDelete( pNtkTemp ); + printf( "The networks are %s. ", RetValue == 1 ? "equivalent" : (RetValue == 0 ? "NOT equivalent" : "UNDECIDED") ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + if ( RetValue == 0 ) + return pModel; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Various statistics.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Acb_NtkPrintCecStats( Acb_Ntk_t * pNtk ) +{ + int iObj, nDcs = 0, nMuxes = 0; + Acb_NtkForEachNode( pNtk, iObj ) + if ( Acb_ObjType( pNtk, iObj ) == ABC_OPER_TRI ) + nDcs++; + else if ( Acb_ObjType( pNtk, iObj ) == ABC_OPER_BIT_MUX ) + nMuxes++; + + printf( "PI = %6d ", Acb_NtkCiNum(pNtk) ); + printf( "PO = %6d ", Acb_NtkCoNum(pNtk) ); + printf( "Obj = %6d ", Acb_NtkObjNum(pNtk) ); + printf( "DC = %4d ", nDcs ); + printf( "Mux = %4d ", nMuxes ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Changing the PI order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Acb_NtkUpdateCiOrder( Acb_Ntk_t * pNtkF, Acb_Ntk_t * pNtkG ) +{ + int i, iObj; + Vec_Int_t * vMap = Vec_IntStartFull( Acb_ManNameIdMax(pNtkG->pDesign) ); + Vec_Int_t * vOrder = Vec_IntStartFull( Acb_NtkCiNum(pNtkG) ); + Acb_NtkForEachCi( pNtkG, iObj, i ) + Vec_IntWriteEntry( vMap, Acb_ObjName(pNtkG, iObj), i ); + Acb_NtkForEachCi( pNtkF, iObj, i ) + { + int NameIdG = Acb_ManStrId( pNtkG->pDesign, Acb_ObjNameStr(pNtkF, iObj) ); + int iPerm = NameIdG < Vec_IntSize(vMap) ? Vec_IntEntry( vMap, NameIdG ) : -1; + if ( iPerm == -1 ) + printf( "Cannot find name \"%s\" of PI %d of F among PIs of G.\n", Acb_ObjNameStr(pNtkF, iObj), i ); + else + Vec_IntWriteEntry( vOrder, iPerm, iObj ); + } + Vec_IntClear( &pNtkF->vCis ); + Vec_IntAppend( &pNtkF->vCis, vOrder ); + Vec_IntFree( vOrder ); + Vec_IntFree( vMap ); +} +int Acb_NtkCheckPiOrder( Acb_Ntk_t * pNtkF, Acb_Ntk_t * pNtkG ) +{ + int i, nPis = Acb_NtkCiNum(pNtkF); + for ( i = 0; i < nPis; i++ ) + { + char * pNameF = Acb_ObjNameStr( pNtkF, Acb_NtkCi(pNtkF, i) ); + char * pNameG = Acb_ObjNameStr( pNtkG, Acb_NtkCi(pNtkG, i) ); + if ( strcmp(pNameF, pNameG) ) + { +// printf( "PI %d has different names (%s and %s) in these networks.\n", i, pNameF, pNameG ); + printf( "Networks have different PI names. Reordering PIs of the implementation network.\n" ); + Acb_NtkUpdateCiOrder( pNtkF, pNtkG ); + break; + } + } + if ( i == nPis ) + printf( "Networks have the same PI names.\n" ); + return i == nPis; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ void Acb_NtkRunTest( char * pFileNames[4], int fFancy, int fVerbose ) { + extern Acb_Ntk_t * Acb_VerilogSimpleRead( char * pFileName, char * pFileNameW ); + extern void Gia_AigerWrite( Gia_Man_t * p, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine ); + + int fSolve = 1; + int * pModel = NULL; + Gia_Man_t * pGiaF = NULL; + Gia_Man_t * pGiaG = NULL; + Gia_Man_t * pGia = NULL; + Acb_Ntk_t * pNtkF = Acb_VerilogSimpleRead( pFileNames[0], NULL ); + Acb_Ntk_t * pNtkG = Acb_VerilogSimpleRead( pFileNames[1], NULL ); + if ( !pNtkF || !pNtkG ) + return; + + assert( Acb_NtkCiNum(pNtkF) == Acb_NtkCiNum(pNtkG) ); + assert( Acb_NtkCoNum(pNtkF) == Acb_NtkCoNum(pNtkG) ); + + Acb_NtkCheckPiOrder( pNtkF, pNtkG ); + //Acb_NtkCheckPiOrder( pNtkG, pNtkF ); + Acb_NtkPrintCecStats( pNtkF ); + Acb_NtkPrintCecStats( pNtkG ); + + pGiaF = Acb_NtkGiaDeriveDual( pNtkF ); + pGiaG = Acb_NtkGiaDeriveDual( pNtkG ); + pGia = Acb_NtkGiaDeriveMiter( pGiaF, pGiaG, 2 ); + //Gia_AigerWrite( pGiaF, Extra_FileNameGenericAppend(pFileNames[1], "_f2.aig"), 0, 0, 0 ); + //Gia_AigerWrite( pGiaG, Extra_FileNameGenericAppend(pFileNames[1], "_g2.aig"), 0, 0, 0 ); + //Gia_AigerWrite( pGia, Extra_FileNameGenericAppend(pFileNames[1], "_miter_0.aig"), 0, 0, 0 ); + //printf( "Written the miter info file \"%s\".\n", Extra_FileNameGenericAppend(pFileNames[1], "_miter_0.aig") ); + + //Gia_ManPrintStats( pGia, NULL ); + //Gia_ManSimTry( pGiaF, pGiaG ); + + if ( fSolve ) + { + pModel = Acb_NtkSolve( pGia ); + Acb_OutputFile( pFileNames[2], pNtkF, pModel ); + ABC_FREE( pModel ); + } + + Gia_ManStop( pGia ); + Gia_ManStop( pGiaF ); + Gia_ManStop( pGiaG ); + + Acb_ManFree( pNtkF->pDesign ); + Acb_ManFree( pNtkG->pDesign ); } diff --git a/src/base/acb/acbUtil.c b/src/base/acb/acbUtil.c index 2243541b..ef106e86 100644 --- a/src/base/acb/acbUtil.c +++ b/src/base/acb/acbUtil.c @@ -21,6 +21,7 @@ #include "acb.h" #include "base/abc/abc.h" #include "base/io/ioAbc.h" +#include "base/main/main.h" ABC_NAMESPACE_IMPL_START @@ -71,6 +72,15 @@ Vec_Int_t * Acb_ObjCollectTfi( Acb_Ntk_t * p, int iObj, int fTerm ) Acb_ObjCollectTfi_rec( p, iObj, fTerm ); return &p->vArray0; } +Vec_Int_t * Acb_ObjCollectTfiVec( Acb_Ntk_t * p, Vec_Int_t * vObjs ) +{ + int i, iObj; + Vec_IntClear( &p->vArray0 ); + Acb_NtkIncTravId( p ); + Vec_IntForEachEntry( vObjs, iObj, i ) + Acb_ObjCollectTfi_rec( p, iObj, 0 ); + return &p->vArray0; +} void Acb_ObjCollectTfo_rec( Acb_Ntk_t * p, int iObj, int fTerm ) { @@ -95,6 +105,219 @@ Vec_Int_t * Acb_ObjCollectTfo( Acb_Ntk_t * p, int iObj, int fTerm ) Acb_ObjCollectTfo_rec( p, iObj, fTerm ); return &p->vArray1; } +Vec_Int_t * Acb_ObjCollectTfoVec( Acb_Ntk_t * p, Vec_Int_t * vObjs ) +{ + int i, iObj; + if ( !Acb_NtkHasObjFanout(p) ) + Acb_NtkCreateFanout( p ); + Vec_IntClear( &p->vArray1 ); + Acb_NtkIncTravId( p ); + Vec_IntForEachEntry( vObjs, iObj, i ) + Acb_ObjCollectTfo_rec( p, iObj, 0 ); + return &p->vArray1; +} + +/**Function************************************************************* + + Synopsis [Count the number of nodes driving the POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Acb_NtkIsPiBuffers( Acb_Ntk_t * p, int iObj ) +{ + if ( Acb_ObjIsCi(p, iObj) ) + return 1; + if ( Acb_ObjFaninNum(p, iObj) != 1 ) + return 0; + return Acb_NtkIsPiBuffers( p, Acb_ObjFanin(p, iObj, 0) ); +} +int Acb_NtkCountPiBuffers( Acb_Ntk_t * p, Vec_Int_t * vObjs ) +{ + int i, iObj, Count = 0; + Vec_IntForEachEntry( vObjs, iObj, i ) + Count += Acb_NtkIsPiBuffers( p, iObj ); + return Count; +} +int Acb_NtkCountPoDrivers( Acb_Ntk_t * p, Vec_Int_t * vObjs ) +{ + int i, iObj, Count = 0; + Acb_NtkIncTravId( p ); + Acb_NtkForEachCo( p, iObj, i ) + { + int Fanin0 = Acb_ObjFanin0(p, iObj); + Acb_ObjSetTravIdCur( p, iObj ); + Acb_ObjSetTravIdCur( p, Fanin0 ); + if ( Acb_ObjFaninNum(p, Fanin0) == 1 ) + Acb_ObjSetTravIdCur( p, Acb_ObjFanin0(p, Fanin0) ); + } + Vec_IntForEachEntry( vObjs, iObj, i ) + Count += Acb_ObjIsTravIdCur(p, iObj); + return Count; +} + +/**Function************************************************************* + + Synopsis [Compute MFFC size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Acb_NtkNodeDeref_rec( Vec_Int_t * vRefs, Acb_Ntk_t * p, int iObj ) +{ + int i, Fanin, * pFanins, Counter = 1; + if ( Acb_ObjIsCi(p, iObj) ) + return 0; + Acb_ObjForEachFaninFast( p, iObj, pFanins, Fanin, i ) + { + assert( Vec_IntEntry(vRefs, Fanin) > 0 ); + Vec_IntAddToEntry( vRefs, Fanin, -1 ); + if ( Vec_IntEntry(vRefs, Fanin) == 0 ) + Counter += Acb_NtkNodeDeref_rec( vRefs, p, Fanin ); + } + return Counter; +} +int Acb_NtkNodeRef_rec( Vec_Int_t * vRefs, Acb_Ntk_t * p, int iObj ) +{ + int i, Fanin, * pFanins, Counter = 1; + if ( Acb_ObjIsCi(p, iObj) ) + return 0; + Acb_ObjForEachFaninFast( p, iObj, pFanins, Fanin, i ) + { + if ( Vec_IntEntry(vRefs, Fanin) == 0 ) + Counter += Acb_NtkNodeRef_rec( vRefs, p, Fanin ); + Vec_IntAddToEntry( vRefs, Fanin, 1 ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Computing and updating direct and reverse logic level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Acb_NtkCollectDeref_rec( Vec_Int_t * vRefs, Acb_Ntk_t * p, int iObj, Vec_Int_t * vRes ) +{ + int i, Fanin, * pFanins; + if ( Acb_ObjIsCi(p, iObj) ) + return; + Vec_IntPush( vRes, iObj ); + Acb_ObjForEachFaninFast( p, iObj, pFanins, Fanin, i ) + { + assert( Vec_IntEntry(vRefs, Fanin) > 0 ); + Vec_IntAddToEntry( vRefs, Fanin, -1 ); + if ( Vec_IntEntry(vRefs, Fanin) == 0 ) + Acb_NtkCollectDeref_rec( vRefs, p, Fanin, vRes ); + } +} +Vec_Int_t * Acb_NtkCollectMffc( Acb_Ntk_t * p, Vec_Int_t * vObjsRefed, Vec_Int_t * vObjsDerefed ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + Vec_Int_t * vRefs = Vec_IntStart( Acb_NtkObjNumMax(p) ); + int i, iObj, Fanin, * pFanins; + Acb_NtkForEachObj( p, iObj ) + Acb_ObjForEachFaninFast( p, iObj, pFanins, Fanin, i ) + Vec_IntAddToEntry( vRefs, Fanin, 1 ); + Acb_NtkForEachCo( p, iObj, i ) + Vec_IntAddToEntry( vRefs, iObj, 1 ); + if ( vObjsRefed ) + Vec_IntForEachEntry( vObjsRefed, iObj, i ) + Vec_IntAddToEntry( vRefs, iObj, 1 ); + Vec_IntForEachEntry( vObjsDerefed, iObj, i ) + { + if ( Acb_ObjIsCo(p, iObj) ) + iObj = Acb_ObjFanin0(p, iObj); + if ( Vec_IntEntry(vRefs, iObj) != 0 ) + Acb_NtkCollectDeref_rec( vRefs, p, iObj, vRes ); + } + Vec_IntFree( vRefs ); + Vec_IntUniqify( vRes ); + return vRes; +} + +Vec_Int_t * Acb_NamesToIds( Acb_Ntk_t * pNtk, Vec_Int_t * vNamesInv, Vec_Ptr_t * vNames ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( Vec_PtrSize(vNames) ); + char * pName; int i; + Vec_PtrForEachEntry( char *, vNames, pName, i ) + { + int NameId = Acb_NtkStrId(pNtk, pName); + int iObjId = 0; + if ( NameId < 1 ) + printf( "Cannot find name \"%s\" in the network \"%s\".\n", pName, pNtk->pDesign->pName ); + else + iObjId = Vec_IntEntry( vNamesInv, NameId ); + Vec_IntPush( vRes, iObjId ); + } + return vRes; +} +int Acb_NtkCollectMfsGates( char * pFileName, Vec_Ptr_t * vNamesRefed, Vec_Ptr_t * vNamesDerefed, int nGates[5] ) +{ + Acb_Ntk_t * pNtkF = Acb_VerilogSimpleRead( pFileName, NULL ); + Vec_Int_t * vNamesInv = Vec_IntInvert( &pNtkF->vObjName, 0 ) ; + Vec_Int_t * vObjsRefed = Acb_NamesToIds( pNtkF, vNamesInv, vNamesRefed ); + Vec_Int_t * vObjsDerefed = Acb_NamesToIds( pNtkF, vNamesInv, vNamesDerefed ); + Vec_Int_t * vNodes = Acb_NtkCollectMffc( pNtkF, vObjsRefed, vObjsDerefed ); + int i, iObj, RetValue = Vec_IntSize(vNodes); + Vec_IntFree( vNamesInv ); + Vec_IntFree( vObjsRefed ); + Vec_IntFree( vObjsDerefed ); + for ( i = 0; i < 5; i++ ) + nGates[i] = 0; + Vec_IntForEachEntry( vNodes, iObj, i ) + { + int nFan = Acb_ObjFaninNum(pNtkF, iObj); + int Type = Acb_ObjType( pNtkF, iObj ); + if ( Type == ABC_OPER_CONST_F ) + nGates[0]++; + else if ( Type == ABC_OPER_CONST_T ) + nGates[1]++; + else if ( Type == ABC_OPER_BIT_BUF || Type == ABC_OPER_CO ) + nGates[2]++; + else if ( Type == ABC_OPER_BIT_INV ) + nGates[3]++; + else + { + assert( nFan >= 2 ); + nGates[4] += Acb_ObjFaninNum(pNtkF, iObj)-1; + } + } + Vec_IntFree( vNodes ); + Acb_ManFree( pNtkF->pDesign ); + return RetValue; +} +Vec_Ptr_t * Acb_NtkReturnMfsGates( char * pFileName, Vec_Ptr_t * vNodes ) +{ + Vec_Ptr_t * vMffc = Vec_PtrAlloc( 100 ); + Acb_Ntk_t * pNtkF = Acb_VerilogSimpleRead( pFileName, NULL ); + Vec_Int_t * vNamesInv = Vec_IntInvert( &pNtkF->vObjName, 0 ) ; + Vec_Int_t * vNodeObjs = Acb_NamesToIds( pNtkF, vNamesInv, vNodes ); + Vec_Int_t * vNodeMffc = Acb_NtkCollectMffc( pNtkF, NULL, vNodeObjs ); + int i, iObj; + Vec_IntForEachEntry( vNodeMffc, iObj, i ) + Vec_PtrPush( vMffc, Abc_UtilStrsav( Acb_ObjNameStr(pNtkF, iObj) ) ); +//Vec_IntPrint( vNodeMffc ); +//Vec_PtrPrintNames( vMffc ); + Vec_IntFree( vNodeMffc ); + Vec_IntFree( vNodeObjs ); + Vec_IntFree( vNamesInv ); + Acb_ManFree( pNtkF->pDesign ); + return vMffc; +} /**Function************************************************************* @@ -671,6 +894,8 @@ int Acb_NtkExtract( char * pFileName0, char * pFileName1, int fUseXors, int fVer int nTargets = Vec_IntSize(&pNtkF->vTargets); Gia_Man_t * pGiaF = Acb_NtkToGia2( pNtkF, fUseBuf, fUseXors, &pNtkF->vTargets, 0 ); Gia_Man_t * pGiaG = Acb_NtkToGia2( pNtkG, 0, 0, NULL, nTargets ); + pGiaF->pSpec = Abc_UtilStrsav( pNtkF->pDesign->pSpec ); + pGiaG->pSpec = Abc_UtilStrsav( pNtkG->pDesign->pSpec ); assert( Acb_NtkCiNum(pNtkF) == Acb_NtkCiNum(pNtkG) ); assert( Acb_NtkCoNum(pNtkF) == Acb_NtkCoNum(pNtkG) ); *ppGiaF = pGiaF; @@ -784,6 +1009,8 @@ int Abc_NtkExtract( char * pFileName0, char * pFileName1, int fUseXors, int fVer Gia_Man_t * pGiaG = Abc_NtkToGia2( pNtkG, 0 ); assert( Abc_NtkCiNum(pNtkF) == Abc_NtkCiNum(pNtkG) ); assert( Abc_NtkCoNum(pNtkF) == Abc_NtkCoNum(pNtkG) ); + pGiaF->pSpec = Abc_UtilStrsav( pNtkF->pSpec ); + pGiaG->pSpec = Abc_UtilStrsav( pNtkG->pSpec ); *ppGiaF = pGiaF; *ppGiaG = pGiaG; *pvNodes = Abc_NtkCollectCopies( pNtkF, pGiaF, pvNodesR, pvPolar ); @@ -846,7 +1073,7 @@ Vec_Int_t * Acb_NtkPlaces( char * pFileName, Vec_Ptr_t * vNames ) ABC_FREE( pBuffer ); return vPlaces; } -void Acb_NtkInsert( char * pFileNameIn, char * pFileNameOut, Vec_Ptr_t * vNames, int fNumber ) +void Acb_NtkInsert( char * pFileNameIn, char * pFileNameOut, Vec_Ptr_t * vNames, int fNumber, int fSkipMffc ) { int i, k, Prev = 0, Pos, Pos2, iObj; Vec_Int_t * vPlaces; @@ -864,15 +1091,32 @@ void Acb_NtkInsert( char * pFileNameIn, char * pFileNameOut, Vec_Ptr_t * vNames, printf( "Cannot open input file \"%s\".\n", pFileNameIn ); return; } - vPlaces = Acb_NtkPlaces( pFileNameIn, vNames ); - Vec_IntForEachEntryDouble( vPlaces, Pos, iObj, i ) + if ( fSkipMffc ) { - for ( k = Prev; k < Pos; k++ ) - fputc( pBuffer[k], pFile ); - fprintf( pFile, "// [t_%d = %s] //", iObj, (char *)Vec_PtrEntry(vNames, iObj) ); - Prev = Pos; + Vec_Ptr_t * vMffcNames = Acb_NtkReturnMfsGates( pFileNameIn, vNames ); + vPlaces = Acb_NtkPlaces( pFileNameIn, vMffcNames ); + Vec_IntForEachEntryDouble( vPlaces, Pos, iObj, i ) + { + for ( k = Prev; k < Pos; k++ ) + fputc( pBuffer[k], pFile ); + fprintf( pFile, "// MFFC %d = %s //", iObj, (char *)Vec_PtrEntry(vMffcNames, iObj) ); + Prev = Pos; + } + Vec_IntFree( vPlaces ); + Vec_PtrFreeFree( vMffcNames ); + } + else + { + vPlaces = Acb_NtkPlaces( pFileNameIn, vNames ); + Vec_IntForEachEntryDouble( vPlaces, Pos, iObj, i ) + { + for ( k = Prev; k < Pos; k++ ) + fputc( pBuffer[k], pFile ); + fprintf( pFile, "// [t_%d = %s] //", iObj, (char *)Vec_PtrEntry(vNames, iObj) ); + Prev = Pos; + } + Vec_IntFree( vPlaces ); } - Vec_IntFree( vPlaces ); pName = strstr(pBuffer, "endmodule"); Pos2 = pName - pBuffer; for ( k = Prev; k < Pos2; k++ ) @@ -939,7 +1183,7 @@ void Acb_Ntk4CollectRing( Acb_Ntk_t * pNtk, Vec_Int_t * vStart, Vec_Int_t * vRes } void Acb_Ntk4DumpWeightsInt( Acb_Ntk_t * pNtk, Vec_Int_t * vObjs, char * pFileName ) { - int i, iObj;//, Weight; + int i, iObj;//, Count = 0;//, Weight; Vec_Int_t * vDists, * vStart, * vNexts; FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) @@ -971,15 +1215,30 @@ void Acb_Ntk4DumpWeightsInt( Acb_Ntk_t * pNtk, Vec_Int_t * vObjs, char * pFileNa // Vec_IntForEachEntry( vDists, Weight, i ) // if ( Weight && Acb_ObjNameStr(pNtk, i)[0] != '1' ) // fprintf( pFile, "%s %d\n", Acb_ObjNameStr(pNtk, i), 10000+Weight ); +/* + // mark reachable + Vec_IntClear( &pNtk->vArray0 ); + Acb_NtkIncTravId( pNtk ); + Acb_NtkForEachCo( pNtk, iObj, i ) + if ( !Vec_IntEntry(vStatus, i) ) + Acb_ObjCollectTfi_rec( pNtk, iObj, 0 ); +*/ Acb_NtkForEachObj( pNtk, iObj ) { char * pName = Acb_ObjNameStr(pNtk, iObj); int Weight = Vec_IntEntry(vDists, iObj); if ( Weight == 0 ) Weight = 10000; +/* + if ( !Acb_ObjSetTravIdCur(pNtk, iObj) ) + { + Count++; + continue; + } +*/ fprintf( pFile, "%s %d\n", pName, 100000+Weight ); } - + //printf( "Skipped %d nodes.\n", Count ); Vec_IntFree( vDists ); fclose( pFile ); } @@ -1000,27 +1259,6 @@ void Acb_Ntk4DumpWeights( char * pFileNameIn, Vec_Ptr_t * vObjNames, char * pFil Vec_IntFree( vObjs ); } -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Acb_NtkRunSim( char * pFileName[4], int nWords, int nBeam, int LevL, int LevU, int fOrder, int fFancy, int fUseBuf, int fRandom, int fUseWeights, int fVerbose, int fVeryVerbose ) -{ - extern int Gia_Sim4Try( char * pFileName0, char * pFileName1, char * pFileName2, int nWords, int nBeam, int LevL, int LevU, int fOrder, int fFancy, int fUseBuf, int fVerbose ); - extern void Acb_NtkRunEco( char * pFileNames[4], int fCheck, int fRandom, int fVerbose, int fVeryVerbose ); - char * pFileNames[4] = { pFileName[2], pFileName[1], fUseWeights ? (char *)"weights.txt" : NULL, pFileName[2] }; - if ( Gia_Sim4Try( pFileName[0], pFileName[1], pFileName[2], nWords, nBeam, LevL, LevU, fOrder, fFancy, fUseBuf, fVerbose ) ) - Acb_NtkRunEco( pFileNames, 1, fRandom, fVerbose, fVeryVerbose ); -} - - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/cba/cbaNtk.c b/src/base/cba/cbaNtk.c index 5be0aa6c..c3f8fae9 100644 --- a/src/base/cba/cbaNtk.c +++ b/src/base/cba/cbaNtk.c @@ -445,7 +445,7 @@ void Cba_NtkObjOrder( Cba_Ntk_t * p, Vec_Int_t * vObjs, Vec_Int_t * vNameIds ) // printf( "%s \n", pName ); // printf( "\n" ); // do the sorting - Vec_PtrSort( vNames, (int (*)(void))Cba_StrCmp ); + Vec_PtrSort( vNames, (int (*)(const void *, const void *))Cba_StrCmp ); // print after // Vec_PtrForEachEntry( char *, vNames, pName, i ) // printf( "%s \n", pName ); diff --git a/src/base/cmd/cmdHist.c b/src/base/cmd/cmdHist.c index 218d832f..b8cfc98f 100644 --- a/src/base/cmd/cmdHist.c +++ b/src/base/cmd/cmdHist.c @@ -65,7 +65,8 @@ void Cmd_HistoryAddCommand( Abc_Frame_t * p, const char * command ) strncmp(Buffer,"time",4) && strncmp(Buffer,"quit",4) && strncmp(Buffer,"alias",5) && -// strncmp(Buffer,"source",6) && + strncmp(Buffer,"source abc.rc",13) && + strncmp(Buffer,"source ..\\abc.rc",16) && strncmp(Buffer,"history",7) && strncmp(Buffer,"hi ", 3) && strcmp(Buffer,"hi") && Buffer[strlen(Buffer)-1] != '?' ) { diff --git a/src/base/io/io.c b/src/base/io/io.c index a5cffbf4..5cf74ef9 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -24,6 +24,13 @@ #include "proof/abs/abs.h" #include "sat/bmc/bmc.h" +#ifdef WIN32 +#include <process.h> +#define unlink _unlink +#else +#include <unistd.h> +#endif + ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// @@ -49,6 +56,7 @@ static int IoCommandReadVerilog ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadStatus ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadGig ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadJson ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadSF ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWrite ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteHie ( Abc_Frame_t * pAbc, int argc, char **argv ); @@ -118,6 +126,7 @@ void Io_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "I/O", "read_status", IoCommandReadStatus, 0 ); Cmd_CommandAdd( pAbc, "I/O", "&read_gig", IoCommandReadGig, 0 ); Cmd_CommandAdd( pAbc, "I/O", "read_json", IoCommandReadJson, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "read_sf", IoCommandReadSF, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write", IoCommandWrite, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_hie", IoCommandWriteHie, 0 ); @@ -1415,6 +1424,73 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadSF( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Io_TransformSF2PLA( char * pNameIn, char * pNameOut ); + + Abc_Ntk_t * pNtk; + FILE * pFile; + char * pFileName, * pFileTemp = "_temp_sf_.pla"; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + pFileName = argv[globalUtilOptind]; + if ( (pFile = fopen( pFileName, "r" )) == NULL ) + { + fprintf( pAbc->Err, "Cannot open input file \"%s\". \n", pFileName ); + return 1; + } + fclose( pFile ); + Io_TransformSF2PLA( pFileName, pFileTemp ); + pNtk = Io_Read( pFileTemp, IO_FILE_PLA, 1, 0 ); + unlink( pFileTemp ); + if ( pNtk == NULL ) + return 1; + ABC_FREE( pNtk->pName ); + pNtk->pName = Extra_FileNameGeneric( pFileName ); + ABC_FREE( pNtk->pSpec ); + pNtk->pSpec = Abc_UtilStrsav( pFileName ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + Abc_FrameClearVerifStatus( pAbc ); + + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_sf [-h] <file>\n" ); + fprintf( pAbc->Err, "\t reads file in SF format\n" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + /**Function************************************************************* @@ -2906,17 +2982,36 @@ usage: ***********************************************************************/ int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ) { + extern void Io_WriteVerilogLut( Abc_Ntk_t * pNtk, char * pFileName, int nLutSize, int fFixed, int fNoModules ); char * pFileName; - int c, fOnlyAnds = 0; + int c, fFixed = 0, fOnlyAnds = 0, fNoModules = 0; + int nLutSize = -1; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Kfamh" ) ) != EOF ) { switch ( c ) { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 2 || nLutSize > 6 ) + goto usage; + break; + case 'f': + fFixed ^= 1; + break; case 'a': fOnlyAnds ^= 1; break; + case 'm': + fNoModules ^= 1; + break; case 'h': goto usage; default: @@ -2930,6 +3025,8 @@ int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ) } if ( argc != globalUtilOptind + 1 ) goto usage; + if ( fFixed ) + nLutSize = 6; // get the output file name pFileName = argv[globalUtilOptind]; // call the corresponding file writer @@ -2941,14 +3038,19 @@ int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ) Io_WriteVerilog( pNtkTemp, pFileName, 1 ); Abc_NtkDelete( pNtkTemp ); } + else if ( nLutSize >= 2 && nLutSize <= 6 ) + Io_WriteVerilogLut( pAbc->pNtkCur, pFileName, nLutSize, fFixed, fNoModules ); else - Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_VERILOG ); + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_VERILOG ); return 0; usage: - fprintf( pAbc->Err, "usage: write_verilog [-ah] <file>\n" ); + fprintf( pAbc->Err, "usage: write_verilog [-K num] [-famh] <file>\n" ); fprintf( pAbc->Err, "\t writes the current network in Verilog format\n" ); + fprintf( pAbc->Err, "\t-K num : write the network using instances of K-LUTs (2 <= K <= 6) [default = not used]\n" ); + fprintf( pAbc->Err, "\t-f : toggle using fixed format [default = %s]\n", fFixed? "yes":"no" ); fprintf( pAbc->Err, "\t-a : toggle writing expressions with only ANDs (without XORs and MUXes) [default = %s]\n", fOnlyAnds? "yes":"no" ); + fprintf( pAbc->Err, "\t-m : toggle writing additional modules [default = %s]\n", !fNoModules? "yes":"no" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; diff --git a/src/base/io/ioReadAiger.c b/src/base/io/ioReadAiger.c index f87d971f..9cf41413 100644 --- a/src/base/io/ioReadAiger.c +++ b/src/base/io/ioReadAiger.c @@ -480,6 +480,7 @@ Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck ) if ( pCur < pContents + nFileSize && *pCur != 'c' ) { int Counter = 0; + int fNodeNames = 0; while ( pCur < pContents + nFileSize && *pCur != 'c' ) { // get the terminal type @@ -490,6 +491,12 @@ Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck ) vTerms = pNtkNew->vBoxes; else if ( *pCur == 'o' || *pCur == 'b' || *pCur == 'c' || *pCur == 'j' || *pCur == 'f' ) vTerms = pNtkNew->vPos; + else if ( *pCur == 'n' ) + { + fNodeNames++; + while ( *pCur++ != '\n' ); + continue; + } else { // fprintf( stdout, "Wrong terminal type.\n" ); @@ -543,6 +550,8 @@ Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck ) } // if ( Counter ) // printf( "Io_ReadAiger(): Added %d default names for nameless I/O/register objects.\n", Counter ); + if ( fNodeNames ) + printf( "Io_ReadAiger(): The names of internal nodes are not supported. Ignoring %d node names.\n", fNodeNames ); } else { diff --git a/src/base/io/ioReadBench.c b/src/base/io/ioReadBench.c index 3ea3fb70..42eb908d 100644 --- a/src/base/io/ioReadBench.c +++ b/src/base/io/ioReadBench.c @@ -88,7 +88,7 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ) Abc_Ntk_t * pNtk; Abc_Obj_t * pNode, * pNet; Vec_Str_t * vString; - unsigned uTruth[8]; + unsigned uTruth[2048]; char * pType, ** ppNames, * pString; int iLine, nNames, nDigits, fLutsPresent = 0; @@ -161,7 +161,7 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ) ppNames = (char **)vTokens->pArray + 3; nNames = vTokens->nSize - 3; // check the number of inputs - if ( nNames > 8 ) + if ( nNames > 15 ) { printf( "%s: Currently cannot read truth tables with more than 8 inputs (%d).\n", Extra_FileReaderGetFileName(p), nNames ); Vec_StrFree( vString ); diff --git a/src/base/io/ioReadBlif.c b/src/base/io/ioReadBlif.c index 405b44d6..e8979c9b 100644 --- a/src/base/io/ioReadBlif.c +++ b/src/base/io/ioReadBlif.c @@ -22,6 +22,9 @@ #include "base/main/main.h" #include "map/mio/mio.h" + + + ABC_NAMESPACE_IMPL_START @@ -877,10 +880,13 @@ int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) return 1; } // set timing info - //Abc_NtkTimeSetArrival( p->pNtkCur, Abc_ObjFanin0(pNet)->Id, (float)TimeRise, (float)TimeFall ); - Vec_IntPush( p->vInArrs, Abc_ObjFanin0(pNet)->Id ); - Vec_IntPush( p->vInArrs, Abc_Float2Int((float)TimeRise) ); - Vec_IntPush( p->vInArrs, Abc_Float2Int((float)TimeFall) ); + // printf("Debug: Forcing setting of arrival times\n"); + if (Abc_ObjFaninNum(pNet) >0){ + Abc_NtkTimeSetArrival( p->pNtkCur, Abc_ObjFanin0(pNet)->Id, (float)TimeRise, (float)TimeFall ); + Vec_IntPush( p->vInArrs, Abc_ObjFanin0(pNet)->Id ); + Vec_IntPush( p->vInArrs, Abc_Float2Int((float)TimeRise) ); + Vec_IntPush( p->vInArrs, Abc_Float2Int((float)TimeFall) ); + } return 0; } @@ -928,7 +934,10 @@ int Io_ReadBlifNetworkOutputRequired( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) return 1; } // set timing info -// Abc_NtkTimeSetRequired( p->pNtkCur, Abc_ObjFanout0(pNet)->Id, (float)TimeRise, (float)TimeFall ); + // printf("Setting required time for object %d to R %f F %f\n", + // Abc_ObjFanout0(pNet)->Id, (float)TimeRise, (float)TimeFall ); + + Abc_NtkTimeSetRequired( p->pNtkCur, Abc_ObjFanout0(pNet)->Id, (float)TimeRise, (float)TimeFall ); Vec_IntPush( p->vOutReqs, Abc_ObjFanout0(pNet)->Id ); Vec_IntPush( p->vOutReqs, Abc_Float2Int((float)TimeRise) ); Vec_IntPush( p->vOutReqs, Abc_Float2Int((float)TimeFall) ); diff --git a/src/base/io/ioReadBlifMv.c b/src/base/io/ioReadBlifMv.c index c1808ef5..e5c6fe49 100644 --- a/src/base/io/ioReadBlifMv.c +++ b/src/base/io/ioReadBlifMv.c @@ -1351,7 +1351,8 @@ static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine ) Abc_Ntk_t * pModel; Abc_Obj_t * pBox, * pNet, * pTerm; char * pToken, * pName, * pName2, ** ppNames; - int nEquals, Last, i, k; + int nEquals, i, k; + word Last; // split the line into tokens nEquals = Io_MvCountChars( pLine, '=' ); @@ -1404,9 +1405,9 @@ static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine ) pName2 = NULL; pName = Abc_ObjName(Abc_ObjFanout0(pTerm)); for ( k = 0; k < nEquals; k++ ) - if ( !strcmp( ppNames[2*((k+Last)%nEquals)], pName ) ) + if ( !strcmp( ppNames[2*(int)((k+Last)%nEquals)], pName ) ) { - pName2 = ppNames[2*((k+Last)%nEquals)+1]; + pName2 = ppNames[2*(int)((k+Last)%nEquals)+1]; Last = k+Last+1; break; } @@ -1656,7 +1657,7 @@ static int Io_MvWriteValues( Abc_Obj_t * pNode, Vec_Str_t * vFunc ) ***********************************************************************/ static int Io_MvParseLiteralMv( Io_MvMod_t * p, Abc_Obj_t * pNode, char * pToken, Vec_Str_t * vFunc, int iLit ) { - char Buffer[10]; + char Buffer[16]; Io_MvVar_t * pVar; Abc_Obj_t * pFanin, * pNet; char * pCur, * pNext; diff --git a/src/base/io/ioUtil.c b/src/base/io/ioUtil.c index c6b47b11..ddfcc91a 100644 --- a/src/base/io/ioUtil.c +++ b/src/base/io/ioUtil.c @@ -862,6 +862,62 @@ FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mo } } +/**Function************************************************************* + + Synopsis [Tranform SF into PLA.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_TransformSF2PLA( char * pNameIn, char * pNameOut ) +{ + int fStart = 0, Size = 1000000; + char * pBuffer, * pToken; + FILE * pFileIn = fopen( pNameIn, "rb" ); + FILE * pFileOut = fopen( pNameOut, "wb" ); + if ( pFileIn == NULL ) + { + if ( pFileOut ) fclose( pFileOut ); + printf( "Cannot open file \"%s\" for reading.\n", pNameIn ); + return; + } + if ( pFileOut == NULL ) + { + if ( pFileIn ) fclose( pFileIn ); + printf( "Cannot open file \"%s\" for reading.\n", pNameOut ); + return; + } + pBuffer = ABC_ALLOC( char, Size ); + fprintf( pFileOut, ".type fd\n" ); + while ( fgets(pBuffer, Size, pFileIn) ) + { + if ( strstr(pBuffer, "END_SDF") ) + break; + if ( strstr(pBuffer, "SDF") ) + { + char * pRes = fgets(pBuffer, Size, pFileIn); + assert( pRes != NULL ); + if ( (pToken = strtok( pBuffer, " \t\r\n" )) ) + fprintf( pFileOut, ".i %d\n", atoi(pToken) ); + if ( (pToken = strtok( NULL, " \t\r\n" )) ) + fprintf( pFileOut, ".o %d\n", atoi(pToken) ); + if ( (pToken = strtok( NULL, " \t\r\n" )) ) + fprintf( pFileOut, ".p %d\n", atoi(pToken) ); + fStart = 1; + } + else if ( fStart ) + fprintf( pFileOut, "%s", pBuffer ); + } + fprintf( pFileOut, ".e\n" ); + fclose( pFileIn ); + fclose( pFileOut ); + ABC_FREE( pBuffer ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/io/ioWriteBench.c b/src/base/io/ioWriteBench.c index 81d64582..23de719e 100644 --- a/src/base/io/ioWriteBench.c +++ b/src/base/io/ioWriteBench.c @@ -259,7 +259,7 @@ int Io_WriteBenchLutOneNode( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vTruth int i, nFanins; assert( Abc_ObjIsNode(pNode) ); nFanins = Abc_ObjFaninNum(pNode); - assert( nFanins <= 8 ); + assert( nFanins <= 15 ); // compute the truth table pTruth = Hop_ManConvertAigToTruth( (Hop_Man_t *)pNode->pNtk->pManFunc, Hop_Regular((Hop_Obj_t *)pNode->pData), nFanins, vTruth, 0 ); if ( Hop_IsComplement((Hop_Obj_t *)pNode->pData) ) diff --git a/src/base/io/ioWriteDot.c b/src/base/io/ioWriteDot.c index d9687c6e..0ab3c4d2 100644 --- a/src/base/io/ioWriteDot.c +++ b/src/base/io/ioWriteDot.c @@ -100,7 +100,7 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho // transform logic functions from BDD to SOP if ( (fHasBdds = Abc_NtkIsBddLogic(pNtk)) ) { - if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY) ) + if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY, 1) ) { printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" ); return; @@ -463,7 +463,7 @@ void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho // transform logic functions from BDD to SOP if ( (fHasBdds = Abc_NtkIsBddLogic(pNtk)) ) { - if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY) ) + if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY, 1) ) { printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" ); return; diff --git a/src/base/io/ioWriteVerilog.c b/src/base/io/ioWriteVerilog.c index 2e481324..e05aed2e 100644 --- a/src/base/io/ioWriteVerilog.c +++ b/src/base/io/ioWriteVerilog.c @@ -567,6 +567,14 @@ void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk, int fOnlyAnds ) Hop_IthVar((Hop_Man_t *)pNtk->pManFunc, k)->pData = Extra_UtilStrsav(Io_WriteVerilogGetName(Abc_ObjName(pFanin))); // write the formula Hop_ObjPrintVerilog( pFile, pFunc, vLevels, 0, fOnlyAnds ); + if ( pObj->fPersist ) + { + Abc_Obj_t * pFan0 = Abc_ObjFanin0(Abc_ObjFanin(pObj, 0)); + Abc_Obj_t * pFan1 = Abc_ObjFanin0(Abc_ObjFanin(pObj, 1)); + int Cond = Abc_ObjIsNode(pFan0) && Abc_ObjIsNode(pFan1) && !pFan0->fPersist && !pFan1->fPersist; + fprintf( pFile, "; // MUXF7 %s\n", Cond ? "":"to be legalized" ); + } + else fprintf( pFile, ";\n" ); // clear the input names Abc_ObjForEachFanin( pObj, pFanin, k ) @@ -631,10 +639,8 @@ int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk ) char * Io_WriteVerilogGetName( char * pName ) { static char Buffer[500]; - int Length, i; - Length = strlen(pName); - // consider the case of a signal having name "0" or "1" - if ( !(Length == 1 && (pName[0] == '0' || pName[0] == '1')) ) + int i, Length = strlen(pName); + if ( pName[0] < '0' || pName[0] > '9' ) { for ( i = 0; i < Length; i++ ) if ( !((pName[i] >= 'a' && pName[i] <= 'z') || @@ -653,6 +659,248 @@ char * Io_WriteVerilogGetName( char * pName ) return Buffer; } + +/**Function************************************************************* + + Synopsis [Write the network of K-input LUTs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteLutModule( FILE * pFile, int nLutSize ) +{ + fprintf( pFile, "module lut%d #( parameter TT = %d\'h0 ) ( input [%d:0] in, output out );\n", nLutSize, 1<<nLutSize, nLutSize-1 ); + fprintf( pFile, " assign out = TT[in];\n" ); + fprintf( pFile, "endmodule\n\n" ); +} +void Io_WriteFixedModules( FILE * pFile ) +{ + fprintf( pFile, "module LUT6 #( parameter INIT = 64\'h0000000000000000 ) (\n" ); + fprintf( pFile, " output O,\n" ); + fprintf( pFile, " input I0,\n" ); + fprintf( pFile, " input I1,\n" ); + fprintf( pFile, " input I2,\n" ); + fprintf( pFile, " input I3,\n" ); + fprintf( pFile, " input I4,\n" ); + fprintf( pFile, " input I5\n" ); + fprintf( pFile, ");\n" ); + fprintf( pFile, " assign O = INIT[ {I5, I4, I3, I2, I1, I0} ];\n" ); + fprintf( pFile, "endmodule\n\n" ); + + fprintf( pFile, "module MUXF7 (\n" ); + fprintf( pFile, " output O,\n" ); + fprintf( pFile, " input I0,\n" ); + fprintf( pFile, " input I1,\n" ); + fprintf( pFile, " input S\n" ); + fprintf( pFile, ");\n" ); + fprintf( pFile, " assign O = S ? I1 : I0;\n" ); + fprintf( pFile, "endmodule\n\n" ); + + fprintf( pFile, "module MUXF8 (\n" ); + fprintf( pFile, " output O,\n" ); + fprintf( pFile, " input I0,\n" ); + fprintf( pFile, " input I1,\n" ); + fprintf( pFile, " input S\n" ); + fprintf( pFile, ");\n" ); + fprintf( pFile, " assign O = S ? I1 : I0;\n" ); + fprintf( pFile, "endmodule\n\n" ); +} +void Io_WriteVerilogObjectsLut( FILE * pFile, Abc_Ntk_t * pNtk, int nLutSize, int fFixed ) +{ + Abc_Ntk_t * pNtkBox; + Abc_Obj_t * pObj, * pTerm; + int i, k, Counter, nDigits, Length = 0; + + // write boxes + nDigits = Abc_Base10Log( Abc_NtkBoxNum(pNtk)-Abc_NtkLatchNum(pNtk) ); + Counter = 0; + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + pNtkBox = (Abc_Ntk_t *)pObj->pData; + fprintf( pFile, " %s box%0*d", pNtkBox->pName, nDigits, Counter++ ); + fprintf( pFile, "(" ); + Abc_NtkForEachPi( pNtkBox, pTerm, k ) + { + fprintf( pFile, ".%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pTerm))) ); + fprintf( pFile, "(%s), ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin(pObj,k)))) ); + } + Abc_NtkForEachPo( pNtkBox, pTerm, k ) + { + fprintf( pFile, ".%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(pTerm))) ); + fprintf( pFile, "(%s)%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout(pObj,k)))), k==Abc_NtkPoNum(pNtkBox)-1? "":", " ); + } + fprintf( pFile, ");\n" ); + } + + // find the longest signal name + Abc_NtkForEachNode( pNtk, pObj, i ) + { + Length = Abc_MaxInt( Length, strlen(Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj)))) ); + Abc_ObjForEachFanin( pObj, pTerm, k ) + Length = Abc_MaxInt( Length, strlen(Io_WriteVerilogGetName(Abc_ObjName(pTerm))) ); + } + + // write LUT instances + nDigits = Abc_Base10Log( Abc_NtkNodeNum(pNtk) ); + Counter = 0; + if ( fFixed ) + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( pObj->fPersist ) + { + int One = Abc_ObjFanin0(Abc_ObjFanin(pObj, 1))->fPersist && Abc_ObjFanin0(Abc_ObjFanin(pObj, 2))->fPersist; + fprintf( pFile, " MUXF%d ", 7+One ); + fprintf( pFile, " mux_%0*d (", nDigits, Counter++ ); + fprintf( pFile, " %*s", Length, Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj))) ); + for ( k = Abc_ObjFaninNum(pObj) - 1; k >= 0; k-- ) + fprintf( pFile, ", %*s", Length, Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin(pObj, k))) ); + fprintf( pFile, " );\n" ); + } + else + { + word Truth = Abc_SopToTruth( (char *)pObj->pData, Abc_ObjFaninNum(pObj) ); + fprintf( pFile, " LUT6 #(64\'h" ); + fprintf( pFile, "%08x%08x", (unsigned)(Truth >> 32), (unsigned)Truth ); + fprintf( pFile, ") lut_%0*d (", nDigits, Counter++ ); + fprintf( pFile, " %*s", Length, Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj))) ); + for ( k = 0; k < Abc_ObjFaninNum(pObj); k++ ) + fprintf( pFile, ", %*s", Length, Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin(pObj, k))) ); + for ( ; k < 6; k++ ) + fprintf( pFile, ", %*s", Length, "1\'b0" ); + fprintf( pFile, " );\n" ); + } + } + else + Abc_NtkForEachNode( pNtk, pObj, i ) + { + word Truth = Abc_SopToTruth( (char *)pObj->pData, Abc_ObjFaninNum(pObj) ); + fprintf( pFile, " lut%d #(%d\'h", nLutSize, 1<<nLutSize ); + if ( nLutSize == 6 ) + fprintf( pFile, "%08x%08x", (unsigned)(Truth >> 32), (unsigned)Truth ); + else + fprintf( pFile, "%0*x", 1<<(nLutSize-2), Abc_InfoMask(1 << nLutSize) & (unsigned)Truth ); + fprintf( pFile, ") lut_%0*d ( {", nDigits, Counter++ ); + for ( k = nLutSize - 1; k >= Abc_ObjFaninNum(pObj); k-- ) + fprintf( pFile, "%*s, ", Length, "1\'b0" ); + for ( k = Abc_ObjFaninNum(pObj) - 1; k >= 0; k-- ) + fprintf( pFile, "%*s%s", Length, Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin(pObj, k))), k==0 ? "":", " ); + fprintf( pFile, "}, %*s );\n", Length, Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj))) ); + } +} +void Io_WriteVerilogLutInt( FILE * pFile, Abc_Ntk_t * pNtk, int nLutSize, int fFixed ) +{ + // write inputs and outputs +// fprintf( pFile, "module %s ( gclk,\n ", Abc_NtkName(pNtk) ); + fprintf( pFile, "module %s ( ", Io_WriteVerilogGetName(Abc_NtkName(pNtk)) ); + // add the clock signal if it does not exist + if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 ) + fprintf( pFile, "clock, " ); + // write other primary inputs + fprintf( pFile, "\n " ); + if ( Abc_NtkPiNum(pNtk) > 0 ) + { + Io_WriteVerilogPis( pFile, pNtk, 3 ); + fprintf( pFile, ",\n " ); + } + if ( Abc_NtkPoNum(pNtk) > 0 ) + Io_WriteVerilogPos( pFile, pNtk, 3 ); + fprintf( pFile, " );\n\n" ); + // add the clock signal if it does not exist + if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 ) + fprintf( pFile, " input clock;\n" ); + // write inputs, outputs, registers, and wires + if ( Abc_NtkPiNum(pNtk) > 0 ) + { +// fprintf( pFile, " input gclk," ); + fprintf( pFile, " input " ); + Io_WriteVerilogPis( pFile, pNtk, 10 ); + fprintf( pFile, ";\n" ); + } + if ( Abc_NtkPoNum(pNtk) > 0 ) + { + fprintf( pFile, " output" ); + Io_WriteVerilogPos( pFile, pNtk, 5 ); + fprintf( pFile, ";\n\n" ); + } + // if this is not a blackbox, write internal signals + if ( !Abc_NtkHasBlackbox(pNtk) ) + { + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + fprintf( pFile, " reg" ); + Io_WriteVerilogRegs( pFile, pNtk, 4 ); + fprintf( pFile, ";\n\n" ); + } + if ( Io_WriteVerilogWiresCount(pNtk) > 0 ) + { + fprintf( pFile, " wire" ); + Io_WriteVerilogWires( pFile, pNtk, 4 ); + fprintf( pFile, ";\n\n" ); + } + // write nodes + Io_WriteVerilogObjectsLut( pFile, pNtk, nLutSize, fFixed ); + // write registers + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + fprintf( pFile, "\n" ); + Io_WriteVerilogLatches( pFile, pNtk ); + } + } + // finalize the file + fprintf( pFile, "\nendmodule\n\n" ); +} +void Io_WriteVerilogLut( Abc_Ntk_t * pNtk, char * pFileName, int nLutSize, int fFixed, int fNoModules ) +{ + FILE * pFile; + Abc_Ntk_t * pNtkTemp; + Abc_Obj_t * pObj; + int i, Counter = 0; + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( Abc_ObjFaninNum(pObj) > nLutSize ) + { + if ( Counter < 3 ) + printf( "Node \"%s\" has the fanin count (%d) larger than the LUT size (%d).\n", Abc_ObjName(pObj), Abc_ObjFaninNum(pObj), nLutSize ); + Counter++; + } + if ( Counter ) + { + printf( "In total, %d internal logic nodes exceed the fanin count limit. Verilog is not written.\n", Counter ); + return; + } + + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteVerilog(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + + // write the equations for the network + fprintf( pFile, "// Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + fprintf( pFile, "\n" ); + if ( !fNoModules ) + { + if ( fFixed ) + Io_WriteFixedModules( pFile ); + else + Io_WriteLutModule( pFile, nLutSize ); + } + pNtkTemp = Abc_NtkToNetlist( pNtk ); + Abc_NtkToSop( pNtkTemp, -1, ABC_INFINITY ); + Io_WriteVerilogLutInt( pFile, pNtkTemp, nLutSize, fFixed ); + Abc_NtkDelete( pNtkTemp ); + + fprintf( pFile, "\n" ); + fclose( pFile ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/main/abcapis.h b/src/base/main/abcapis.h index e384896d..d34306ba 100644 --- a/src/base/main/abcapis.h +++ b/src/base/main/abcapis.h @@ -78,8 +78,11 @@ extern ABC_DLL void Abc_NtkSetFlopNum( Abc_Frame_t * pAbc, int nFlops ); // procedures to input/output 'mini LUT' extern ABC_DLL void Abc_FrameGiaInputMiniLut( Abc_Frame_t * pAbc, void * pMiniLut ); +extern ABC_DLL void Abc_FrameGiaInputMiniLut2( Abc_Frame_t * pAbc, void * pMiniLut ); extern ABC_DLL void * Abc_FrameGiaOutputMiniLut( Abc_Frame_t * pAbc ); extern ABC_DLL char * Abc_FrameGiaOutputMiniLutAttr( Abc_Frame_t * pAbc, void * pMiniLut ); +extern ABC_DLL int * Abc_FrameReadMiniLutSwitching( Abc_Frame_t * pAbc ); +extern ABC_DLL int * Abc_FrameReadMiniLutSwitchingPo( Abc_Frame_t * pAbc ); // procedures to input/output NDR data-structure extern ABC_DLL void Abc_FrameInputNdr( Abc_Frame_t * pAbc, void * pData ); diff --git a/src/base/main/main.h b/src/base/main/main.h index 2efb3358..f3457e27 100644 --- a/src/base/main/main.h +++ b/src/base/main/main.h @@ -105,10 +105,13 @@ extern ABC_DLL void * Abc_FrameReadManDd(); extern ABC_DLL void * Abc_FrameReadManDec(); extern ABC_DLL void * Abc_FrameReadManDsd(); extern ABC_DLL void * Abc_FrameReadManDsd2(); +extern ABC_DLL Vec_Ptr_t * Abc_FrameReadSignalNames(); +extern ABC_DLL char * Abc_FrameReadSpecName(); extern ABC_DLL char * Abc_FrameReadFlag( char * pFlag ); extern ABC_DLL int Abc_FrameIsFlagEnabled( char * pFlag ); extern ABC_DLL int Abc_FrameIsBatchMode(); +extern ABC_DLL void Abc_FrameSetBatchMode( int Mode ); extern ABC_DLL int Abc_FrameIsBridgeMode(); extern ABC_DLL void Abc_FrameSetBridgeMode(); @@ -147,6 +150,8 @@ extern ABC_DLL void Abc_FrameSetCnf( Vec_Int_t * vInv ); extern ABC_DLL void Abc_FrameSetStr( Vec_Str_t * vInv ); extern ABC_DLL void Abc_FrameSetJsonStrs( Abc_Nam_t * pStrs ); extern ABC_DLL void Abc_FrameSetJsonObjs( Vec_Wec_t * vObjs ); +extern ABC_DLL void Abc_FrameSetSignalNames( Vec_Ptr_t * vNames ); +extern ABC_DLL void Abc_FrameSetSpecName( char * pFileName ); extern ABC_DLL int Abc_FrameCheckPoConst( Abc_Frame_t * p, int iPoNum ); diff --git a/src/base/main/mainFrame.c b/src/base/main/mainFrame.c index 1d54f4e4..ba41d4c1 100644 --- a/src/base/main/mainFrame.c +++ b/src/base/main/mainFrame.c @@ -67,6 +67,8 @@ void * Abc_FrameReadManDec() { if ( s_GlobalFram void * Abc_FrameReadManDsd() { return s_GlobalFrame->pManDsd; } void * Abc_FrameReadManDsd2() { return s_GlobalFrame->pManDsd2; } char * Abc_FrameReadFlag( char * pFlag ) { return Cmd_FlagReadByName( s_GlobalFrame, pFlag ); } +Vec_Ptr_t * Abc_FrameReadSignalNames() { return s_GlobalFrame->vSignalNames; } +char * Abc_FrameReadSpecName() { return s_GlobalFrame->pSpecName; } int Abc_FrameReadBmcFrames( Abc_Frame_t * p ) { return s_GlobalFrame->nFrames; } int Abc_FrameReadProbStatus( Abc_Frame_t * p ) { return s_GlobalFrame->Status; } @@ -102,8 +104,11 @@ void Abc_FrameSetManDsd2( void * pMan ) { if (s_GlobalFrame void Abc_FrameSetInv( Vec_Int_t * vInv ) { Vec_IntFreeP(&s_GlobalFrame->pAbcWlcInv); s_GlobalFrame->pAbcWlcInv = vInv; } void Abc_FrameSetJsonStrs( Abc_Nam_t * pStrs ) { Abc_NamDeref( s_GlobalFrame->pJsonStrs ); s_GlobalFrame->pJsonStrs = pStrs; } void Abc_FrameSetJsonObjs( Vec_Wec_t * vObjs ) { Vec_WecFreeP(&s_GlobalFrame->vJsonObjs ); s_GlobalFrame->vJsonObjs = vObjs; } +void Abc_FrameSetSignalNames( Vec_Ptr_t * vNames ) { if ( s_GlobalFrame->vSignalNames ) Vec_PtrFreeFree( s_GlobalFrame->vSignalNames ); s_GlobalFrame->vSignalNames = vNames; } +void Abc_FrameSetSpecName( char * pFileName ) { ABC_FREE( s_GlobalFrame->pSpecName ); s_GlobalFrame->pSpecName = pFileName; } int Abc_FrameIsBatchMode() { return s_GlobalFrame ? s_GlobalFrame->fBatchMode : 0; } +void Abc_FrameSetBatchMode( int Mode ) { if ( s_GlobalFrame ) s_GlobalFrame->fBatchMode = Mode; } int Abc_FrameIsBridgeMode() { return s_GlobalFrame ? s_GlobalFrame->fBridgeMode : 0; } void Abc_FrameSetBridgeMode() { if ( s_GlobalFrame ) s_GlobalFrame->fBridgeMode = 1; } @@ -231,6 +236,9 @@ void Abc_FrameDeallocate( Abc_Frame_t * p ) } Vec_IntFreeP( &p->vIndFlops ); Vec_PtrFreeP( &p->vLTLProperties_global ); + if ( p->vSignalNames ) + Vec_PtrFreeFree( p->vSignalNames ); + ABC_FREE( p->pSpecName ); Abc_FrameDeleteAllNetworks( p ); ABC_FREE( p->pDrivingCell ); ABC_FREE( p->pCex2 ); diff --git a/src/base/main/mainInit.c b/src/base/main/mainInit.c index d85d7b67..693cea90 100644 --- a/src/base/main/mainInit.c +++ b/src/base/main/mainInit.c @@ -65,6 +65,8 @@ extern void Abc85_Init( Abc_Frame_t * pAbc ); extern void Abc85_End( Abc_Frame_t * pAbc ); extern void Glucose_Init( Abc_Frame_t *pAbc ); extern void Glucose_End( Abc_Frame_t * pAbc ); +extern void Glucose2_Init( Abc_Frame_t *pAbc ); +extern void Glucose2_End( Abc_Frame_t * pAbc ); static Abc_FrameInitializer_t* s_InitializerStart = NULL; static Abc_FrameInitializer_t* s_InitializerEnd = NULL; @@ -117,9 +119,9 @@ void Abc_FrameInit( Abc_Frame_t * pAbc ) Bac_Init( pAbc ); Cba_Init( pAbc ); Pla_Init( pAbc ); - Sim_Init( pAbc ); Test_Init( pAbc ); Glucose_Init( pAbc ); + Glucose2_Init( pAbc ); for( p = s_InitializerStart ; p ; p = p->next ) if(p->init) p->init(pAbc); @@ -157,7 +159,6 @@ void Abc_FrameEnd( Abc_Frame_t * pAbc ) Bac_End( pAbc ); Cba_End( pAbc ); Pla_End( pAbc ); - Sim_End( pAbc ); Test_End( pAbc ); Glucose_End( pAbc ); } diff --git a/src/base/main/mainInt.h b/src/base/main/mainInt.h index bc57ad2a..e860878e 100644 --- a/src/base/main/mainInt.h +++ b/src/base/main/mainInt.h @@ -133,6 +133,8 @@ struct Abc_Frame_t_ int nFrames; // the number of time frames completed by BMC Vec_Ptr_t * vPlugInComBinPairs; // pairs of command and its binary name Vec_Ptr_t * vLTLProperties_global; // related to LTL + Vec_Ptr_t * vSignalNames; // temporary storage for signal names + char * pSpecName; void * pSave1; void * pSave2; void * pSave3; diff --git a/src/base/main/mainUtils.c b/src/base/main/mainUtils.c index d1fe1d20..377299fd 100644 --- a/src/base/main/mainUtils.c +++ b/src/base/main/mainUtils.c @@ -52,7 +52,14 @@ static char * DateReadFromDateString( char * datestr ); char * Abc_UtilsGetVersion( Abc_Frame_t * pAbc ) { static char Version[1000]; +#if __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdate-time" +#endif sprintf(Version, "%s (compiled %s %s)", ABC_VERSION, __DATE__, __TIME__); +#if __GNUC__ + #pragma GCC diagnostic pop +#endif return Version; } diff --git a/src/base/wlc/wlc.c b/src/base/wlc/wlc.c index 6f0890e2..261ec96b 100644 --- a/src/base/wlc/wlc.c +++ b/src/base/wlc/wlc.c @@ -265,6 +265,446 @@ void Wlc_BlastMultiplierCnfTest( int nBits ) sat_solver_delete( pSat ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Wlc_ManGenAdderN( Gia_Man_t * p, int nLits, int * pLitsA, int * pLitsB, int Carry ) +{ + extern void Wlc_BlastFullAdder( Gia_Man_t * pNew, int a, int b, int c, int * pc, int * ps ); + Vec_Int_t * vRes = Vec_IntStart( nLits + 1 ); + int i, * pRes = Vec_IntArray(vRes); + for ( i = 0; i < nLits; i++ ) + Wlc_BlastFullAdder( p, pLitsA[i], pLitsB[i], Carry, &Carry, &pRes[i] ); + pRes[nLits] = Carry; + return vRes; +} +Vec_Int_t * Wlc_ManGenAdder2_rec( Gia_Man_t * p, int nLits, int * pLitsA, int * pLitsB, int Carry, int Size ) +{ + Vec_Int_t * vRes, * vRes0, * vRes1, * vRes2; int i, iCtrl; + if ( nLits == Size ) + return Wlc_ManGenAdderN( p, nLits, pLitsA, pLitsB, Carry ); + vRes0 = Wlc_ManGenAdder2_rec( p, nLits/2, pLitsA, pLitsB, Carry, Size ); + vRes1 = Wlc_ManGenAdder2_rec( p, nLits/2, pLitsA + nLits/2, pLitsB + nLits/2, 0, Size ); + vRes2 = Wlc_ManGenAdder2_rec( p, nLits/2, pLitsA + nLits/2, pLitsB + nLits/2, 1, Size ); + vRes = Vec_IntAlloc( nLits + 1 ); + Vec_IntAppend( vRes, vRes0 ); + iCtrl = Vec_IntPop( vRes ); + for ( i = 0; i <= nLits/2; i++ ) + Vec_IntPush( vRes, Gia_ManHashMux(p, iCtrl, Vec_IntEntry(vRes2, i), Vec_IntEntry(vRes1, i)) ); + assert( Vec_IntSize(vRes) == nLits + 1 ); + Vec_IntFree( vRes0 ); + Vec_IntFree( vRes1 ); + Vec_IntFree( vRes2 ); + return vRes; +} +Gia_Man_t * Wlc_ManGenAdder2( int nBits, int Size, int fSigned ) +{ + Gia_Man_t * pTemp, * pNew; int n, i, iLit, nBitsAll; + Vec_Int_t * vOuts, * vLits = Vec_IntAlloc( 1000 ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "adder" ); + for ( nBitsAll = Size; nBitsAll < nBits; nBitsAll *= 2 ) + ; + for ( n = 0; n < 2; n++ ) + { + for ( i = 0; i < nBits; i++ ) + Vec_IntPush( vLits, Gia_ManAppendCi(pNew) ); + for ( ; i < nBitsAll; i++ ) + Vec_IntPush( vLits, fSigned ? Vec_IntEntry(vLits, nBits-1) : 0 ); + } + Gia_ManHashAlloc( pNew ); + vOuts = Wlc_ManGenAdder2_rec( pNew, nBitsAll, Vec_IntEntryP(vLits, 0), Vec_IntEntryP(vLits, Vec_IntSize(vLits)/2), 0, Size ); + Gia_ManHashStop( pNew ); + Vec_IntForEachEntry( vOuts, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + Vec_IntFree( vLits ); + Vec_IntFree( vOuts ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +Vec_Int_t * Wlc_ManGenAdder_rec( Gia_Man_t * p, int nLits, int * pLitsA, int * pLitsB, int Carry, int Size ) +{ + Vec_Int_t * vRes, * vRes0, * vRes1, * vRes2, * vRes3, * vRes4; int i, iCtrl; + if ( nLits == Size ) + return Wlc_ManGenAdderN( p, nLits, pLitsA, pLitsB, Carry ); + assert( nLits % 3 == 0 ); + vRes0 = Wlc_ManGenAdder_rec( p, nLits/3, pLitsA + 0*nLits/3, pLitsB + 0*nLits/3, Carry, Size ); + vRes1 = Wlc_ManGenAdder_rec( p, nLits/3, pLitsA + 1*nLits/3, pLitsB + 1*nLits/3, 0, Size ); + vRes2 = Wlc_ManGenAdder_rec( p, nLits/3, pLitsA + 1*nLits/3, pLitsB + 1*nLits/3, 1, Size ); + vRes3 = Wlc_ManGenAdder_rec( p, nLits/3, pLitsA + 2*nLits/3, pLitsB + 2*nLits/3, 0, Size ); + vRes4 = Wlc_ManGenAdder_rec( p, nLits/3, pLitsA + 2*nLits/3, pLitsB + 2*nLits/3, 1, Size ); + vRes = Vec_IntAlloc( nLits + 1 ); + Vec_IntAppend( vRes, vRes0 ); + iCtrl = Vec_IntPop( vRes ); + for ( i = 0; i <= nLits/3; i++ ) + Vec_IntPush( vRes, Gia_ManHashMux(p, iCtrl, Vec_IntEntry(vRes2, i), Vec_IntEntry(vRes1, i)) ); + iCtrl = Vec_IntPop( vRes ); + for ( i = 0; i <= nLits/3; i++ ) + Vec_IntPush( vRes, Gia_ManHashMux(p, iCtrl, Vec_IntEntry(vRes4, i), Vec_IntEntry(vRes3, i)) ); + assert( Vec_IntSize(vRes) == nLits + 1 ); + Vec_IntFree( vRes0 ); + Vec_IntFree( vRes1 ); + Vec_IntFree( vRes2 ); + Vec_IntFree( vRes3 ); + Vec_IntFree( vRes4 ); + return vRes; +} +Gia_Man_t * Wlc_ManGenAdder( int nBits ) +{ + Gia_Man_t * pTemp, * pNew; int n, i, iLit, nBitsAll; + Vec_Int_t * vOuts, * vLits = Vec_IntAlloc( 1000 ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "adder" ); + for ( nBitsAll = 3; nBitsAll < nBits; nBitsAll *= 3 ) + ; + for ( n = 0; n < 2; n++ ) + { + for ( i = 0; i < nBits; i++ ) + Vec_IntPush( vLits, Gia_ManAppendCi(pNew) ); + for ( ; i < nBitsAll; i++ ) + Vec_IntPush( vLits, 0 ); + } + Gia_ManHashAlloc( pNew ); + vOuts = Wlc_ManGenAdder_rec( pNew, nBitsAll, Vec_IntEntryP(vLits, 0), Vec_IntEntryP(vLits, Vec_IntSize(vLits)/2), 0, 3 ); + Gia_ManHashStop( pNew ); + Vec_IntForEachEntryStop( vOuts, iLit, i, nBits+1 ) + Gia_ManAppendCo( pNew, iLit ); + Vec_IntFree( vLits ); + Vec_IntFree( vOuts ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wlc_BuildOne32( Gia_Man_t * p, int * pLitIn, int * pLitOut ) +{ + Wlc_BlastFullAdder( p, pLitIn[0], pLitIn[1], pLitIn[2], &pLitIn[5], &pLitOut[0] ); + Wlc_BlastFullAdder( p, pLitIn[3], pLitIn[4], pLitIn[5], &pLitOut[2], &pLitOut[1] ); +} +void Wlc_BuildOne51( Gia_Man_t * p, int * pLitIn, int * pLitOut ) +{ + int Lit00, Lit01, Lit11; + Wlc_BlastFullAdder( p, pLitIn[0], pLitIn[1], pLitIn[2], &Lit01, &Lit00 ); + Wlc_BlastFullAdder( p, pLitIn[3], pLitIn[4], Lit00, &Lit11, &pLitOut[0] ); + Wlc_BlastFullAdder( p, pLitIn[5], Lit01, Lit11, &pLitOut[2], &pLitOut[1] ); +} +void Wlc_BuildOne6( Gia_Man_t * p, int * pLitIn, int Const1, int * pLitOut ) +{ + int Lit00, Lit01, Lit10, Lit11, Lit12; + Wlc_BlastFullAdder( p, pLitIn[0], pLitIn[1], pLitIn[2], &Lit01, &Lit00 ); + Wlc_BlastFullAdder( p, pLitIn[3], pLitIn[4], pLitIn[5], &Lit11, &Lit10 ); + Wlc_BlastFullAdder( p, Lit00, Lit10, Const1, &Lit12, &pLitOut[0] ); + Wlc_BlastFullAdder( p, Lit01, Lit11, Lit12, &pLitOut[2],&pLitOut[1] ); +} +Vec_Wec_t * Wlc_ManGenTree_iter( Gia_Man_t * p, Vec_Wec_t * vBits, int * pCounter ) +{ + Vec_Wec_t * vBitsNew = Vec_WecStart( Vec_WecSize(vBits) ); + int i, k, pLitsIn[16], pLitsOut[16], Count = 0, fSimple = Vec_WecMaxLevelSize(vBits) <= 3; + for ( i = 0; i < Vec_WecSize(vBits)-1; i++ ) + { + Vec_Int_t * vBits0 = Vec_WecEntry(vBits, i); + Vec_Int_t * vBits1 = Vec_WecEntry(vBits, i+1); + if ( fSimple ) + { + assert( Vec_IntSize(vBits0) <= 3 ); + for ( k = 0; Vec_IntSize(vBits0) > 0; k++ ) + pLitsIn[k] = Vec_IntPop( vBits0 ); + for ( ; k < 3; k++ ) + pLitsIn[k] = 0; + assert( k == 3 ); + Wlc_BlastFullAdder( p, pLitsIn[0], pLitsIn[1], pLitsIn[2], &pLitsOut[1], &pLitsOut[0] ); + Vec_WecPush( vBitsNew, i+0, pLitsOut[0] ); + Vec_WecPush( vBitsNew, i+1, pLitsOut[1] ); + Count += 2; + continue; + } + while ( Vec_IntSize(vBits0) >= 6 ) + { + for ( k = 0; k < 6; k++ ) + pLitsIn[k] = Vec_IntPop( vBits0 ); + assert( k == 6 ); + Wlc_BuildOne6( p, pLitsIn, 0, pLitsOut ); + Vec_WecPush( vBitsNew, i+0, pLitsOut[0] ); + Vec_WecPush( vBitsNew, i+1, pLitsOut[1] ); + Vec_WecPush( vBitsNew, i+2, pLitsOut[2] ); + Count += 3; + } + if ( Vec_IntSize(vBits0) == 5 && Vec_IntSize(vBits1) > 0 ) + { + for ( k = 0; Vec_IntSize(vBits0) > 0; k++ ) + pLitsIn[k] = Vec_IntPop( vBits0 ); + pLitsIn[k++] = Vec_IntPop( vBits1 ); + assert( k == 6 ); + Wlc_BuildOne51( p, pLitsIn, pLitsOut ); + Vec_WecPush( vBitsNew, i+0, pLitsOut[0] ); + Vec_WecPush( vBitsNew, i+1, pLitsOut[1] ); + Vec_WecPush( vBitsNew, i+2, pLitsOut[2] ); + Count += 3; + } + if ( Vec_IntSize(vBits0) == 5 && Vec_IntSize(vBits1) == 0 ) + { + for ( k = 0; Vec_IntSize(vBits0) > 0; k++ ) + pLitsIn[k] = Vec_IntPop( vBits0 ); + pLitsIn[k++] = 0; + assert( k == 6 ); + Wlc_BuildOne6( p, pLitsIn, 0, pLitsOut ); + Vec_WecPush( vBitsNew, i+0, pLitsOut[0] ); + Vec_WecPush( vBitsNew, i+1, pLitsOut[1] ); + Vec_WecPush( vBitsNew, i+2, pLitsOut[2] ); + Count += 3; + } + if ( Vec_IntSize(vBits0) == 4 && Vec_IntSize(vBits1) > 0 ) + { + for ( k = 0; Vec_IntSize(vBits0) > 0; k++ ) + pLitsIn[k] = Vec_IntPop( vBits0 ); + pLitsIn[k++] = 0; + pLitsIn[k++] = Vec_IntPop( vBits1 ); + assert( k == 6 ); + Wlc_BuildOne51( p, pLitsIn, pLitsOut ); + Vec_WecPush( vBitsNew, i+0, pLitsOut[0] ); + Vec_WecPush( vBitsNew, i+1, pLitsOut[1] ); + Vec_WecPush( vBitsNew, i+2, pLitsOut[2] ); + Count += 3; + } + if ( Vec_IntSize(vBits0) == 3 && Vec_IntSize(vBits1) >= 2 ) + { + for ( k = 0; Vec_IntSize(vBits0) > 0; k++ ) + pLitsIn[k] = Vec_IntPop( vBits0 ); + pLitsIn[k++] = Vec_IntPop( vBits1 ); + pLitsIn[k++] = Vec_IntPop( vBits1 ); + assert( k == 5 ); + Wlc_BuildOne32( p, pLitsIn, pLitsOut ); + Vec_WecPush( vBitsNew, i+0, pLitsOut[0] ); + Vec_WecPush( vBitsNew, i+1, pLitsOut[1] ); + Vec_WecPush( vBitsNew, i+2, pLitsOut[2] ); + Count += 3; + } + if ( Vec_IntSize(vBits0) >= 3 ) + { + for ( k = 0; k < 3; k++ ) + pLitsIn[k] = Vec_IntPop( vBits0 ); + assert( k == 3 ); + Wlc_BlastFullAdder( p, pLitsIn[0], pLitsIn[1], pLitsIn[2], &pLitsOut[1], &pLitsOut[0] ); + Vec_WecPush( vBitsNew, i+0, pLitsOut[0] ); + Vec_WecPush( vBitsNew, i+1, pLitsOut[1] ); + Count += 2; + } +/* + if ( Vec_IntSize(vBits0) == 2 ) + { + Vec_IntClear( vBits0 ); + Vec_WecPush( vBitsNew, i+0, 0 ); + Vec_WecPush( vBitsNew, i+1, 0 ); + Count += 2; + } +*/ + for ( k = 0; Vec_IntSize(vBits0) > 0; k++ ) + Vec_WecPush( vBitsNew, i, Vec_IntPop(vBits0) ); + } + if ( pCounter ) + *pCounter = Count; + return vBitsNew; +} +void Wlc_ManGenTreeOne( Gia_Man_t * pNew, Vec_Wec_t * vBits0, int fMult, int fVerbose ) +{ + extern int Wlc_BlastAdder( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int Carry ); // result is in pAdd0 + + Vec_Wec_t * vTemp, * vBits = Vec_WecDup( vBits0 ); + Vec_Int_t * vOuts = Vec_IntAlloc( 1000 ), * vOuts2; + Vec_Int_t * vLits0 = Vec_IntAlloc( 1000 ); + Vec_Int_t * vLits1 = Vec_IntAlloc( 1000 ); + int i, iLit, nBitsAll = 0, CounterAll = 0, Counter = 1; + for ( i = 0; Counter && i < 1000; i++ ) + { + if ( fVerbose ) printf( "LEVEL %d\n", i ); + if ( fVerbose ) Vec_WecPrint( vBits, 0 ); + if ( Vec_WecMaxLevelSize(vBits) <= 2 ) + break; + vBits = Wlc_ManGenTree_iter( pNew, vTemp = vBits, &Counter ); + Vec_WecFree( vTemp ); + CounterAll += Counter; + } + printf( "Total count = %d.\n", CounterAll ); + if ( !fMult ) + { + int Carry; +/* + Vec_WecForEachLevel( vBits, vOuts2, i ) + { + if ( i == 10 ) + break; + if ( i == 0 ) + { + assert( Vec_IntSize(vOuts2) == 1 ); + Vec_IntPush( vOuts, Vec_IntPop(vOuts2) ); + continue; + } + assert( Vec_IntSize(vOuts2) == 1 || Vec_IntSize(vOuts2) == 2 ); + Vec_IntPush( vLits0, Vec_IntPop(vOuts2) ); + if ( Vec_IntSize(vOuts2) == 1 ) + Vec_IntPush( vLits1, Vec_IntPop(vOuts2) ); + else + { + Vec_IntPush( vLits1, 0 ); + } + } + assert( Vec_IntSize(vLits0) == 9 ); + assert( Vec_IntSize(vLits1) == 9 ); +*/ + Vec_WecForEachLevel( vBits, vOuts2, i ) + { + if ( Vec_IntSize(vOuts2) == 0 ) + break; + assert( Vec_IntSize(vOuts2) == 1 || Vec_IntSize(vOuts2) == 2 ); + Vec_IntPush( vLits0, Vec_IntPop(vOuts2) ); + if ( Vec_IntSize(vOuts2) == 1 ) + Vec_IntPush( vLits1, Vec_IntPop(vOuts2) ); + else + Vec_IntPush( vLits1, 0 ); + } + printf( "The adder size is %d.\n", Vec_IntSize(vLits0) ); + Vec_IntShrink( vLits0, 11 ); + Vec_IntShrink( vLits1, 11 ); + +// vOuts2 = Wlc_ManGenAdder_rec( pNew, 9, Vec_IntArray(vLits0), Vec_IntArray(vLits1), 0, 3 ); +// Vec_IntAppend( vOuts, vOuts2 ); +// Vec_IntFree( vOuts2 ); + + Carry = Wlc_BlastAdder( pNew, Vec_IntArray(vLits0), Vec_IntArray(vLits1), 11, 0 ); + Vec_IntAppend( vOuts, vLits0 ); + Vec_IntPush( vOuts, Carry ); + + + Gia_ManAppendCo( pNew, Vec_IntEntry(vOuts, 11) ); + } + else + { + Vec_WecForEachLevel( vBits, vOuts2, i ) + { + if ( Vec_IntSize(vOuts2) == 0 ) + break; + assert( Vec_IntSize(vOuts2) == 1 || Vec_IntSize(vOuts2) == 2 ); + Vec_IntPush( vLits0, Vec_IntPop(vOuts2) ); + if ( Vec_IntSize(vOuts2) == 1 ) + Vec_IntPush( vLits1, Vec_IntPop(vOuts2) ); + else + Vec_IntPush( vLits1, 0 ); + } + printf( "The adder size is %d.\n", Vec_IntSize(vLits0) ); + Vec_IntShrink( vLits0, Gia_ManCiNum(pNew)+1 ); // mult + Vec_IntShrink( vLits1, Gia_ManCiNum(pNew)+1 ); // mult + + for ( nBitsAll = 3; nBitsAll < Vec_IntSize(vLits0); nBitsAll *= 3 ) + ; + for ( i = Vec_IntSize(vLits0); i < nBitsAll; i++ ) + { + Vec_IntPush( vLits0, 0 ); + Vec_IntPush( vLits1, 0 ); + } + assert( Vec_IntSize(vLits0) == nBitsAll ); + assert( Vec_IntSize(vLits1) == nBitsAll ); + + vOuts2 = Wlc_ManGenAdder_rec( pNew, nBitsAll, Vec_IntArray(vLits0), Vec_IntArray(vLits1), 0, 3 ); + Vec_IntAppend( vOuts, vOuts2 ); + Vec_IntFree( vOuts2 ); + //Carry = Wlc_BlastAdder( pNew, Vec_IntArray(vLits0), Vec_IntArray(vLits1), nBitsAll, 0 ); + //Vec_IntAppend( vOuts, vLits0 ); + //Vec_IntPush( vOuts, Carry ); + + Vec_IntShrink( vOuts, Gia_ManCiNum(pNew) ); // mult + //Vec_IntShrink( vOuts, Gia_ManCiNum(pNew)/2 ); + + Vec_IntForEachEntry( vOuts, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + } + + Vec_IntFree( vOuts ); + Vec_IntFree( vLits0 ); + Vec_IntFree( vLits1 ); + Vec_WecFree( vBits ); +} +Gia_Man_t * Wlc_ManGenTree( int nInputs, int Value, int nBits, int fVerbose ) +{ + Gia_Man_t * pTemp, * pNew; int i, Counter = 0; + Vec_Wec_t * vBits = Vec_WecStart( nBits+2 ); + for ( i = 0; i < nBits+2; i++ ) + Vec_WecPush( vBits, i, (Value >> i) & 1 ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "tree" ); + for ( i = 0; i < nInputs; i++ ) + Vec_WecPush( vBits, 0, Gia_ManAppendCi(pNew) ); + Gia_ManHashAlloc( pNew ); + Wlc_ManGenTreeOne( pNew, vBits, 0, fVerbose ); + Gia_ManHashStop( pNew ); + Vec_WecFree( vBits ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Wlc_ManGenProd( int nInputs, int fVerbose ) +{ + extern void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ); + extern void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ); + Vec_Int_t * vIns = Vec_IntAlloc( 2*nInputs ); + Gia_Man_t * pTemp, * pNew; + Vec_Wec_t * vProds; int i; + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "tree" ); + + for ( i = 0; i < 2*nInputs; i++ ) + Vec_IntPush( vIns, Gia_ManAppendCi(pNew) ); + //for ( i = 0; i < nInputs; i++ ) + // Vec_IntPush( vIns, Gia_ManAppendCi(pNew) ); + //for ( i = 0; i < nInputs; i++ ) + // Vec_IntPush( vIns, Vec_IntEntry(vIns, i) ); + + Gia_ManHashAlloc( pNew ); + Wlc_BlastBooth( pNew, Vec_IntArray(vIns), Vec_IntArray(vIns)+nInputs, nInputs, nInputs, NULL, 0, 0, &vProds ); + //Wlc_BlastMultiplier3( pNew, Vec_IntArray(vIns), Vec_IntArray(vIns)+nInputs, nInputs, nInputs, NULL, 0, 0, &vProds ); + //Vec_WecPrint( vProds, 0 ); + Wlc_ManGenTreeOne( pNew, vProds, 1, fVerbose ); + Gia_ManHashStop( pNew ); + Vec_WecFree( vProds ); + Vec_IntFree( vIns ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/wlc/wlc.h b/src/base/wlc/wlc.h index 0a4f745c..0b3bed6c 100644 --- a/src/base/wlc/wlc.h +++ b/src/base/wlc/wlc.h @@ -217,6 +217,7 @@ struct Wlc_BstPar_t_ int fBooth; int fNonRest; int fCla; + int fDivBy0; int fNoCleanup; int fCreateMiter; int fCreateWordMiter; @@ -238,6 +239,7 @@ static inline void Wlc_BstParDefault( Wlc_BstPar_t * pPar ) pPar->fMulti = 0; pPar->fBooth = 0; pPar->fCla = 0; + pPar->fDivBy0 = 0; pPar->fCreateMiter = 0; pPar->fCreateWordMiter = 0; pPar->fDecMuxes = 0; diff --git a/src/base/wlc/wlcAbc.c b/src/base/wlc/wlcAbc.c index e1b06ffd..8b7dbfa7 100644 --- a/src/base/wlc/wlcAbc.c +++ b/src/base/wlc/wlcAbc.c @@ -140,7 +140,7 @@ void Wlc_NtkPrintInvStats( Wlc_Ntk_t * pNtk, Vec_Int_t * vCounts, int fVerbose ) SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Wlc_NtkGetInv( Wlc_Ntk_t * pNtk, Vec_Int_t * vInv ) +Abc_Ntk_t * Wlc_NtkGetInv( Wlc_Ntk_t * pNtk, Vec_Int_t * vInv, Vec_Ptr_t * vNamesIn ) { extern Vec_Int_t * Pdr_InvCounts( Vec_Int_t * vInv ); extern Vec_Str_t * Pdr_InvPrintStr( Vec_Int_t * vInv, Vec_Int_t * vCounts ); @@ -166,8 +166,16 @@ Abc_Ntk_t * Wlc_NtkGetInv( Wlc_Ntk_t * pNtk, Vec_Int_t * vInv ) if ( Entry == 0 ) continue; pMainObj = Abc_NtkCreatePi( pMainNtk ); - sprintf( Buffer, "pi%d", i ); - Abc_ObjAssignName( pMainObj, Buffer, NULL ); + // If vNamesIn is given, take names from there for as many entries as possible + // otherwise generate names from counter + if (vNamesIn != NULL && i < Vec_PtrSize(vNamesIn)) { + Abc_ObjAssignName( pMainObj, (char *)Vec_PtrEntry(vNamesIn, i), NULL ); + } + else + { + sprintf( Buffer, "pi%d", i ); + Abc_ObjAssignName( pMainObj, Buffer, NULL ); + } } if ( Abc_NtkPiNum(pMainNtk) != nInputs ) { diff --git a/src/base/wlc/wlcAbs.c b/src/base/wlc/wlcAbs.c index 402ce21b..c297c54f 100644 --- a/src/base/wlc/wlcAbs.c +++ b/src/base/wlc/wlcAbs.c @@ -867,10 +867,10 @@ static Vec_Bit_t * Wlc_NtkMarkLimit( Wlc_Ntk_t * p, Wlc_Par_t * pPars ) } } - Vec_PtrSort( vAdds, (int (*)(void))IntPairPtrCompare ) ; - Vec_PtrSort( vMults, (int (*)(void))IntPairPtrCompare ) ; - Vec_PtrSort( vMuxes, (int (*)(void))IntPairPtrCompare ) ; - Vec_PtrSort( vFlops, (int (*)(void))IntPairPtrCompare ) ; + Vec_PtrSort( vAdds, (int (*)(const void *, const void *))IntPairPtrCompare ) ; + Vec_PtrSort( vMults, (int (*)(const void *, const void *))IntPairPtrCompare ) ; + Vec_PtrSort( vMuxes, (int (*)(const void *, const void *))IntPairPtrCompare ) ; + Vec_PtrSort( vFlops, (int (*)(const void *, const void *))IntPairPtrCompare ) ; Vec_PtrForEachEntry( Int_Pair_t *, vAdds, pPair, i ) { diff --git a/src/base/wlc/wlcBlast.c b/src/base/wlc/wlcBlast.c index 3a01e238..6e910cd8 100644 --- a/src/base/wlc/wlcBlast.c +++ b/src/base/wlc/wlcBlast.c @@ -345,11 +345,12 @@ void Wlc_BlastFullAdder( Gia_Man_t * pNew, int a, int b, int c, int * pc, int * if ( fCompl ) *ps = Abc_LitNot(*ps), *pc = Abc_LitNot(*pc); } -void Wlc_BlastAdder( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int Carry ) // result is in pAdd0 +int Wlc_BlastAdder( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int Carry ) // result is in pAdd0 { int b; for ( b = 0; b < nBits; b++ ) Wlc_BlastFullAdder( pNew, pAdd0[b], pAdd1[b], Carry, &Carry, &pAdd0[b] ); + return Carry; } void Wlc_BlastSubtract( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int Carry ) // result is in pAdd0 { @@ -1022,7 +1023,7 @@ void Wlc_BlastReduceMatrix2( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Int_t * v } -void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla ) +void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ) { Vec_Wec_t * vProds = Vec_WecStart( nArgA + nArgB ); Vec_Wec_t * vLevels = Vec_WecStart( nArgA + nArgB ); @@ -1043,7 +1044,10 @@ void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA Vec_WecPush( vLevels, nArgA+nArgB-1, 0 ); } - Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes, fSigned, fCla ); + if ( pvProds ) + *pvProds = Vec_WecDup(vProds); + else + Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes, fSigned, fCla ); // Wlc_BlastReduceMatrix2( pNew, vProds, vRes, fSigned, fCla ); Vec_WecFree( vProds ); @@ -1086,7 +1090,7 @@ void Wlc_BlastDecoder( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vTmp, Vec_IntPush( vRes, iMint ); } } -void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla ) +void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ) { Vec_Wec_t * vProds = Vec_WecStart( nArgA + nArgB + 3 ); Vec_Wec_t * vLevels = Vec_WecStart( nArgA + nArgB + 3 ); @@ -1159,9 +1163,11 @@ void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int //Vec_WecPrint( vProds, 0 ); //Wlc_BlastPrintMatrix( pNew, vProds, 1 ); //printf( "Cutoff ID for partial products = %d.\n", Gia_ManObjNum(pNew) ); - Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes, fSigned, fCla ); -// Wlc_BlastReduceMatrix2( pNew, vProds, vRes, fSigned, fCla ); - + if ( pvProds ) + *pvProds = Vec_WecDup(vProds); + else + Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes, fSigned, fCla ); + // Wlc_BlastReduceMatrix2( pNew, vProds, vRes, fSigned, fCla ); Vec_WecFree( vProds ); Vec_WecFree( vLevels ); Vec_IntFree( vArgB ); @@ -1792,9 +1798,9 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) if ( Wlc_NtkCountConstBits(pArg0, nRangeMax) < Wlc_NtkCountConstBits(pArg1, nRangeMax) ) ABC_SWAP( int *, pArg0, pArg1 ); if ( pPar->fBooth ) - Wlc_BlastBooth( pNew, pArg0, pArg1, nRange0, nRange1, vRes, fSigned, pPar->fCla ); + Wlc_BlastBooth( pNew, pArg0, pArg1, nRange0, nRange1, vRes, fSigned, pPar->fCla, NULL ); else if ( pPar->fCla ) - Wlc_BlastMultiplier3( pNew, pArg0, pArg1, nRange0, nRange1, vRes, Wlc_ObjIsSignedFanin01(p, pObj), pPar->fCla ); + Wlc_BlastMultiplier3( pNew, pArg0, pArg1, nRange0, nRange1, vRes, Wlc_ObjIsSignedFanin01(p, pObj), pPar->fCla, NULL ); else Wlc_BlastMultiplier( pNew, pArg0, pArg1, nRangeMax, nRangeMax, vTemp2, vRes, fSigned ); if ( nRange > Vec_IntSize(vRes) ) @@ -1815,7 +1821,7 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) else Wlc_BlastDivider( pNew, pArg0, nRangeMax, pArg1, nRangeMax, pObj->Type == WLC_OBJ_ARI_DIVIDE, vRes ); Vec_IntShrink( vRes, nRange ); - //if ( pObj->Type == WLC_OBJ_ARI_DIVIDE ) + if ( !pPar->fDivBy0 ) Wlc_BlastZeroCondition( pNew, pFans1, nRange1, vRes ); } else if ( pObj->Type == WLC_OBJ_ARI_MINUS ) @@ -2104,7 +2110,7 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) // complement flop inputs whose init state is 1 for ( i = 0; i < nFf2Regs; i++ ) Gia_ManAppendCo( pNew, Gia_ManAppendCi(pNew) ); - //Gia_ManSetRegNum( pNew, nFf2Regs ); + Gia_ManSetRegNum( pNew, nFf2Regs ); } else { @@ -2490,6 +2496,98 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) return pNew; } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float * Extra_FileReadFloat( FILE * pFile, int * pnFileSize ) +{ + float * pBuffer; + int RetValue, nFileSize; + fseek( pFile, 0, SEEK_END ); + nFileSize = *pnFileSize = ftell( pFile ); + rewind( pFile ); + assert( nFileSize%4 == 0 ); + pBuffer = ABC_CALLOC( float, nFileSize/4 ); + RetValue = fread( pBuffer, nFileSize, 1, pFile ); + return pBuffer; +} +float * Extra_FileReadFloatContents( char * pFileName, int * pnFileSize ) +{ + FILE * pFile; + float * pBuffer; + pFile = fopen( pFileName, "rb" ); + pBuffer = pFile ? Extra_FileReadFloat( pFile, pnFileSize ) : NULL; + if ( pFile ) fclose( pFile ); + return pBuffer; +} +static inline int Extra_FixedFound( int Value, int Fixed ) +{ + Value += 1 << (Fixed-1); + Value >>= Fixed; + return Value; +} +static inline int Extra_ConvertFloat8( float Value ) +{ + return Extra_FixedFound( (int)(Value * (1 << 16)), 8 ); +} +Gia_Man_t * Wlc_BlastArray( char * pFileName ) +{ + int nFileSize = 0; + float * pBuffer = Extra_FileReadFloatContents( pFileName, &nFileSize ); + int i, v, Value, nInputs = nFileSize/4 - 1; + Vec_Int_t * vArg0 = Vec_IntAlloc( 100 ); + Vec_Int_t * vArg1 = Vec_IntAlloc( 100 ); + Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + Vec_Int_t * vSum = Vec_IntAlloc( 100 ); + Gia_Man_t * pTemp, * pNew = Gia_ManStart( 10000 ); + pNew->pName = Abc_UtilStrsav( "blast" ); + Gia_ManHashAlloc( pNew ); + for ( i = 0; i < 8*nInputs; i++ ) + Gia_ManAppendCi(pNew); + + Value = (Extra_ConvertFloat8(pBuffer[0]) << 8) | (1 << 7); + for ( v = 0; v < 20; v++ ) + Vec_IntPush( vSum, (Value >> v) & 1 ); + + for ( i = 0; i < nInputs; i++ ) + { + Value = Extra_ConvertFloat8( pBuffer[1+i] ); + + Vec_IntClear( vArg0 ); + for ( v = 0; v < 8; v++ ) + Vec_IntPush( vArg0, Gia_ManCiLit(pNew, 8*i+v) ); + + Vec_IntClear( vArg1 ); + for ( v = 0; v < 12; v++ ) + Vec_IntPush( vArg1, (Value >> v) & 1 ); + + Wlc_BlastMultiplier( pNew, Vec_IntArray(vArg0), Vec_IntArray(vArg1), 8, 12, vTemp, vRes, 1 ); + Wlc_BlastAdder( pNew, Vec_IntArray(vSum), Vec_IntArray(vRes), 20, 0 ); + } + ABC_FREE( pBuffer ); + for ( v = 8; v < 16; v++ ) + Gia_ManAppendCo( pNew, Vec_IntEntry(vSum, v) ); + Vec_IntFree( vArg0 ); + Vec_IntFree( vArg1 ); + Vec_IntFree( vTemp ); + Vec_IntFree( vRes ); + Vec_IntFree( vSum ); + + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/wlc/wlcCom.c b/src/base/wlc/wlcCom.c index 51f15597..39f1bebd 100644 --- a/src/base/wlc/wlcCom.c +++ b/src/base/wlc/wlcCom.c @@ -1037,7 +1037,7 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) Wlc_BstParDefault( pPar ); pPar->nOutputRange = 2; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ORAMcombqadestnizvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "ORAMcombqaydestnizvh" ) ) != EOF ) { switch ( c ) { @@ -1103,6 +1103,9 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'a': pPar->fCla ^= 1; break; + case 'y': + pPar->fDivBy0 ^= 1; + break; case 'd': pPar->fCreateMiter ^= 1; break; @@ -1198,7 +1201,7 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_FrameUpdateGia( pAbc, pNew ); return 0; usage: - Abc_Print( -2, "usage: %%blast [-ORAM num] [-combqadestnizvh]\n" ); + Abc_Print( -2, "usage: %%blast [-ORAM num] [-combqaydestnizvh]\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", pPar->iOutput ); Abc_Print( -2, "\t-R num : the total number of word-level POs to bit-blast [default = %d]\n", pPar->nOutputRange ); @@ -1210,6 +1213,7 @@ usage: Abc_Print( -2, "\t-b : toggle generating radix-4 Booth multipliers [default = %s]\n", pPar->fBooth? "yes": "no" ); Abc_Print( -2, "\t-q : toggle generating non-restoring square root [default = %s]\n", pPar->fNonRest? "yes": "no" ); Abc_Print( -2, "\t-a : toggle generating carry-look-ahead adder [default = %s]\n", pPar->fCla? "yes": "no" ); + Abc_Print( -2, "\t-y : toggle creating different divide-by-0 condition [default = %s]\n", pPar->fDivBy0? "yes": "no" ); Abc_Print( -2, "\t-d : toggle creating dual-output multi-output miter [default = %s]\n", pPar->fCreateMiter? "yes": "no" ); Abc_Print( -2, "\t-e : toggle creating miter with output word bits combined [default = %s]\n", pPar->fCreateWordMiter? "yes": "no" ); Abc_Print( -2, "\t-s : toggle creating decoded MUXes [default = %s]\n", pPar->fDecMuxes? "yes": "no" ); @@ -1327,16 +1331,20 @@ usage: ******************************************************************************/ int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Wln_NtkRetimeTest( char * pFileName, int fSkipSimple, int fDump, int fVerbose ); + extern void Wln_NtkRetimeTest( char * pFileName, int fIgnoreIO, int fSkipSimple, int fDump, int fVerbose ); FILE * pFile; char * pFileName = NULL; + int fIgnoreIO = 0; int fSkipSimple = 0; int c, fDump = 0, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "sdvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "isdvh" ) ) != EOF ) { switch ( c ) { + case 'i': + fIgnoreIO ^= 1; + break; case 's': fSkipSimple ^= 1; break; @@ -1362,7 +1370,7 @@ int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) printf( "Transforming NDR into internal represnetation has failed.\n" ); return 0; } - vMoves = Wln_NtkRetime( pNtk, fSkipSimple, fVerbose ); + vMoves = Wln_NtkRetime( pNtk, fIgnoreIO, fSkipSimple, fVerbose ); Wln_NtkFree( pNtk ); ABC_FREE( pAbc->pNdrArray ); if ( vMoves ) pAbc->pNdrArray = Vec_IntReleaseNewArray( vMoves ); @@ -1385,11 +1393,12 @@ int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; } fclose( pFile ); - Wln_NtkRetimeTest( pFileName, fSkipSimple, fDump, fVerbose ); + Wln_NtkRetimeTest( pFileName, fIgnoreIO, fSkipSimple, fDump, fVerbose ); return 0; usage: - Abc_Print( -2, "usage: %%retime [-sdvh]\n" ); + Abc_Print( -2, "usage: %%retime [-isdvh]\n" ); Abc_Print( -2, "\t performs retiming for the NDR design\n" ); + Abc_Print( -2, "\t-i : toggle ignoring delays of IO paths [default = %s]\n", fIgnoreIO? "yes": "no" ); Abc_Print( -2, "\t-s : toggle printing simple nodes [default = %s]\n", !fSkipSimple? "yes": "no" ); Abc_Print( -2, "\t-d : toggle dumping the network in Verilog [default = %s]\n", fDump? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); @@ -1718,15 +1727,19 @@ usage: ******************************************************************************/ int Abc_CommandInvGet( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Abc_Ntk_t * Wlc_NtkGetInv( Wlc_Ntk_t * pNtk, Vec_Int_t * vInv ); + extern Abc_Ntk_t * Wlc_NtkGetInv( Wlc_Ntk_t * pNtk, Vec_Int_t * vInv, Vec_Ptr_t * vNamesIn ); Abc_Ntk_t * pMainNtk; Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc); - int c, fVerbose = 0; + int c, i, fVerbose = 0, fFlopNamesFromGia = 0; + Vec_Ptr_t * vNamesIn = NULL; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "fvh" ) ) != EOF ) { switch ( c ) { + case 'f': + fFlopNamesFromGia ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -1741,16 +1754,38 @@ int Abc_CommandInvGet( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( 1, "Abc_CommandInvGet(): Invariant is not available.\n" ); return 0; } + // See if we shall and can copy the PI names from the current GIA + if ( fFlopNamesFromGia ) + { + if ( pAbc->pGia == NULL ) + { + Abc_Print( 1, "Abc_CommandInvGet(): No network in &-space, cannot copy names.\n" ); + fFlopNamesFromGia = 0; + } + else + { + vNamesIn = Vec_PtrStart( Gia_ManRegNum(pAbc->pGia) ); + for ( i = 0; i < Gia_ManRegNum(pAbc->pGia); ++i ) + { + // Only the registers + Vec_PtrSetEntry( vNamesIn, i, Extra_UtilStrsav( (const char*)Vec_PtrEntry( pAbc->pGia->vNamesIn, Gia_ManPiNum(pAbc->pGia)+i ) ) ); + } + } + } // derive the network - pMainNtk = Wlc_NtkGetInv( pNtk, Wlc_AbcGetInv(pAbc) ); + pMainNtk = Wlc_NtkGetInv( pNtk, Wlc_AbcGetInv(pAbc), vNamesIn ); + // Delete names + if (vNamesIn) + Vec_PtrFree( vNamesIn ); // replace the current network if ( pMainNtk ) Abc_FrameReplaceCurrentNetwork( pAbc, pMainNtk ); return 0; usage: - Abc_Print( -2, "usage: inv_get [-vh]\n" ); + Abc_Print( -2, "usage: inv_get [-fvh]\n" ); Abc_Print( -2, "\t places invariant found by PDR as the current network in the main-space\n" ); - Abc_Print( -2, "\t (in the case of \'sat\' or \'undecided\', inifity clauses are used)\n" ); + Abc_Print( -2, "\t (in the case of \'sat\' or \'undecided\', infinity clauses are used)\n" ); + Abc_Print( -2, "\t-f : toggle reading flop names from the &-space [default = %s]\n", fFlopNamesFromGia? "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/wlcNdr.c b/src/base/wlc/wlcNdr.c index 3212500f..d401281a 100644 --- a/src/base/wlc/wlcNdr.c +++ b/src/base/wlc/wlcNdr.c @@ -263,7 +263,7 @@ void Wlc_NtkToNdrTest( Wlc_Ntk_t * pNtk ) ppNames[i] = Wlc_ObjName(pNtk, i); // verify by writing Verilog - Ndr_WriteVerilog( NULL, pDesign, ppNames ); + Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); Ndr_Write( "test.ndr", pDesign ); // cleanup @@ -368,7 +368,7 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData ) Ndr_Data_t * p = (Ndr_Data_t *)pData; Wlc_Obj_t * pObj; Vec_Int_t * vName2Obj, * vFanins = Vec_IntAlloc( 100 ); int Mod = 2, i, k, Obj, * pArray, nDigits, fFound, NameId, NameIdMax; - Vec_Wrd_t * vTruths = NULL; + Vec_Wrd_t * vTruths = NULL; int nTruths[2] = {0}; Wlc_Ntk_t * pTemp, * pNtk = Wlc_NtkAlloc( "top", Ndr_DataObjNum(p, Mod)+1 ); Wlc_NtkCheckIntegrity( pData ); Vec_IntClear( &pNtk->vFfs ); @@ -415,11 +415,14 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData ) Vec_IntPush( &pNtk->vFfs2, iObj ); if ( Type == ABC_OPER_LUT ) { + word * pTruth; if ( vTruths == NULL ) vTruths = Vec_WrdStart( 1000 ); if ( NameId >= Vec_WrdSize(vTruths) ) Vec_WrdFillExtra( vTruths, 2*NameId, 0 ); - Vec_WrdWriteEntry( vTruths, NameId, *((word *)Ndr_ObjReadBodyP(p, Obj, NDR_FUNCTION)) ); + pTruth = (word *)Ndr_ObjReadBodyP(p, Obj, NDR_FUNCTION); + Vec_WrdWriteEntry( vTruths, NameId, pTruth ? *pTruth : 0 ); + nTruths[ pTruth != NULL ]++; } if ( Type == ABC_OPER_SLICE ) Vec_IntPushTwo( vFanins, End, Beg ); @@ -437,6 +440,8 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData ) Wlc_ObjFanin1(pNtk, pObj)->Signed = 1; } } + if ( nTruths[0] ) + printf( "Warning! The number of LUTs without function is %d (out of %d).\n", nTruths[0], nTruths[0]+nTruths[1] ); // mark primary outputs Ndr_ModForEachPo( p, Mod, Obj ) { @@ -487,7 +492,7 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData ) pNtk->pManName = Abc_NamStart( NameIdMax+1, 10 ); for ( i = 1; i <= NameIdMax; i++ ) { - char pName[20]; sprintf( pName, "s%0*d", nDigits, i ); + char pName[100]; sprintf( pName, "s%0*d", nDigits, i ); NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pName, &fFound ); assert( !fFound && i == NameId ); } @@ -535,7 +540,7 @@ Wlc_Ntk_t * Wlc_ReadNdr( char * pFileName ) void * pData = Ndr_Read( pFileName ); Wlc_Ntk_t * pNtk = Wlc_NtkFromNdr( pData ); //char * ppNames[10] = { NULL, "a", "b", "c", "d", "e", "f", "g", "h", "i" }; - //Ndr_WriteVerilog( NULL, pData, ppNames ); + //Ndr_WriteVerilog( NULL, pData, ppNames, 0 ); //Ndr_Delete( pData ); Abc_FrameInputNdr( Abc_FrameGetGlobalFrame(), pData ); return pNtk; diff --git a/src/base/wln/wln.h b/src/base/wln/wln.h index 510d74c1..93a1a92a 100644 --- a/src/base/wln/wln.h +++ b/src/base/wln/wln.h @@ -246,7 +246,7 @@ extern int Wln_ObjClone( Wln_Ntk_t * pNew, Wln_Ntk_t * p, int iObj ); extern int Wln_ObjCreateCo( Wln_Ntk_t * p, int iFanin ); extern void Wln_ObjPrint( Wln_Ntk_t * p, int iObj ); /*=== wlcRetime.c ========================================================*/ -extern Vec_Int_t * Wln_NtkRetime( Wln_Ntk_t * p, int fSkipSimple, int fVerbose ); +extern Vec_Int_t * Wln_NtkRetime( Wln_Ntk_t * p, int fIgnoreIO, int fSkipSimple, int fVerbose ); extern void Wln_NtkRetimeCreateDelayInfo( Wln_Ntk_t * pNtk ); /*=== wlcWriteVer.c ========================================================*/ extern void Wln_WriteVer( Wln_Ntk_t * p, char * pFileName ); diff --git a/src/base/wln/wlnNdr.c b/src/base/wln/wlnNdr.c index eb685463..9eaf71ed 100644 --- a/src/base/wln/wlnNdr.c +++ b/src/base/wln/wlnNdr.c @@ -96,7 +96,7 @@ void Wln_NtkToNdrTest( Wln_Ntk_t * p ) ppNames[i] = Abc_UtilStrsav(Wln_ObjName(p, i)); // verify by writing Verilog - Ndr_WriteVerilog( NULL, pDesign, ppNames ); + Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); Ndr_Write( "test.ndr", pDesign ); // cleanup @@ -256,7 +256,7 @@ Wln_Ntk_t * Wln_NtkFromNdr( void * pData, int fDump ) pNtk->pManName = Abc_NamStart( NameIdMax+1, 10 ); for ( i = 1; i <= NameIdMax; i++ ) { - char pName[20]; sprintf( pName, "s%0*d", nDigits, i ); + char pName[100]; sprintf( pName, "s%0*d", nDigits, i ); NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pName, &fFound ); assert( !fFound && i == NameId ); } @@ -301,7 +301,7 @@ Wln_Ntk_t * Wln_ReadNdr( char * pFileName ) Wln_Ntk_t * pNtk = pData ? Wln_NtkFromNdr( pData, 0 ) : NULL; if ( pNtk ) return NULL; //char * ppNames[10] = { NULL, "a", "b", "c", "d", "e", "f", "g", "h", "i" }; - //Ndr_WriteVerilog( NULL, pData, ppNames ); + //Ndr_WriteVerilog( NULL, pData, ppNames, 0 ); Ndr_Delete( pData ); return pNtk; } @@ -314,7 +314,7 @@ void Wln_ReadNdrTest() Wln_NtkStaticFanoutTest( pNtk ); Wln_NtkFree( pNtk ); } -void Wln_NtkRetimeTest( char * pFileName, int fSkipSimple, int fDump, int fVerbose ) +void Wln_NtkRetimeTest( char * pFileName, int fIgnoreIO, int fSkipSimple, int fDump, int fVerbose ) { Vec_Int_t * vMoves; void * pData = Ndr_Read( pFileName ); @@ -326,7 +326,7 @@ void Wln_NtkRetimeTest( char * pFileName, int fSkipSimple, int fDump, int fVerbo return; } Wln_NtkRetimeCreateDelayInfo( pNtk ); - vMoves = Wln_NtkRetime( pNtk, fSkipSimple, fVerbose ); + vMoves = Wln_NtkRetime( pNtk, fIgnoreIO, fSkipSimple, fVerbose ); //Vec_IntPrint( vMoves ); Vec_IntFree( vMoves ); Wln_NtkFree( pNtk ); diff --git a/src/base/wln/wlnRetime.c b/src/base/wln/wlnRetime.c index 734ac194..5ccc1dd0 100644 --- a/src/base/wln/wlnRetime.c +++ b/src/base/wln/wlnRetime.c @@ -335,6 +335,55 @@ void Wln_RetFindSources( Wln_Ret_t * p ) /**Function************************************************************* + Synopsis [Mark paths from PIs to POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Wln_RetMarkPaths_rec( Wln_Ntk_t * p, int iObj, int fVerbose ) +{ + int k, iFanin, fPrev = 1; + if ( Wln_ObjIsTravIdPrevious(p, iObj) ) + return 1; + if ( Wln_ObjIsTravIdCurrent(p, iObj) ) + return 0; + if ( Wln_ObjIsCio(p, iObj) || Wln_ObjIsFf(p, iObj) ) + return 0; + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + fPrev &= Wln_RetMarkPaths_rec( p, iFanin, fVerbose ); + if ( fPrev ) + { + Wln_ObjSetTravIdPrevious( p, iObj ); + if ( Vec_IntEntry(&p->vInstIds, iObj) > 0 ) + { + if ( fVerbose ) + printf( "Updating delay %5d -> %5d : ", Vec_IntEntry(&p->vInstIds, iObj), 1 ); + if ( fVerbose ) + Wln_ObjPrint( p, iObj ); + Vec_IntWriteEntry( &p->vInstIds, iObj, 1 ); + } + return 1; + } + Wln_ObjSetTravIdCurrent( p, iObj ); + return 0; +} +void Wln_RetMarkPaths( Wln_Ntk_t * p, int fVerbose ) +{ + int i, iObj; + Wln_NtkIncrementTravId( p ); + Wln_NtkIncrementTravId( p ); + Wln_NtkForEachPi( p, iObj, i ) + Wln_ObjSetTravIdPrevious( p, iObj ); + Wln_NtkForEachPo( p, iObj, i ) + Wln_RetMarkPaths_rec( p, Wln_ObjFanin0(p, iObj), fVerbose ); +} + +/**Function************************************************************* + Synopsis [Retimability check.] Description [] @@ -571,7 +620,7 @@ void Wln_NtkRetimeCreateDelayInfo( Wln_Ntk_t * pNtk ) printf( "Assuming default delays: 10 units for most nodes and 1 unit for bit-slice, concat, and buffers driving COs.\n" ); } } -Vec_Int_t * Wln_NtkRetime( Wln_Ntk_t * pNtk, int fSkipSimple, int fVerbose ) +Vec_Int_t * Wln_NtkRetime_int( Wln_Ntk_t * pNtk, int fSkipSimple, int fVerbose ) { Wln_Ret_t * p = Wln_RetAlloc( pNtk ); Vec_Int_t * vSources = &p->vSources; @@ -666,6 +715,12 @@ Vec_Int_t * Wln_NtkRetime( Wln_Ntk_t * pNtk, int fSkipSimple, int fVerbose ) } return vMoves; } +Vec_Int_t * Wln_NtkRetime( Wln_Ntk_t * pNtk, int fIgnoreIO, int fSkipSimple, int fVerbose ) +{ + if ( fIgnoreIO ) + Wln_RetMarkPaths( pNtk, fVerbose ); + return Wln_NtkRetime_int( pNtk, fSkipSimple, fVerbose ); +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/bdd/extrab/extraBddMisc.c b/src/bdd/extrab/extraBddMisc.c index 42003864..f4ec0712 100644 --- a/src/bdd/extrab/extraBddMisc.c +++ b/src/bdd/extrab/extraBddMisc.c @@ -1291,7 +1291,7 @@ static DdNode * extraBddCountCubes( DdManager * dd, DdNode * L, DdNode * U, st__ if (r) { int nCubes = 0; - if ( st__lookup( table, (char *)r, (char **)&nCubes ) ) + if ( st__lookup_int( table, (char *)r, &nCubes ) ) *pnCubes = nCubes; else assert( 0 ); return r; diff --git a/src/bdd/llb/llb4Nonlin.c b/src/bdd/llb/llb4Nonlin.c index f8ee825e..d99109fd 100644 --- a/src/bdd/llb/llb4Nonlin.c +++ b/src/bdd/llb/llb4Nonlin.c @@ -1156,7 +1156,7 @@ Aig_Man_t * Llb_ReachableStates( Aig_Man_t * pAig ) Cudd_Quit( dd ); // convert - pNtkMuxes = Abc_NtkBddToMuxes( pNtk, 0, 1000000 ); + pNtkMuxes = Abc_NtkBddToMuxes( pNtk, 0, 1000000, 0 ); Abc_NtkDelete( pNtk ); pNtk = Abc_NtkStrash( pNtkMuxes, 0, 1, 0 ); Abc_NtkDelete( pNtkMuxes ); diff --git a/src/bool/bdc/bdc.h b/src/bool/bdc/bdc.h index bd0f7d7d..cc3cfeab 100644 --- a/src/bool/bdc/bdc.h +++ b/src/bool/bdc/bdc.h @@ -79,6 +79,8 @@ extern void * Bdc_FuncCopy( Bdc_Fun_t * p ); extern int Bdc_FuncCopyInt( Bdc_Fun_t * p ); extern void Bdc_FuncSetCopy( Bdc_Fun_t * p, void * pCopy ); extern void Bdc_FuncSetCopyInt( Bdc_Fun_t * p, int iCopy ); +extern int Bdc_ManBidecNodeNum( word * pFunc, word * pCare, int nVars, int fVerbose ); +extern Vec_Int_t * Bdc_ManBidecResub( word * pFunc, word * pCare, int nVars ); /*=== working with saved copies ==========================================*/ static inline int Bdc_FunObjCopy( Bdc_Fun_t * pObj ) { return Abc_LitNotCond( Bdc_FuncCopyInt(Bdc_Regular(pObj)), Bdc_IsComplement(pObj) ); } diff --git a/src/bool/bdc/bdcCore.c b/src/bool/bdc/bdcCore.c index 5a7a0c3a..cce0e306 100644 --- a/src/bool/bdc/bdcCore.c +++ b/src/bool/bdc/bdcCore.c @@ -364,6 +364,85 @@ void Bdc_ManDecomposeTest( unsigned uTruth, int nVars ) Bdc_ManFree( p ); } +/**Function************************************************************* + + Synopsis [Performs decomposition of one function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bdc_ManBidecNodeNum( word * pFunc, word * pCare, int nVars, int fVerbose ) +{ + int nNodes; + Bdc_Man_t * pManDec; + Bdc_Par_t Pars = {0}, * pPars = &Pars; + pPars->nVarsMax = nVars; + pManDec = Bdc_ManAlloc( pPars ); + Bdc_ManDecompose( pManDec, (unsigned *)pFunc, (unsigned *)pCare, nVars, NULL, 1000 ); + nNodes = Bdc_ManAndNum( pManDec ); + if ( fVerbose ) + Bdc_ManDecPrint( pManDec ); + Bdc_ManFree( pManDec ); + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Performs decomposition of one function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_ManBidecResubInt( Bdc_Man_t * p, Vec_Int_t * vRes ) +{ + int i, iRoot = Bdc_FunId(p,Bdc_Regular(p->pRoot)) - 1; + if ( iRoot == -1 ) + Vec_IntPush( vRes, !Bdc_IsComplement(p->pRoot) ); + else if ( iRoot < p->nVars ) + Vec_IntPush( vRes, 4 + Abc_Var2Lit(iRoot, Bdc_IsComplement(p->pRoot)) ); + else + { + for ( i = p->nVars+1; i < p->nNodes; i++ ) + { + Bdc_Fun_t * pNode = p->pNodes + i; + int iLit0 = Abc_Var2Lit( Bdc_FunId(p,Bdc_Regular(pNode->pFan0)) - 1, Bdc_IsComplement(pNode->pFan0) ); + int iLit1 = Abc_Var2Lit( Bdc_FunId(p,Bdc_Regular(pNode->pFan1)) - 1, Bdc_IsComplement(pNode->pFan1) ); + if ( iLit0 > iLit1 ) + iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1; + Vec_IntPushTwo( vRes, 4 + iLit0, 4 + iLit1 ); + } + assert( 2 + iRoot == p->nNodes ); + Vec_IntPush( vRes, 4 + Abc_Var2Lit(iRoot, Bdc_IsComplement(p->pRoot)) ); + } +} +Vec_Int_t * Bdc_ManBidecResub( word * pFunc, word * pCare, int nVars ) +{ + Vec_Int_t * vRes = NULL; + int nNodes; + Bdc_Man_t * pManDec; + Bdc_Par_t Pars = {0}, * pPars = &Pars; + pPars->nVarsMax = nVars; + pManDec = Bdc_ManAlloc( pPars ); + Bdc_ManDecompose( pManDec, (unsigned *)pFunc, (unsigned *)pCare, nVars, NULL, 1000 ); + if ( pManDec->pRoot != NULL ) + { + //Bdc_ManDecPrint( pManDec ); + nNodes = Bdc_ManAndNum( pManDec ); + vRes = Vec_IntAlloc( 2*nNodes + 1 ); + Bdc_ManBidecResubInt( pManDec, vRes ); + assert( Vec_IntSize(vRes) == 2*nNodes + 1 ); + } + Bdc_ManFree( pManDec ); + return vRes; +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/bool/kit/kit.h b/src/bool/kit/kit.h index 47f06403..ee82b084 100644 --- a/src/bool/kit/kit.h +++ b/src/bool/kit/kit.h @@ -568,11 +568,14 @@ extern unsigned Kit_GraphToTruth( Kit_Graph_t * pGraph ); extern Kit_Graph_t * Kit_TruthToGraph( unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); extern Kit_Graph_t * Kit_TruthToGraph2( unsigned * pTruth0, unsigned * pTruth1, int nVars, Vec_Int_t * vMemory ); extern int Kit_GraphLeafDepth_rec( Kit_Graph_t * pGraph, Kit_Node_t * pNode, Kit_Node_t * pLeaf ); +extern int Kit_TruthLitNum( unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); /*=== kitHop.c ==========================================================*/ //extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); //extern Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph ); //extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); //extern Hop_Obj_t * Kit_CoverToHop( Hop_Man_t * pMan, Vec_Int_t * vCover, int nVars, Vec_Int_t * vMemory ); +extern int Kit_IsopNodeNum( unsigned * pTruth0, unsigned * pTruth1, int nVars, Vec_Int_t * vMemory ); +extern Vec_Int_t * Kit_IsopResub( unsigned * pTruth0, unsigned * pTruth1, int nVars, Vec_Int_t * vMemory ); /*=== kitIsop.c ==========================================================*/ extern int Kit_TruthIsop( unsigned * puTruth, int nVars, Vec_Int_t * vMemory, int fTryBoth ); extern int Kit_TruthIsop2( unsigned * puTruth0, unsigned * puTruth1, int nVars, Vec_Int_t * vMemory, int fTryBoth, int fReturnTt ); diff --git a/src/bool/kit/kitGraph.c b/src/bool/kit/kitGraph.c index 0e548575..a81b6404 100644 --- a/src/bool/kit/kitGraph.c +++ b/src/bool/kit/kitGraph.c @@ -19,6 +19,7 @@ ***********************************************************************/ #include "kit.h" +#include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START @@ -385,7 +386,7 @@ Kit_Graph_t * Kit_TruthToGraph2( unsigned * pTruth0, unsigned * pTruth1, int nVa Kit_Graph_t * pGraph; int RetValue; // derive SOP - RetValue = Kit_TruthIsop2( pTruth0, pTruth1, nVars, vMemory, 1, 0 ); // tried 1 and found not useful in "renode" + RetValue = Kit_TruthIsop2( pTruth0, pTruth1, nVars, vMemory, 0, 0 ); // tried 1 and found not useful in "renode" if ( RetValue == -1 ) return NULL; if ( Vec_IntSize(vMemory) > (1<<16) ) @@ -496,6 +497,31 @@ int * Kit_TruthTest( char * pFileName ) return pResult; } +/**Function************************************************************* + + Synopsis [Derives the factored form from the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_TruthLitNum( unsigned * pTruth, int nVars, Vec_Int_t * vMemory ) +{ + Kit_Graph_t * pGraph; + int RetValue, nLits; + RetValue = Kit_TruthIsop( pTruth, nVars, vMemory, 1 ); + if ( RetValue == -1 || Vec_IntSize(vMemory) > (1<<16) ) + return -1; + assert( RetValue == 0 || RetValue == 1 ); + pGraph = Kit_SopFactor( vMemory, RetValue, nVars, vMemory ); + nLits = 1 + Kit_GraphNodeNum( pGraph ); + Kit_GraphFree( pGraph ); + return nLits; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/bool/kit/kitHop.c b/src/bool/kit/kitHop.c index 4ac82ac9..4509dadf 100644 --- a/src/bool/kit/kitHop.c +++ b/src/bool/kit/kitHop.c @@ -136,6 +136,107 @@ int Kit_TruthToGia2( Gia_Man_t * pMan, unsigned * pTruth0, unsigned * pTruth1, i SeeAlso [] ***********************************************************************/ +int Kit_IsopNodeNum( unsigned * pTruth0, unsigned * pTruth1, int nVars, Vec_Int_t * vMemory ) +{ + Kit_Graph_t * pGraph; + int nNodes; + // transform truth table into the decomposition tree + if ( vMemory == NULL ) + { + vMemory = Vec_IntAlloc( 0 ); + pGraph = Kit_TruthToGraph2( pTruth0, pTruth1, nVars, vMemory ); + Vec_IntFree( vMemory ); + } + else + pGraph = Kit_TruthToGraph2( pTruth0, pTruth1, nVars, vMemory ); + if ( pGraph == NULL ) + { + printf( "Kit_TruthToGia2(): Converting truth table to AIG has failed for function:\n" ); + Kit_DsdPrintFromTruth( pTruth0, nVars ); printf( "\n" ); + Kit_DsdPrintFromTruth( pTruth1, nVars ); printf( "\n" ); + } + // derive the AIG for the decomposition tree + nNodes = Kit_GraphNodeNum( pGraph ); + Kit_GraphFree( pGraph ); + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_IsopResubInt( Kit_Graph_t * pGraph, Vec_Int_t * vRes ) +{ + int nVars = Kit_GraphLeaveNum(pGraph); + assert( nVars >= 0 && nVars <= pGraph->nSize ); + if ( Kit_GraphIsConst(pGraph) ) + Vec_IntPush( vRes, Kit_GraphIsConst1(pGraph) ); + else if ( Kit_GraphIsVar(pGraph) ) + Vec_IntPush( vRes, 4 + Abc_Var2Lit(Kit_GraphVarInt(pGraph), Kit_GraphIsComplement(pGraph)) ); + else + { + Kit_Node_t * pNode; int i; + Kit_GraphForEachNode( pGraph, pNode, i ) + { + Kit_Node_t * pFan0 = Kit_GraphNodeFanin0( pGraph, pNode ); + Kit_Node_t * pFan1 = Kit_GraphNodeFanin1( pGraph, pNode ); + int iLit0 = Abc_Var2Lit( Kit_GraphNodeInt(pGraph, pFan0), pNode->eEdge0.fCompl ); + int iLit1 = Abc_Var2Lit( Kit_GraphNodeInt(pGraph, pFan1), pNode->eEdge1.fCompl ); + if ( iLit0 > iLit1 ) + iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1; + Vec_IntPushTwo( vRes, 4 + iLit0, 4 + iLit1 ); + } + assert( pNode == Kit_GraphNode(pGraph, pGraph->eRoot.Node) ); + Vec_IntPush( vRes, 4 + Abc_Var2Lit(Kit_GraphNodeInt(pGraph, pNode), Kit_GraphIsComplement(pGraph)) ); + } +} +Vec_Int_t * Kit_IsopResub( unsigned * pTruth0, unsigned * pTruth1, int nVars, Vec_Int_t * vMemory ) +{ + Vec_Int_t * vRes = NULL; + Kit_Graph_t * pGraph; + int nNodes; + // transform truth table into the decomposition tree + if ( vMemory == NULL ) + { + vMemory = Vec_IntAlloc( 0 ); + pGraph = Kit_TruthToGraph2( pTruth0, pTruth1, nVars, vMemory ); + Vec_IntFree( vMemory ); + } + else + pGraph = Kit_TruthToGraph2( pTruth0, pTruth1, nVars, vMemory ); + if ( pGraph == NULL ) + { + printf( "Kit_TruthToGia2(): Converting truth table to AIG has failed for function:\n" ); + Kit_DsdPrintFromTruth( pTruth0, nVars ); printf( "\n" ); + Kit_DsdPrintFromTruth( pTruth1, nVars ); printf( "\n" ); + } + // derive the AIG for the decomposition tree + nNodes = Kit_GraphNodeNum( pGraph ); + vRes = Vec_IntAlloc( 2*nNodes + 1 ); + Kit_IsopResubInt( pGraph, vRes ); + assert( Vec_IntSize(vRes) == 2*nNodes + 1 ); + Kit_GraphFree( pGraph ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ Hop_Obj_t * Kit_GraphToHopInternal( Hop_Man_t * pMan, Kit_Graph_t * pGraph ) { Kit_Node_t * pNode = NULL; diff --git a/src/map/if/ifCut.c b/src/map/if/ifCut.c index ad37b77f..2d6889c0 100644 --- a/src/map/if/ifCut.c +++ b/src/map/if/ifCut.c @@ -608,6 +608,10 @@ static inline int If_ManSortCompare( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC return -1; if ( pC0->Delay > pC1->Delay + p->fEpsilon ) return 1; + if ( pC0->fUseless < pC1->fUseless ) + return -1; + if ( pC0->fUseless > pC1->fUseless ) + return 1; return 0; } if ( p->SortMode == 0 ) // delay @@ -632,6 +636,10 @@ static inline int If_ManSortCompare( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC return -1; if ( pC0->Power > pC1->Power + p->fEpsilon ) return 1; + if ( pC0->fUseless < pC1->fUseless ) + return -1; + if ( pC0->fUseless > pC1->fUseless ) + return 1; return 0; } assert( p->SortMode == 2 ); // delay old @@ -639,6 +647,10 @@ static inline int If_ManSortCompare( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC return -1; if ( pC0->Delay > pC1->Delay + p->fEpsilon ) return 1; + if ( pC0->fUseless < pC1->fUseless ) + return -1; + if ( pC0->fUseless > pC1->fUseless ) + return 1; if ( pC0->Area < pC1->Area - p->fEpsilon ) return -1; if ( pC0->Area > pC1->Area + p->fEpsilon ) @@ -1129,8 +1141,8 @@ float If_CutAreaRefed( If_Man_t * p, If_Cut_t * pCut ) return 0; aResult2 = If_CutAreaDeref( p, pCut ); aResult = If_CutAreaRef( p, pCut ); - assert( aResult > aResult2 - p->fEpsilon ); - assert( aResult < aResult2 + p->fEpsilon ); +// assert( aResult > aResult2 - p->fEpsilon ); +// assert( aResult < aResult2 + p->fEpsilon ); return aResult; } @@ -1207,8 +1219,8 @@ float If_CutEdgeDerefed( If_Man_t * p, If_Cut_t * pCut ) return pCut->nLeaves; aResult2 = If_CutEdgeRef( p, pCut ); aResult = If_CutEdgeDeref( p, pCut ); - assert( aResult > aResult2 - 3*p->fEpsilon ); - assert( aResult < aResult2 + 3*p->fEpsilon ); +// assert( aResult > aResult2 - 3*p->fEpsilon ); +// assert( aResult < aResult2 + 3*p->fEpsilon ); return aResult; } @@ -1230,8 +1242,8 @@ float If_CutEdgeRefed( If_Man_t * p, If_Cut_t * pCut ) return pCut->nLeaves; aResult2 = If_CutEdgeDeref( p, pCut ); aResult = If_CutEdgeRef( p, pCut ); - assert( aResult > aResult2 - p->fEpsilon ); - assert( aResult < aResult2 + p->fEpsilon ); +// assert( aResult > aResult2 - p->fEpsilon ); +// assert( aResult < aResult2 + p->fEpsilon ); return aResult; } diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c index bd8ebed7..f234d354 100644 --- a/src/map/if/ifMap.c +++ b/src/map/if/ifMap.c @@ -225,7 +225,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep if ( p->pPars->fPower ) pCut->Power = (Mode == 2)? If_CutPowerDerefed( p, pCut, pObj ) : If_CutPowerFlow( p, pCut, pObj ); // save the best cut from the previous iteration - if ( !fPreprocess ) + if ( !fPreprocess || pCut->nLeaves <= 1 ) If_CutCopy( p, pCutSet->ppCuts[pCutSet->nCuts++], pCut ); } @@ -516,7 +516,8 @@ void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fP // remove elementary cuts for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv ) - pTemp->pCutSet->nCuts--; + if ( pTemp != pObj || pTemp->pCutSet->nCuts > 1 ) + pTemp->pCutSet->nCuts--; // update the cutset of the node pCutSet = pObj->pCutSet; diff --git a/src/map/if/ifTruth.c b/src/map/if/ifTruth.c index 83c40952..ae4bcea4 100644 --- a/src/map/if/ifTruth.c +++ b/src/map/if/ifTruth.c @@ -20,6 +20,7 @@ #include "if.h" #include "bool/kit/kit.h" +#include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/mio/mio.c b/src/map/mio/mio.c index 8648a604..3010bbd3 100644 --- a/src/map/mio/mio.c +++ b/src/map/mio/mio.c @@ -408,6 +408,7 @@ int Mio_CommandWriteGenlib( Abc_Frame_t * pAbc, int argc, char **argv ) FILE * pOut, * pErr, * pFile; char * pFileName; int fSelected = 0; + int fVerilog = 0; int fVerbose = 0; int c; @@ -415,16 +416,19 @@ int Mio_CommandWriteGenlib( Abc_Frame_t * pAbc, int argc, char **argv ) pErr = Abc_FrameReadErr(pAbc); Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "vah")) != EOF ) + while ( (c = Extra_UtilGetopt(argc, argv, "agvh")) != EOF ) { switch (c) { - case 'v': - fVerbose ^= 1; - break; case 'a': fSelected ^= 1; break; + case 'g': + fVerilog ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; case 'h': goto usage; break; @@ -450,16 +454,20 @@ int Mio_CommandWriteGenlib( Abc_Frame_t * pAbc, int argc, char **argv ) printf( "Error! Cannot open file \"%s\" for writing the library.\n", pFileName ); return 1; } - Mio_WriteLibrary( pFile, (Mio_Library_t *)Abc_FrameReadLibGen(), 0, 0, fSelected ); + if ( fVerilog ) + Mio_WriteLibraryVerilog( pFile, (Mio_Library_t *)Abc_FrameReadLibGen(), 0, 0, fSelected ); + else + Mio_WriteLibrary( pFile, (Mio_Library_t *)Abc_FrameReadLibGen(), 0, 0, fSelected ); fclose( pFile ); printf( "The current genlib library is written into file \"%s\".\n", pFileName ); return 0; usage: - fprintf( pErr, "\nusage: write_genlib [-vah] <file>\n"); + fprintf( pErr, "\nusage: write_genlib [-agvh] <file>\n"); fprintf( pErr, "\t writes the current genlib library into a file\n" ); - fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", fVerbose? "yes" : "no" ); fprintf( pErr, "\t-a : toggles writing min-area gates [default = %s]\n", fSelected? "yes" : "no" ); + fprintf( pErr, "\t-g : toggles writing the library in Verilog [default = %s]\n", fVerilog? "yes" : "no" ); + fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", fVerbose? "yes" : "no" ); fprintf( pErr, "\t-h : print the command usage\n"); fprintf( pErr, "\t<file> : optional file name to write the library\n"); return 1; diff --git a/src/map/mio/mio.h b/src/map/mio/mio.h index d7f52f8c..18e3b92b 100644 --- a/src/map/mio/mio.h +++ b/src/map/mio/mio.h @@ -194,6 +194,7 @@ extern void Mio_GateDelete( Mio_Gate_t * pGate ); extern void Mio_PinDelete( Mio_Pin_t * pPin ); extern Mio_Pin_t * Mio_PinDup( Mio_Pin_t * pPin ); extern void Mio_WriteLibrary( FILE * pFile, Mio_Library_t * pLib, int fPrintSops, int fShort, int fSelected ); +extern void Mio_WriteLibraryVerilog( FILE * pFile, Mio_Library_t * pLib, int fPrintSops, int fShort, int fSelected ); extern Mio_Gate_t ** Mio_CollectRoots( Mio_Library_t * pLib, int nInputs, float tDelay, int fSkipInv, int * pnGates, int fVerbose ); extern Mio_Cell_t * Mio_CollectRootsNew( Mio_Library_t * pLib, int nInputs, int * pnGates, int fVerbose ); extern Mio_Cell_t * Mio_CollectRootsNewDefault( int nInputs, int * pnGates, int fVerbose ); diff --git a/src/map/mio/mioUtils.c b/src/map/mio/mioUtils.c index 9cd44cba..c7180e1c 100644 --- a/src/map/mio/mioUtils.c +++ b/src/map/mio/mioUtils.c @@ -288,6 +288,99 @@ void Mio_WriteLibrary( FILE * pFile, Mio_Library_t * pLib, int fPrintSops, int f /**Function************************************************************* + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Exp_PrintNodeVerilog( FILE * pFile, int nVars, Vec_Int_t * p, Vec_Ptr_t * vNames, int Node, int fCompl ) +{ + extern void Exp_PrintLitVerilog( FILE * pFile, int nVars, Vec_Int_t * p, Vec_Ptr_t * vNames, int Lit ); + if ( Vec_IntEntry(p, 2*Node+1) >= 2*nVars ) + fprintf( pFile, "(" ); + Exp_PrintLitVerilog( pFile, nVars, p, vNames, Vec_IntEntry(p, 2*Node+1) ^ fCompl ); + if ( Vec_IntEntry(p, 2*Node+1) >= 2*nVars ) + fprintf( pFile, ")" ); + fprintf( pFile, " %c ", fCompl ? '|' : '&' ); + if ( Vec_IntEntry(p, 2*Node+0) >= 2*nVars ) + fprintf( pFile, "(" ); + Exp_PrintLitVerilog( pFile, nVars, p, vNames, Vec_IntEntry(p, 2*Node+0) ^ fCompl ); + if ( Vec_IntEntry(p, 2*Node+0) >= 2*nVars ) + fprintf( pFile, ")" ); +} +void Exp_PrintLitVerilog( FILE * pFile, int nVars, Vec_Int_t * p, Vec_Ptr_t * vNames, int Lit ) +{ + if ( Lit == EXP_CONST0 ) + fprintf( pFile, "1\'b0" ); + else if ( Lit == EXP_CONST1 ) + fprintf( pFile, "1\'b1" ); + else if ( Lit < 2 * nVars ) + fprintf( pFile, "%s%s", (Lit&1) ? "~" : "", (char *)Vec_PtrEntry(vNames, Lit/2) ); + else + Exp_PrintNodeVerilog( pFile, nVars, p, vNames, Lit/2-nVars, Lit&1 ); +} +void Exp_PrintVerilog( FILE * pFile, int nVars, Vec_Int_t * p, Vec_Ptr_t * vNames ) +{ + Exp_PrintLitVerilog( pFile, nVars, p, vNames, Vec_IntEntryLast(p) ); +} +void Mio_WriteGateVerilog( FILE * pFile, Mio_Gate_t * pGate, Vec_Ptr_t * vNames ) +{ + char * pName; int i; + fprintf( pFile, "module %s ( ", pGate->pName ); + fprintf( pFile, "%s", pGate->pOutName ); + Vec_PtrForEachEntry( char *, vNames, pName, i ) + fprintf( pFile, ", %s", pName ); + fprintf( pFile, " );\n" ); + fprintf( pFile, " output %s;\n", pGate->pOutName ); + if ( Vec_PtrSize(vNames) > 0 ) + { + fprintf( pFile, " input %s", (char *)Vec_PtrEntry(vNames, 0) ); + Vec_PtrForEachEntryStart( char *, vNames, pName, i, 1 ) + fprintf( pFile, ", %s", pName ); + fprintf( pFile, ";\n" ); + } + fprintf( pFile, " assign %s = ", pGate->pOutName ); + Exp_PrintVerilog( pFile, Vec_PtrSize(vNames), pGate->vExpr, vNames ); + fprintf( pFile, ";\n" ); + fprintf( pFile, "endmodule\n\n" ); +} +void Mio_WriteLibraryVerilog( FILE * pFile, Mio_Library_t * pLib, int fPrintSops, int fShort, int fSelected ) +{ + Mio_Gate_t * pGate; + Mio_Pin_t * pPin; + Vec_Ptr_t * vGates = Vec_PtrAlloc( 1000 ); + Vec_Ptr_t * vNames = Vec_PtrAlloc( 100 ); + int i, nCells; + if ( fSelected ) + { + Mio_Cell2_t * pCells = Mio_CollectRootsNewDefault2( 6, &nCells, 0 ); + for ( i = 0; i < nCells; i++ ) + Vec_PtrPush( vGates, pCells[i].pMioGate ); + ABC_FREE( pCells ); + } + else + { + for ( i = 0; i < pLib->nGates; i++ ) + Vec_PtrPush( vGates, pLib->ppGates0[i] ); + } + fprintf( pFile, "// Verilog for genlib library \"%s\" with %d gates written by ABC on %s\n\n", pLib->pName, Vec_PtrSize(vGates), Extra_TimeStamp() ); + Vec_PtrForEachEntry( Mio_Gate_t *, vGates, pGate, i ) + { + Vec_PtrClear( vNames ); + Mio_GateForEachPin( pGate, pPin ) + Vec_PtrPush( vNames, pPin->pName ); + Mio_WriteGateVerilog( pFile, pGate, vNames ); + } + Vec_PtrFree( vNames ); + Vec_PtrFree( vGates ); +} + +/**Function************************************************************* + Synopsis [Compares the max delay of two gates.] Description [] diff --git a/src/map/scl/scl.c b/src/map/scl/scl.c index 27342458..635ec19e 100644 --- a/src/map/scl/scl.c +++ b/src/map/scl/scl.c @@ -153,11 +153,12 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) float Gain = 0; int nGatesMin = 0; int fShortNames = 0; + int fUnit = 0; int fVerbose = 1; int fVeryVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "SGMdnvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "SGMdnuvwh" ) ) != EOF ) { switch ( c ) { @@ -200,6 +201,9 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'n': fShortNames ^= 1; break; + case 'u': + fUnit ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -242,6 +246,12 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) // dump the resulting library if ( fDump && pAbc->pLibScl ) Abc_SclWriteLiberty( Extra_FileNameGenericAppend(pFileName, "_temp.lib"), (SC_Lib *)pAbc->pLibScl ); + if ( fUnit ) + { + SC_Cell * pCell; int i; + SC_LibForEachCell( pLib, pCell, i ) + pCell->area = 1; + } // extract genlib library if ( pAbc->pLibScl ) { @@ -251,13 +261,14 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pAbc->Err, "usage: read_lib [-SG float] [-M num] [-dnvwh] <file>\n" ); + fprintf( pAbc->Err, "usage: read_lib [-SG float] [-M num] [-dnuvwh] <file>\n" ); fprintf( pAbc->Err, "\t reads Liberty library from file\n" ); fprintf( pAbc->Err, "\t-S float : the slew parameter used to generate the library [default = %.2f]\n", Slew ); fprintf( pAbc->Err, "\t-G float : the gain parameter used to generate the library [default = %.2f]\n", Gain ); fprintf( pAbc->Err, "\t-M num : skip gate classes whose size is less than this [default = %d]\n", nGatesMin ); fprintf( pAbc->Err, "\t-d : toggle dumping the parsed library into file \"*_temp.lib\" [default = %s]\n", fDump? "yes": "no" ); fprintf( pAbc->Err, "\t-n : toggle replacing gate/pin names by short strings [default = %s]\n", fShortNames? "yes": "no" ); + fprintf( pAbc->Err, "\t-u : toggle setting unit area for all cells [default = %s]\n", fUnit? "yes": "no" ); fprintf( pAbc->Err, "\t-v : toggle writing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-w : toggle writing information about skipped gates [default = %s]\n", fVeryVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); diff --git a/src/map/scl/sclBufSize.c b/src/map/scl/sclBufSize.c index be9cc3bd..4d438af0 100644 --- a/src/map/scl/sclBufSize.c +++ b/src/map/scl/sclBufSize.c @@ -435,7 +435,7 @@ void Abc_SclBufSize( Bus_Man_t * p, float Gain ) // add one or more inverters // Abc_NtkPrintFanoutProfile( pObj ); Abc_NodeCollectFanouts( pObj, p->vFanouts ); - Vec_PtrSort( p->vFanouts, (int(*)(void))Bus_SclCompareFanouts ); + Vec_PtrSort( p->vFanouts, (int(*)(const void *, const void *))Bus_SclCompareFanouts ); do { Abc_Obj_t * pInv; diff --git a/src/map/scl/sclBuffer.c b/src/map/scl/sclBuffer.c index 97f5f095..8417b317 100644 --- a/src/map/scl/sclBuffer.c +++ b/src/map/scl/sclBuffer.c @@ -371,7 +371,7 @@ Abc_Obj_t * Abc_SclPerformBufferingOne( Abc_Obj_t * pObj, int Degree, int fUseIn // collect fanouts and sort by reverse level vFanouts = Vec_PtrAlloc( Abc_ObjFanoutNum(pObj) ); Abc_NodeCollectFanouts( pObj, vFanouts ); - Vec_PtrSort( vFanouts, (int (*)(void))Abc_NodeCompareLevels ); + Vec_PtrSort( vFanouts, (int (*)(const void *, const void *))Abc_NodeCompareLevels ); // select the first Degree fanouts if ( fUseInvs ) pBuffer = Abc_NtkCreateNodeInv( pObj->pNtk, NULL ); diff --git a/src/misc/bzlib/decompress.c b/src/misc/bzlib/decompress.c index 47dd98e4..4b7370f1 100644 --- a/src/misc/bzlib/decompress.c +++ b/src/misc/bzlib/decompress.c @@ -21,6 +21,10 @@ #include "bzlib_private.h" +#if (__GNUC__ >= 8) + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif + ABC_NAMESPACE_IMPL_START diff --git a/src/misc/extra/extra.h b/src/misc/extra/extra.h index 2f38692d..3ab09965 100644 --- a/src/misc/extra/extra.h +++ b/src/misc/extra/extra.h @@ -106,6 +106,7 @@ extern char * Extra_FileNameGenericAppend( char * pBase, char * pSuffix ); extern void Extra_FileNameCorrectPath( char * FileName ); extern char * Extra_FileNameWithoutPath( char * FileName ); extern char * Extra_FilePathWithoutName( char * FileName ); +extern char * Extra_FileInTheSameDir( char * pPathFile, char * pFileName ); extern char * Extra_FileDesignName( char * pFileName ); extern int Extra_FileCheck( char * pFileName ); extern int Extra_FileSize( char * pFileName ); diff --git a/src/misc/extra/extraUtilFile.c b/src/misc/extra/extraUtilFile.c index 38192c71..54e6efc2 100644 --- a/src/misc/extra/extraUtilFile.c +++ b/src/misc/extra/extraUtilFile.c @@ -240,13 +240,25 @@ char * Extra_FilePathWithoutName( char * FileName ) for ( pRes = FileName + strlen(FileName) - 1; pRes >= FileName; pRes-- ) if ( *pRes == '\\' || *pRes == '/' ) { - *pRes = 0; + pRes[1] = '\0'; Extra_FileNameCorrectPath( FileName ); return FileName; } ABC_FREE( FileName ); return NULL; } +char * Extra_FileInTheSameDir( char * pPathFile, char * pFileName ) +{ + static char pBuffer[1000]; char * pThis; + assert( strlen(pPathFile) + strlen(pFileName) < 990 ); + memmove( pBuffer, pPathFile, strlen(pPathFile) ); + for ( pThis = pBuffer + strlen(pPathFile) - 1; pThis >= pBuffer; pThis-- ) + if ( *pThis == '\\' || *pThis == '/' ) + break; + memmove( ++pThis, pFileName, strlen(pFileName) ); + pThis[strlen(pFileName)] = '\0'; + return pBuffer; +} char * Extra_FileDesignName( char * pFileName ) { char * pBeg, * pEnd, * pStore, * pCur; diff --git a/src/misc/extra/extraUtilPrime.c b/src/misc/extra/extraUtilPrime.c index 215de367..13558092 100644 --- a/src/misc/extra/extraUtilPrime.c +++ b/src/misc/extra/extraUtilPrime.c @@ -583,7 +583,7 @@ void Tab_DecomposeTest() Vec_Int_t * vPrimes = Abc_GenPrimes( nVars ); Tab_Man_t * p = Tab_ManAlloc( nVars, Vec_IntSize(vPrimes) ); Tab_ManStart( p, vPrimes ); - printf( "Created %d cubes dependent on %d variables with %d literals.\n", p->nCubes, p->nVars ); + printf( "Created %d cubes dependent on %d variables.\n", p->nCubes, p->nVars ); vPairs = Tab_ManCollectDist1( p, 0 ); printf( "Collected %d pairs.\n", Vec_IntSize(vPairs)/2 ); Vec_IntFree( vPairs ); diff --git a/src/misc/extra/extraUtilReader.c b/src/misc/extra/extraUtilReader.c index db604396..7ee3ddc3 100644 --- a/src/misc/extra/extraUtilReader.c +++ b/src/misc/extra/extraUtilReader.c @@ -22,8 +22,11 @@ #include "extra.h" #include "misc/vec/vec.h" -ABC_NAMESPACE_IMPL_START +#if (__GNUC__ >= 8) + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif +ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// diff --git a/src/misc/mem/mem.c b/src/misc/mem/mem.c index 23d8d7ec..347d0130 100644 --- a/src/misc/mem/mem.c +++ b/src/misc/mem/mem.c @@ -156,6 +156,22 @@ void Mem_FixedStop( Mem_Fixed_t * p, int fVerbose ) /**Function************************************************************* + Synopsis [Wrapper for Mem_FlexStop for use in Vec_AttAlloc] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mem_FlexStop2( Mem_Flex_t * p ) +{ + Mem_FlexStop( p, 0 ); +} + +/**Function************************************************************* + Synopsis [] Description [] diff --git a/src/misc/mem/mem.h b/src/misc/mem/mem.h index 4c0aa038..7bc5306c 100644 --- a/src/misc/mem/mem.h +++ b/src/misc/mem/mem.h @@ -50,6 +50,7 @@ extern int Mem_FixedReadMaxEntriesUsed( Mem_Fixed_t * p ); // flexible-size-block memory manager extern Mem_Flex_t * Mem_FlexStart(); extern void Mem_FlexStop( Mem_Flex_t * p, int fVerbose ); +extern void Mem_FlexStop2( Mem_Flex_t * p ); extern char * Mem_FlexEntryFetch( Mem_Flex_t * p, int nBytes ); extern void Mem_FlexRestart( Mem_Flex_t * p ); extern int Mem_FlexReadMemUsage( Mem_Flex_t * p ); diff --git a/src/misc/util/abc_global.h b/src/misc/util/abc_global.h index d7c5bea7..d1a9b4d3 100644 --- a/src/misc/util/abc_global.h +++ b/src/misc/util/abc_global.h @@ -288,6 +288,8 @@ static inline int Abc_Base2Log( unsigned n ) { int r; if ( n < static inline int Abc_Base10Log( unsigned n ) { int r; if ( n < 2 ) return (int)n; for ( r = 0, n--; n; n /= 10, r++ ) {}; return r; } static inline int Abc_Base16Log( unsigned n ) { int r; if ( n < 2 ) return (int)n; for ( r = 0, n--; n; n /= 16, r++ ) {}; return r; } static inline char * Abc_UtilStrsav( char * s ) { return s ? strcpy(ABC_ALLOC(char, strlen(s)+1), s) : NULL; } +static inline char * Abc_UtilStrsavTwo( char * s, char * a ){ char * r; if (!a) return Abc_UtilStrsav(s); r = ABC_ALLOC(char, strlen(s)+strlen(a)+1); sprintf(r, "%s%s", s, a ); return r; } +static inline char * Abc_UtilStrsavNum( char * s, int n ) { char * r; if (!s) return NULL; r = ABC_ALLOC(char, strlen(s)+12+1); sprintf(r, "%s%d", s, n ); return r; } static inline int Abc_BitByteNum( int nBits ) { return (nBits>>3) + ((nBits&7) > 0); } static inline int Abc_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } static inline int Abc_Bit6WordNum( int nBits ) { return (nBits>>6) + ((nBits&63) > 0); } @@ -327,7 +329,12 @@ static inline int Abc_Lit2Att4( int Lit ) { assert(Lit >= 0) typedef ABC_INT64_T abctime; static inline abctime Abc_Clock() { -#if (defined(LIN) || defined(LIN64)) && !(__APPLE__ & __MACH__) && !defined(__MINGW32__) +#if defined(__APPLE__) && defined(__MACH__) + #define APPLE_MACH (__APPLE__ & __MACH__) +#else + #define APPLE_MACH 0 +#endif +#if (defined(LIN) || defined(LIN64)) && !APPLE_MACH && !defined(__MINGW32__) struct timespec ts; if ( clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) < 0 ) return (abctime)-1; @@ -513,6 +520,8 @@ static inline void Abc_ReverseOrder( int * pA, int nA ) // sorting extern void Abc_MergeSort( int * pInput, int nSize ); extern int * Abc_MergeSortCost( int * pCosts, int nSize ); +extern void Abc_MergeSortCost2( int * pInput, int nSize, int * pCost ); +extern void Abc_MergeSortCost2Reverse( int * pInput, int nSize, int * pCost ); extern void Abc_QuickSort1( word * pData, int nSize, int fDecrease ); extern void Abc_QuickSort2( word * pData, int nSize, int fDecrease ); extern void Abc_QuickSort3( word * pData, int nSize, int fDecrease ); diff --git a/src/misc/util/utilNam.c b/src/misc/util/utilNam.c index 30a68c63..f6539f03 100644 --- a/src/misc/util/utilNam.c +++ b/src/misc/util/utilNam.c @@ -144,6 +144,45 @@ void Abc_NamPrint( Abc_Nam_t * p, char * pFileName ) /**Function************************************************************* + Synopsis [Writes into a file and reads from a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NamSave( Abc_Nam_t * p, char * pFileName ) +{ + FILE * pFile = fopen( pFileName, "wb" ); int h, i; + if ( pFile == NULL ) { printf( "Count node open input file %s\n", pFileName ); return; } + Vec_IntForEachEntryStart( &p->vInt2Handle, h, i, 1 ) + fprintf( pFile, "%s\n", Abc_NamHandleToStr(p, h) ); + fclose(pFile); +} +Abc_Nam_t * Abc_NamLoad( char * pFileName ) +{ + Abc_Nam_t * p; + int fFound, NameId = -1, nLineSize = 1 << 20; + char * pBuffer = ABC_ALLOC( char, nLineSize+1 ); + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) { printf( "Count node open output file %s\n", pFileName ); return NULL; } + p = Abc_NamStart( 1000, 20 ); + while ( fgets( pBuffer, nLineSize, pFile ) != NULL ) + { + pBuffer[strlen(pBuffer)-1] = 0; + NameId = Abc_NamStrFindOrAdd( p, pBuffer, &fFound ); + assert( !fFound ); + } + assert( NameId+1 == Abc_NamObjNumMax(p) ); + fclose( pFile ); + ABC_FREE( pBuffer ); + return p; +} + +/**Function************************************************************* + Synopsis [References the manager.] Description [] diff --git a/src/misc/util/utilNam.h b/src/misc/util/utilNam.h index 8e054fc1..cf2d27e7 100644 --- a/src/misc/util/utilNam.h +++ b/src/misc/util/utilNam.h @@ -53,6 +53,8 @@ typedef struct Abc_Nam_t_ Abc_Nam_t; extern Abc_Nam_t * Abc_NamStart( int nObjs, int nAveSize ); extern void Abc_NamStop( Abc_Nam_t * p ); extern void Abc_NamPrint( Abc_Nam_t * p, char * pFileName ); +extern void Abc_NamSave( Abc_Nam_t * p, char * pFileName ); +extern Abc_Nam_t * Abc_NamLoad( char * pFileName ); extern Abc_Nam_t * Abc_NamRef( Abc_Nam_t * p ); extern void Abc_NamDeref( Abc_Nam_t * p ); extern int Abc_NamObjNumMax( Abc_Nam_t * p ); diff --git a/src/misc/util/utilSort.c b/src/misc/util/utilSort.c index 31890503..a748caf9 100644 --- a/src/misc/util/utilSort.c +++ b/src/misc/util/utilSort.c @@ -137,6 +137,210 @@ void Abc_MergeSort( int * pInput, int nSize ) } +/**Function************************************************************* + + Synopsis [Merging two lists of entries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_SortMergeCost2( int * p1Beg, int * p1End, int * p2Beg, int * p2End, int * pOut, int * pCost ) +{ + int nEntries = (p1End - p1Beg) + (p2End - p2Beg); + int * pOutBeg = pOut; + while ( p1Beg < p1End && p2Beg < p2End ) + { + if ( pCost[*p1Beg] == pCost[*p2Beg] ) + *pOut++ = *p1Beg++, *pOut++ = *p2Beg++; + else if ( pCost[*p1Beg] < pCost[*p2Beg] ) + *pOut++ = *p1Beg++; + else // if ( pCost[*p1Beg] > pCost[*p2Beg] ) + *pOut++ = *p2Beg++; + } + while ( p1Beg < p1End ) + *pOut++ = *p1Beg++; + while ( p2Beg < p2End ) + *pOut++ = *p2Beg++; + assert( pOut - pOutBeg == nEntries ); +} + +/**Function************************************************************* + + Synopsis [Recursive sorting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_SortCost2_rec( int * pInBeg, int * pInEnd, int * pOutBeg, int * pCost ) +{ + int nSize = pInEnd - pInBeg; + assert( nSize > 0 ); + if ( nSize == 1 ) + return; + if ( nSize == 2 ) + { + if ( pCost[pInBeg[0]] > pCost[pInBeg[1]] ) + { + pInBeg[0] ^= pInBeg[1]; + pInBeg[1] ^= pInBeg[0]; + pInBeg[0] ^= pInBeg[1]; + } + } + else if ( nSize < 8 ) + { + int temp, i, j, best_i; + for ( i = 0; i < nSize-1; i++ ) + { + best_i = i; + for ( j = i+1; j < nSize; j++ ) + if ( pCost[pInBeg[j]] < pCost[pInBeg[best_i]] ) + best_i = j; + temp = pInBeg[i]; + pInBeg[i] = pInBeg[best_i]; + pInBeg[best_i] = temp; + } + } + else + { + Abc_SortCost2_rec( pInBeg, pInBeg + nSize/2, pOutBeg, pCost ); + Abc_SortCost2_rec( pInBeg + nSize/2, pInEnd, pOutBeg + nSize/2, pCost ); + Abc_SortMergeCost2( pInBeg, pInBeg + nSize/2, pInBeg + nSize/2, pInEnd, pOutBeg, pCost ); + memcpy( pInBeg, pOutBeg, sizeof(int) * nSize ); + } +} + +/**Function************************************************************* + + Synopsis [Returns the sorted array of integers.] + + Description [This procedure is about 10% faster than qsort().] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_MergeSortCost2( int * pInput, int nSize, int * pCost ) +{ + int * pOutput; + if ( nSize < 2 ) + return; + pOutput = (int *) malloc( sizeof(int) * nSize ); + Abc_SortCost2_rec( pInput, pInput + nSize, pOutput, pCost ); + free( pOutput ); +} + + +/**Function************************************************************* + + Synopsis [Merging two lists of entries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_SortMergeCost2Reverse( int * p1Beg, int * p1End, int * p2Beg, int * p2End, int * pOut, int * pCost ) +{ + int nEntries = (p1End - p1Beg) + (p2End - p2Beg); + int * pOutBeg = pOut; + while ( p1Beg < p1End && p2Beg < p2End ) + { + if ( pCost[*p1Beg] == pCost[*p2Beg] ) + *pOut++ = *p1Beg++, *pOut++ = *p2Beg++; + else if ( pCost[*p1Beg] > pCost[*p2Beg] ) + *pOut++ = *p1Beg++; + else // if ( pCost[*p1Beg] < pCost[*p2Beg] ) + *pOut++ = *p2Beg++; + } + while ( p1Beg < p1End ) + *pOut++ = *p1Beg++; + while ( p2Beg < p2End ) + *pOut++ = *p2Beg++; + assert( pOut - pOutBeg == nEntries ); +} + +/**Function************************************************************* + + Synopsis [Recursive sorting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_SortCost2Reverse_rec( int * pInBeg, int * pInEnd, int * pOutBeg, int * pCost ) +{ + int nSize = pInEnd - pInBeg; + assert( nSize > 0 ); + if ( nSize == 1 ) + return; + if ( nSize == 2 ) + { + if ( pCost[pInBeg[0]] < pCost[pInBeg[1]] ) + { + pInBeg[0] ^= pInBeg[1]; + pInBeg[1] ^= pInBeg[0]; + pInBeg[0] ^= pInBeg[1]; + } + } + else if ( nSize < 8 ) + { + int temp, i, j, best_i; + for ( i = 0; i < nSize-1; i++ ) + { + best_i = i; + for ( j = i+1; j < nSize; j++ ) + if ( pCost[pInBeg[j]] > pCost[pInBeg[best_i]] ) + best_i = j; + temp = pInBeg[i]; + pInBeg[i] = pInBeg[best_i]; + pInBeg[best_i] = temp; + } + } + else + { + Abc_SortCost2Reverse_rec( pInBeg, pInBeg + nSize/2, pOutBeg, pCost ); + Abc_SortCost2Reverse_rec( pInBeg + nSize/2, pInEnd, pOutBeg + nSize/2, pCost ); + Abc_SortMergeCost2Reverse( pInBeg, pInBeg + nSize/2, pInBeg + nSize/2, pInEnd, pOutBeg, pCost ); + memcpy( pInBeg, pOutBeg, sizeof(int) * nSize ); + } +} + +/**Function************************************************************* + + Synopsis [Returns the sorted array of integers.] + + Description [This procedure is about 10% faster than qsort().] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_MergeSortCost2Reverse( int * pInput, int nSize, int * pCost ) +{ + int * pOutput; + if ( nSize < 2 ) + return; + pOutput = (int *) malloc( sizeof(int) * nSize ); + Abc_SortCost2Reverse_rec( pInput, pInput + nSize, pOutput, pCost ); + free( pOutput ); +} + + /**Function************************************************************* diff --git a/src/misc/util/utilTruth.h b/src/misc/util/utilTruth.h index e0ee1720..d9efa55f 100644 --- a/src/misc/util/utilTruth.h +++ b/src/misc/util/utilTruth.h @@ -35,6 +35,22 @@ ABC_NAMESPACE_HEADER_START /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// +static unsigned s_Truths5[6] = { + 0xAAAAAAAA, + 0xCCCCCCCC, + 0xF0F0F0F0, + 0xFF00FF00, + 0xFFFF0000 +}; + +static unsigned s_Truths5Neg[6] = { + 0x55555555, + 0x33333333, + 0x0F0F0F0F, + 0x00FF00FF, + 0x0000FFFF +}; + static word s_Truths6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), @@ -216,6 +232,12 @@ static inline void Abc_TtMask( word * pTruth, int nWords, int nBits ) SeeAlso [] ***********************************************************************/ +static inline void Abc_TtVec( word * pOut, int nWords, word Entry ) +{ + int w; + for ( w = 0; w < nWords; w++ ) + pOut[w] = Entry; +} static inline void Abc_TtConst( word * pOut, int nWords, int fConst1 ) { int w; @@ -256,6 +278,12 @@ static inline void Abc_TtCopy( word * pOut, word * pIn, int nWords, int fCompl ) for ( w = 0; w < nWords; w++ ) pOut[w] = pIn[w]; } +static inline word * Abc_TtDup( word * pIn, int nWords, int fCompl ) +{ + word * pOut = ABC_ALLOC( word, nWords ); + Abc_TtCopy( pOut, pIn, nWords, fCompl ); + return pOut; +} static inline void Abc_TtAnd( word * pOut, word * pIn1, word * pIn2, int nWords, int fCompl ) { int w; @@ -316,6 +344,24 @@ static inline void Abc_TtOrXor( word * pOut, word * pIn1, word * pIn2, int nWord for ( w = 0; w < nWords; w++ ) pOut[w] |= pIn1[w] ^ pIn2[w]; } +static inline void Abc_TtAndXor( word * pOut, word * pIn1, word * pIn2, int nWords ) +{ + int w; + for ( w = 0; w < nWords; w++ ) + pOut[w] &= pIn1[w] ^ pIn2[w]; +} +static inline void Abc_TtOrAnd( word * pOut, word * pIn1, word * pIn2, int nWords ) +{ + int w; + for ( w = 0; w < nWords; w++ ) + pOut[w] |= pIn1[w] & pIn2[w]; +} +static inline void Abc_TtSharpOr( word * pOut, word * pIn1, word * pIn2, int nWords ) +{ + int w; + for ( w = 0; w < nWords; w++ ) + pOut[w] = (pOut[w] & ~pIn1[w]) | pIn2[w]; +} static inline void Abc_TtXor( word * pOut, word * pIn1, word * pIn2, int nWords, int fCompl ) { int w; @@ -365,6 +411,157 @@ static inline int Abc_TtIntersect( word * pIn1, word * pIn2, int nWords, int fCo } return 0; } +static inline int Abc_TtIntersectCare( word * pIn1, word * pIn2, word * pCare, int nWords, int fCompl ) +{ + int w; + if ( fCompl ) + { + for ( w = 0; w < nWords; w++ ) + if ( ~pIn1[w] & pIn2[w] & pCare[w] ) + return 1; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( pIn1[w] & pIn2[w] & pCare[w] ) + return 1; + } + return 0; +}static inline int Abc_TtIntersectOne( word * pOut, int fComp, word * pIn, int fComp0, int nWords ) +{ + int w; + if ( fComp0 ) + { + if ( fComp ) + { + for ( w = 0; w < nWords; w++ ) + if ( ~pIn[w] & ~pOut[w] ) + return 1; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( ~pIn[w] & pOut[w] ) + return 1; + } + } + else + { + if ( fComp ) + { + for ( w = 0; w < nWords; w++ ) + if ( pIn[w] & ~pOut[w] ) + return 1; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( pIn[w] & pOut[w] ) + return 1; + } + } + return 0; +} +static inline int Abc_TtIntersectTwo( word * pOut, int fComp, word * pIn0, int fComp0, word * pIn1, int fComp1, int nWords ) +{ + int w; + if ( fComp0 && fComp1 ) + { + if ( fComp ) + { + for ( w = 0; w < nWords; w++ ) + if ( ~pIn0[w] & ~pIn1[w] & ~pOut[w] ) + return 1; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( ~pIn0[w] & ~pIn1[w] & pOut[w] ) + return 1; + } + } + else if ( fComp0 ) + { + if ( fComp ) + { + for ( w = 0; w < nWords; w++ ) + if ( ~pIn0[w] & pIn1[w] & ~pOut[w] ) + return 1; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( ~pIn0[w] & pIn1[w] & pOut[w] ) + return 1; + } + } + else if ( fComp1 ) + { + if ( fComp ) + { + for ( w = 0; w < nWords; w++ ) + if ( pIn0[w] & ~pIn1[w] & ~pOut[w] ) + return 1; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( pIn0[w] & ~pIn1[w] & pOut[w] ) + return 1; + } + } + else + { + if ( fComp ) + { + for ( w = 0; w < nWords; w++ ) + if ( pIn0[w] & pIn1[w] & ~pOut[w] ) + return 1; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( pIn0[w] & pIn1[w] & pOut[w] ) + return 1; + } + } + return 0; +} +static inline int Abc_TtIntersectXor( word * pOut, int fComp, word * pIn0, word * pIn1, int fComp01, int nWords ) +{ + int w; + if ( fComp01 ) + { + if ( fComp ) + { + for ( w = 0; w < nWords; w++ ) + if ( ~(pIn0[w] ^ pIn1[w]) & ~pOut[w] ) + return 1; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( ~(pIn0[w] ^ pIn1[w]) & pOut[w] ) + return 1; + } + } + else + { + if ( fComp ) + { + for ( w = 0; w < nWords; w++ ) + if ( (pIn0[w] ^ pIn1[w]) & ~pOut[w] ) + return 1; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( (pIn0[w] ^ pIn1[w]) & pOut[w] ) + return 1; + } + } + return 0; +} static inline int Abc_TtEqual( word * pIn1, word * pIn2, int nWords ) { int w; @@ -373,6 +570,23 @@ static inline int Abc_TtEqual( word * pIn1, word * pIn2, int nWords ) return 0; return 1; } +static inline int Abc_TtEqualCare( word * pIn1, word * pIn2, word * pCare, int fComp, int nWords ) +{ + int w; + if ( fComp ) + { + for ( w = 0; w < nWords; w++ ) + if ( (~pIn1[w] ^ pIn2[w]) & pCare[w] ) + return 0; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( (pIn1[w] ^ pIn2[w]) & pCare[w] ) + return 0; + } + return 1; +} static inline int Abc_TtOpposite( word * pIn1, word * pIn2, int nWords ) { int w; @@ -683,6 +897,33 @@ static inline void Abc_TtElemInit2( word * pTtElems, int nVars ) SeeAlso [] ***********************************************************************/ +static inline int Abc_Tt5HasVar( unsigned t, int iVar ) +{ + return ((t << (1<<iVar)) & s_Truths5[iVar]) != (t & s_Truths5[iVar]); +} +static inline unsigned Abc_Tt5Cofactor0( unsigned t, int iVar ) +{ + assert( iVar >= 0 && iVar < 5 ); + return (t &s_Truths5Neg[iVar]) | ((t &s_Truths5Neg[iVar]) << (1<<iVar)); +} +static inline unsigned Abc_Tt5Cofactor1( unsigned t, int iVar ) +{ + assert( iVar >= 0 && iVar < 5 ); + return (t & s_Truths5[iVar]) | ((t & s_Truths5[iVar]) >> (1<<iVar)); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ static inline word Abc_Tt6Cofactor0( word t, int iVar ) { assert( iVar >= 0 && iVar < 6 ); @@ -1478,31 +1719,6 @@ static inline void Abc_TtFlip( word * pTruth, int nWords, int iVar ) SeeAlso [] ***********************************************************************/ -static inline word Abc_Tt6Permute_rec( word t, int * pPerm, int nVars ) -{ - word uRes0, uRes1; int Var; - if ( t == 0 ) return 0; - if ( ~t == 0 ) return ~(word)0; - for ( Var = nVars-1; Var >= 0; Var-- ) - if ( Abc_Tt6HasVar( t, Var ) ) - break; - assert( Var >= 0 ); - uRes0 = Abc_Tt6Permute_rec( Abc_Tt6Cofactor0(t, Var), pPerm, Var ); - uRes1 = Abc_Tt6Permute_rec( Abc_Tt6Cofactor1(t, Var), pPerm, Var ); - return (uRes0 & s_Truths6Neg[pPerm[Var]]) | (uRes1 & s_Truths6[pPerm[Var]]); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ static inline word Abc_Tt6SwapAdjacent( word Truth, int iVar ) { return (Truth & s_PMasks[iVar][0]) | ((Truth & s_PMasks[iVar][1]) << (1 << iVar)) | ((Truth & s_PMasks[iVar][2]) >> (1 << iVar)); @@ -1609,6 +1825,69 @@ static inline word Abc_Tt6RemoveVar( word t, int iVar ) /**Function************************************************************* + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline word Abc_Tt6Permute_rec( word t, int * pPerm, int nVars ) +{ + word uRes0, uRes1; int Var; + if ( t == 0 ) return 0; + if ( ~t == 0 ) return ~(word)0; + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_Tt6HasVar( t, Var ) ) + break; + assert( Var >= 0 ); + uRes0 = Abc_Tt6Permute_rec( Abc_Tt6Cofactor0(t, Var), pPerm, Var ); + uRes1 = Abc_Tt6Permute_rec( Abc_Tt6Cofactor1(t, Var), pPerm, Var ); + return (uRes0 & s_Truths6Neg[pPerm[Var]]) | (uRes1 & s_Truths6[pPerm[Var]]); +} +static inline void Abc_TtPermute( word * p, int * pPerm, int nVars ) +{ + int v, UnPerm[16], Perm[16]; + assert( nVars <= 16 ); + for ( v = 0; v < nVars; v++ ) + UnPerm[v] = Perm[v] = v; + for ( v = nVars-1; v >= 0; v-- ) + { + int Lev = UnPerm[pPerm[v]]; + if ( v == Lev ) + continue; + Abc_TtSwapVars( p, nVars, v, Lev ); + ABC_SWAP( int, Perm[v], Perm[Lev] ); + UnPerm[Perm[Lev]] = Lev; + UnPerm[Perm[v]] = v; + } + for ( v = 0; v < nVars; v++ ) + assert( Perm[v] == pPerm[v] ); +} +static inline void Abc_TtUnpermute( word * p, int * pPerm, int nVars ) +{ + int v, Perm[16]; + assert( nVars <= 16 ); + for ( v = 0; v < nVars; v++ ) + Perm[v] = pPerm[v]; + for ( v = nVars-1; v >= 0; v-- ) + { + while ( v != Perm[v] ) + { + int vCur = Perm[v]; + Abc_TtSwapVars( p, nVars, v, vCur ); + Perm[v] = Perm[vCur]; + Perm[vCur]= vCur; + } + } + for ( v = 0; v < nVars; v++ ) + assert( Perm[v] == v ); +} + +/**Function************************************************************* + Synopsis [Support minimization.] Description [] @@ -1827,22 +2106,30 @@ static inline int Abc_TtCountOnes( word x ) x = x + (x >> 32); return (int)(x & 0xFF); } +static inline int Abc_TtCountOnes2( word x ) +{ + return x ? Abc_TtCountOnes(x) : 0; +} static inline int Abc_TtCountOnesVec( word * x, int nWords ) { int w, Count = 0; for ( w = 0; w < nWords; w++ ) - Count += Abc_TtCountOnes( x[w] ); + Count += Abc_TtCountOnes2( x[w] ); return Count; } static inline int Abc_TtCountOnesVecMask( word * x, word * pMask, int nWords, int fCompl ) { int w, Count = 0; if ( fCompl ) + { for ( w = 0; w < nWords; w++ ) - Count += Abc_TtCountOnes( pMask[w] & ~x[w] ); + Count += Abc_TtCountOnes2( pMask[w] & ~x[w] ); + } else + { for ( w = 0; w < nWords; w++ ) - Count += Abc_TtCountOnes( pMask[w] & x[w] ); + Count += Abc_TtCountOnes2( pMask[w] & x[w] ); + } return Count; } static inline int Abc_TtCountOnesVecMask2( word * x0, word * x1, int fComp0, int fComp1, word * pMask, int nWords ) @@ -1850,23 +2137,34 @@ static inline int Abc_TtCountOnesVecMask2( word * x0, word * x1, int fComp0, int int w, Count = 0; if ( !fComp0 && !fComp1 ) for ( w = 0; w < nWords; w++ ) - Count += Abc_TtCountOnes( pMask[w] & x0[w] & x1[w] ); + Count += Abc_TtCountOnes2( pMask[w] & x0[w] & x1[w] ); else if ( fComp0 && !fComp1 ) for ( w = 0; w < nWords; w++ ) - Count += Abc_TtCountOnes( pMask[w] & ~x0[w] & x1[w] ); + Count += Abc_TtCountOnes2( pMask[w] & ~x0[w] & x1[w] ); else if ( !fComp0 && fComp1 ) for ( w = 0; w < nWords; w++ ) - Count += Abc_TtCountOnes( pMask[w] & x0[w] & ~x1[w] ); + Count += Abc_TtCountOnes2( pMask[w] & x0[w] & ~x1[w] ); else for ( w = 0; w < nWords; w++ ) - Count += Abc_TtCountOnes( pMask[w] & ~x0[w] & ~x1[w] ); + Count += Abc_TtCountOnes2( pMask[w] & ~x0[w] & ~x1[w] ); return Count; } static inline int Abc_TtCountOnesVecXor( word * x, word * y, int nWords ) { int w, Count = 0; for ( w = 0; w < nWords; w++ ) - Count += Abc_TtCountOnes( x[w] ^ y[w] ); + Count += Abc_TtCountOnes2( x[w] ^ y[w] ); + return Count; +} +static inline int Abc_TtCountOnesVecXorMask( word * x, word * y, int fCompl, word * pMask, int nWords ) +{ + int w, Count = 0; + if ( fCompl ) + for ( w = 0; w < nWords; w++ ) + Count += Abc_TtCountOnes2( pMask[w] & (x[w] ^ ~y[w]) ); + else + for ( w = 0; w < nWords; w++ ) + Count += Abc_TtCountOnes2( pMask[w] & (x[w] ^ y[w]) ); return Count; } static inline int Abc_TtAndXorSum( word * pOut, word * pIn1, word * pIn2, int nWords ) @@ -1875,10 +2173,20 @@ static inline int Abc_TtAndXorSum( word * pOut, word * pIn1, word * pIn2, int nW for ( w = 0; w < nWords; w++ ) { pOut[w] &= pIn1[w] ^ pIn2[w]; - Count += Abc_TtCountOnes( pOut[w] ); + Count += Abc_TtCountOnes2( pOut[w] ); } return Count; } +static inline void Abc_TtIsfPrint( word * pOff, word * pOn, int nWords ) +{ + int nTotal = 64*nWords; + int nOffset = Abc_TtCountOnesVec(pOff, nWords); + int nOnset = Abc_TtCountOnesVec(pOn, nWords); + int nDcset = nTotal - nOffset - nOnset; + printf( "OFF =%6d (%6.2f %%) ", nOffset, 100.0*nOffset/nTotal ); + printf( "ON =%6d (%6.2f %%) ", nOnset, 100.0*nOnset/nTotal ); + printf( "DC =%6d (%6.2f %%)", nDcset, 100.0*nDcset/nTotal ); +} /**Function************************************************************* @@ -1979,6 +2287,22 @@ static inline int Abc_TtFindLastDiffBit2( word * pIn1, word * pIn2, int nWords ) return 64*w + Abc_Tt6LastBit(pIn1[w] ^ pIn2[w]); return -1; } +static inline int Abc_TtFindFirstAndBit2( word * pIn1, word * pIn2, int nWords ) +{ + int w; + for ( w = 0; w < nWords; w++ ) + if ( pIn1[w] & pIn2[w] ) + return 64*w + Abc_Tt6FirstBit(pIn1[w] & pIn2[w]); + return -1; +} +static inline int Abc_TtFindLastAndBit2( word * pIn1, word * pIn2, int nWords ) +{ + int w; + for ( w = nWords - 1; w >= 0; w-- ) + if ( pIn1[w] & pIn2[w] ) + return 64*w + Abc_Tt6LastBit(pIn1[w] & pIn2[w]); + return -1; +} static inline int Abc_TtFindFirstZero( word * pIn, int nVars ) { int w, nWords = Abc_TtWordNum(nVars); diff --git a/src/misc/vec/vecHsh.h b/src/misc/vec/vecHsh.h index 00da8450..b87904a2 100644 --- a/src/misc/vec/vecHsh.h +++ b/src/misc/vec/vecHsh.h @@ -492,6 +492,10 @@ static inline int Hsh_VecSize( Hsh_VecMan_t * p ) { return Vec_IntSize(p->vMap); } +static inline double Hsh_VecManMemory( Hsh_VecMan_t * p ) +{ + return !p ? 0.0 : Vec_IntMemory(p->vTable) + Vec_IntMemory(p->vData) + Vec_IntMemory(p->vMap); +} /**Function************************************************************* diff --git a/src/misc/vec/vecInt.h b/src/misc/vec/vecInt.h index 514ce455..c15369d2 100644 --- a/src/misc/vec/vecInt.h +++ b/src/misc/vec/vecInt.h @@ -63,6 +63,8 @@ struct Vec_Int_t_ for ( i = Vec_IntSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_IntEntry(vVec, i)), 1); i-- ) #define Vec_IntForEachEntryTwo( vVec1, vVec2, Entry1, Entry2, i ) \ for ( i = 0; (i < Vec_IntSize(vVec1)) && (((Entry1) = Vec_IntEntry(vVec1, i)), 1) && (((Entry2) = Vec_IntEntry(vVec2, i)), 1); i++ ) +#define Vec_IntForEachEntryTwoStart( vVec1, vVec2, Entry1, Entry2, i, Start ) \ + for ( i = Start; (i < Vec_IntSize(vVec1)) && (((Entry1) = Vec_IntEntry(vVec1, i)), 1) && (((Entry2) = Vec_IntEntry(vVec2, i)), 1); i++ ) #define Vec_IntForEachEntryDouble( vVec, Entry1, Entry2, i ) \ for ( i = 0; (i+1 < Vec_IntSize(vVec)) && (((Entry1) = Vec_IntEntry(vVec, i)), 1) && (((Entry2) = Vec_IntEntry(vVec, i+1)), 1); i += 2 ) #define Vec_IntForEachEntryDoubleStart( vVec, Entry1, Entry2, i, Start ) \ @@ -148,6 +150,23 @@ static inline Vec_Int_t * Vec_IntStartRange( int First, int Range ) p->pArray[i] = First + i; return p; } +static inline Vec_Int_t * Vec_IntStartRandomLimit( int nSize, int Upper, int Lower ) +{ + Vec_Int_t * p = Vec_IntAlloc( nSize ); + int i, Gap = Upper - Lower + 1; + for ( i = 0; i < p->nSize; i++ ) + p->pArray[i] = Lower + Abc_Random(0) % Gap; + return p; +} +static inline void Vec_IntRandomizeOrder( Vec_Int_t * p ) +{ + int v; + for ( v = 0; v < p->nSize; v++ ) + { + int vRand = Abc_Random(0) % p->nSize; + ABC_SWAP( int, p->pArray[vRand], p->pArray[v] ); + } +} /**Function************************************************************* @@ -732,6 +751,11 @@ static inline void Vec_IntPush( Vec_Int_t * p, int Entry ) } p->pArray[p->nSize++] = Entry; } +static inline int Vec_IntPushReturn( Vec_Int_t * p, int Entry ) +{ + Vec_IntPush( p, Entry ); + return Entry; +} static inline void Vec_IntPushTwo( Vec_Int_t * p, int Entry1, int Entry2 ) { Vec_IntPush( p, Entry1 ); @@ -756,6 +780,12 @@ static inline void Vec_IntPushArray( Vec_Int_t * p, int * pEntries, int nEntries for ( i = 0; i < nEntries; i++ ) Vec_IntPush( p, pEntries[i] ); } +static inline void Vec_IntShift( Vec_Int_t * p, int Shift ) +{ + p->nSize -= Shift; + p->nCap -= Shift; + p->pArray += Shift; +} /**Function************************************************************* @@ -834,6 +864,52 @@ static inline void Vec_IntPushOrderCost( Vec_Int_t * p, int Entry, Vec_Int_t * v /**Function************************************************************* + Synopsis [Check if the array is ordered.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntIsOrdered( Vec_Int_t * p, int fReverse ) +{ + int i; + if ( fReverse ) + { + for ( i = 1; i < p->nSize; i++ ) + if ( p->pArray[i-1] < p->pArray[i] ) + return 0; + } + else + { + for ( i = 1; i < p->nSize; i++ ) + if ( p->pArray[i-1] > p->pArray[i] ) + return 0; + } + return 1; +} +static inline int Vec_IntIsOrderedCost( Vec_Int_t * p, Vec_Int_t * vCost, int fReverse ) +{ + int i; + if ( fReverse ) + { + for ( i = 1; i < p->nSize; i++ ) + if ( Vec_IntEntry(vCost, p->pArray[i-1]) < Vec_IntEntry(vCost, p->pArray[i]) ) + return 0; + } + else + { + for ( i = 1; i < p->nSize; i++ ) + if ( Vec_IntEntry(vCost, p->pArray[i-1]) > Vec_IntEntry(vCost, p->pArray[i]) ) + return 0; + } + return 1; +} + +/**Function************************************************************* + Synopsis [Inserts the entry while preserving the increasing order.] Description [] @@ -1078,6 +1154,17 @@ static inline int Vec_IntFindMax( Vec_Int_t * p ) Best = p->pArray[i]; return Best; } +static inline int Vec_IntArgMax( Vec_Int_t * p ) +{ + int i, Best, Arg = 0; + if ( p->nSize == 0 ) + return -1; + Best = p->pArray[0]; + for ( i = 1; i < p->nSize; i++ ) + if ( Best < p->pArray[i] ) + Best = p->pArray[i], Arg = i; + return Arg; +} /**Function************************************************************* @@ -1101,6 +1188,17 @@ static inline int Vec_IntFindMin( Vec_Int_t * p ) Best = p->pArray[i]; return Best; } +static inline int Vec_IntArgMin( Vec_Int_t * p ) +{ + int i, Best, Arg = 0; + if ( p->nSize == 0 ) + return 0; + Best = p->pArray[0]; + for ( i = 1; i < p->nSize; i++ ) + if ( Best > p->pArray[i] ) + Best = p->pArray[i], Arg = i; + return Arg; +} /**Function************************************************************* @@ -1277,6 +1375,26 @@ static inline int Vec_IntCountZero( Vec_Int_t * p ) /**Function************************************************************* + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntAddPositive( Vec_Int_t * p ) +{ + int i, Counter = 0; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] > 0 ) + Counter += p->pArray[i]; + return Counter; +} + +/**Function************************************************************* + Synopsis [Checks if two vectors are equal.] Description [] @@ -1296,6 +1414,19 @@ static inline int Vec_IntEqual( Vec_Int_t * p1, Vec_Int_t * p2 ) return 0; return 1; } +static inline int Vec_IntContained( Vec_Int_t * pSmall, Vec_Int_t * pLarge ) +{ + int i, k; + for ( i = 0; i < pSmall->nSize; i++ ) + { + for ( k = 0; k < pLarge->nSize; k++ ) + if ( pSmall->pArray[i] == pLarge->pArray[k] ) + break; + if ( k == pLarge->nSize ) + return 0; + } + return 1; +} /**Function************************************************************* @@ -1397,6 +1528,14 @@ static inline void Vec_IntSortMulti( Vec_Int_t * p, int nMulti, int fReverse ) qsort( (void *)p->pArray, (size_t)(p->nSize/nMulti), nMulti*sizeof(int), (int (*)(const void *, const void *)) Vec_IntSortCompare1 ); } +static inline int Vec_IntIsSorted( Vec_Int_t * p, int fReverse ) +{ + int i; + for ( i = 1; i < p->nSize; i++ ) + if ( fReverse ? (p->pArray[i-1] < p->pArray[i]) : (p->pArray[i-1] > p->pArray[i]) ) + return 0; + return 1; +} /**Function************************************************************* @@ -1795,6 +1934,70 @@ static inline int Vec_IntTwoRemove( Vec_Int_t * vArr1, Vec_Int_t * vArr2 ) Synopsis [Returns the result of merging the two vectors.] + Description [Keeps only those entries of vArr1, which are in vArr2.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntTwoMerge1( Vec_Int_t * vArr1, Vec_Int_t * vArr2 ) +{ + int * pBeg = vArr1->pArray; + int * pBeg1 = vArr1->pArray; + int * pBeg2 = vArr2->pArray; + int * pEnd1 = vArr1->pArray + vArr1->nSize; + int * pEnd2 = vArr2->pArray + vArr2->nSize; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( *pBeg1 == *pBeg2 ) + *pBeg++ = *pBeg1++, pBeg2++; + else if ( *pBeg1 < *pBeg2 ) + pBeg1++; + else + pBeg2++; + } + assert( vArr1->nSize >= pBeg - vArr1->pArray ); + vArr1->nSize = pBeg - vArr1->pArray; +} + +/**Function************************************************************* + + Synopsis [Returns the result of subtracting for two vectors.] + + Description [Keeps only those entries of vArr1, which are not in vArr2.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntTwoRemove1( Vec_Int_t * vArr1, Vec_Int_t * vArr2 ) +{ + int * pBeg = vArr1->pArray; + int * pBeg1 = vArr1->pArray; + int * pBeg2 = vArr2->pArray; + int * pEnd1 = vArr1->pArray + vArr1->nSize; + int * pEnd2 = vArr2->pArray + vArr2->nSize; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( *pBeg1 == *pBeg2 ) + pBeg1++, pBeg2++; + else if ( *pBeg1 < *pBeg2 ) + *pBeg++ = *pBeg1++; + else + pBeg2++; + } + while ( pBeg1 < pEnd1 ) + *pBeg++ = *pBeg1++; + assert( vArr1->nSize >= pBeg - vArr1->pArray ); + vArr1->nSize = pBeg - vArr1->pArray; +} + +/**Function************************************************************* + + Synopsis [Returns the result of merging the two vectors.] + Description [Assumes that the vectors are sorted in the increasing order.] SideEffects [] @@ -2032,6 +2235,13 @@ static inline int Vec_IntCompareVec( Vec_Int_t * p1, Vec_Int_t * p2 ) SeeAlso [] ***********************************************************************/ +static inline void Vec_IntClearAppend( Vec_Int_t * vVec1, Vec_Int_t * vVec2 ) +{ + int Entry, i; + Vec_IntClear( vVec1 ); + Vec_IntForEachEntry( vVec2, Entry, i ) + Vec_IntPush( vVec1, Entry ); +} static inline void Vec_IntAppend( Vec_Int_t * vVec1, Vec_Int_t * vVec2 ) { int Entry, i; @@ -2075,6 +2285,67 @@ static inline void Vec_IntRemapArray( Vec_Int_t * vOld2New, Vec_Int_t * vOld, Ve Vec_IntWriteEntry( vNew, iNew, Vec_IntEntry(vOld, iOld) ); } +/**Function************************************************************* + + Synopsis [File interface.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntDumpBin( char * pFileName, Vec_Int_t * p, int fVerbose ) +{ + int RetValue; + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + return; + } + RetValue = fwrite( Vec_IntArray(p), 1, sizeof(int)*Vec_IntSize(p), pFile ); + fclose( pFile ); + if ( RetValue != (int)sizeof(int)*Vec_IntSize(p) ) + printf( "Error reading data from file.\n" ); + if ( fVerbose ) + printf( "Written %d integers into file \"%s\".\n", Vec_IntSize(p), pFileName ); +} +static inline Vec_Int_t * Vec_IntReadBin( char * pFileName, int fVerbose ) +{ + Vec_Int_t * p = NULL; int nSize, RetValue; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return NULL; + } + fseek( pFile, 0, SEEK_END ); + nSize = ftell( pFile ); + if ( nSize == 0 ) + { + printf( "The input file is empty.\n" ); + fclose( pFile ); + return NULL; + } + if ( nSize % sizeof(int) > 0 ) + { + printf( "Cannot read file with integers because it is not aligned at 4 bytes (remainder = %d).\n", (int)(nSize % sizeof(int)) ); + fclose( pFile ); + return NULL; + } + rewind( pFile ); + p = Vec_IntStart( (int)(nSize/sizeof(int)) ); + RetValue = fread( Vec_IntArray(p), 1, nSize, pFile ); + fclose( pFile ); + if ( RetValue != nSize ) + printf( "Error reading data from file.\n" ); + if ( fVerbose ) + printf( "Read %d integers from file \"%s\".\n", (int)(nSize/sizeof(int)), pFileName ); + return p; +} + ABC_NAMESPACE_HEADER_END #endif diff --git a/src/misc/vec/vecPtr.h b/src/misc/vec/vecPtr.h index ed2a481e..0f024f68 100644 --- a/src/misc/vec/vecPtr.h +++ b/src/misc/vec/vecPtr.h @@ -607,6 +607,26 @@ static inline void Vec_PtrFreeFree( Vec_Ptr_t * p ) /**Function************************************************************* + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Vec_PtrFreeFunc( Vec_Ptr_t * p, void (*pFuncItemFree)(void *) ) ___unused; +static void Vec_PtrFreeFunc( Vec_Ptr_t * p, void (*pFuncItemFree)(void *) ) +{ + void * pItem; int i; + Vec_PtrForEachEntry( void *, p, pItem, i ) + if ( pItem ) pFuncItemFree( pItem ); + Vec_PtrFree( p ); +} + +/**Function************************************************************* + Synopsis [Copies the interger array.] Description [] @@ -626,6 +646,26 @@ static inline void Vec_PtrCopy( Vec_Ptr_t * pDest, Vec_Ptr_t * pSour ) /**Function************************************************************* + Synopsis [Print names stored in the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrPrintNames( Vec_Ptr_t * p ) +{ + char * pName; int i; + printf( "Vector has %d entries: {", Vec_PtrSize(p) ); + Vec_PtrForEachEntry( char *, p, pName, i ) + printf( "%s ", pName ); + printf( " }\n" ); +} + +/**Function************************************************************* + Synopsis [] Description [] @@ -651,6 +691,12 @@ static inline void Vec_PtrPushTwo( Vec_Ptr_t * p, void * Entry1, void * Entry2 ) Vec_PtrPush( p, Entry1 ); Vec_PtrPush( p, Entry2 ); } +static inline void Vec_PtrAppend( Vec_Ptr_t * vVec1, Vec_Ptr_t * vVec2 ) +{ + void * Entry; int i; + Vec_PtrForEachEntry( void *, vVec2, Entry, i ) + Vec_PtrPush( vVec1, Entry ); +} /**Function************************************************************* @@ -912,8 +958,8 @@ static int Vec_PtrSortComparePtr( void ** pp1, void ** pp2 ) SeeAlso [] ***********************************************************************/ -static void Vec_PtrSort( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() ) ___unused; -static void Vec_PtrSort( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() ) +static void Vec_PtrSort( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)(const void *, const void *) ) ___unused; +static void Vec_PtrSort( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)(const void *, const void *) ) { if ( p->nSize < 2 ) return; @@ -936,8 +982,8 @@ static void Vec_PtrSort( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() ) SeeAlso [] ***********************************************************************/ -static void Vec_PtrUniqify( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() ) ___unused; -static void Vec_PtrUniqify( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() ) +static void Vec_PtrUniqify( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)(const void *, const void *) ) ___unused; +static void Vec_PtrUniqify( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)(const void *, const void *) ) { int i, k; if ( p->nSize < 2 ) @@ -948,15 +994,15 @@ static void Vec_PtrUniqify( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() ) p->pArray[k++] = p->pArray[i]; p->nSize = k; } -static void Vec_PtrUniqify2( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)(void**, void**), void (*Vec_PtrObjFree)(void*), Vec_Int_t * vCounts ) ___unused; -static void Vec_PtrUniqify2( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)(void**, void**), void (*Vec_PtrObjFree)(void*), Vec_Int_t * vCounts ) +static void Vec_PtrUniqify2( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)(const void *, const void *), void (*Vec_PtrObjFree)(void*), Vec_Int_t * vCounts ) ___unused; +static void Vec_PtrUniqify2( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)(const void *, const void *), void (*Vec_PtrObjFree)(void*), Vec_Int_t * vCounts ) { int i, k; if ( vCounts ) Vec_IntFill( vCounts, 1, 1 ); if ( p->nSize < 2 ) return; - Vec_PtrSort( p, (int (*)())Vec_PtrSortCompare ); + Vec_PtrSort( p, Vec_PtrSortCompare ); for ( i = k = 1; i < p->nSize; i++ ) if ( Vec_PtrSortCompare(p->pArray+i, p->pArray+k-1) != 0 ) { diff --git a/src/misc/vec/vecQue.h b/src/misc/vec/vecQue.h index 54a10a29..6a8a68d0 100644 --- a/src/misc/vec/vecQue.h +++ b/src/misc/vec/vecQue.h @@ -119,6 +119,10 @@ static inline void Vec_QueClear( Vec_Que_t * p ) } p->nSize = 1; } +static inline double Vec_QueMemory( Vec_Que_t * p ) +{ + return !p ? 0.0 : 2.0 * sizeof(int) * (size_t)p->nCap + sizeof(Vec_Que_t) ; +} /**Function************************************************************* diff --git a/src/misc/vec/vecStr.h b/src/misc/vec/vecStr.h index 12053d3d..16e15761 100644 --- a/src/misc/vec/vecStr.h +++ b/src/misc/vec/vecStr.h @@ -561,6 +561,11 @@ static inline void Vec_StrPush( Vec_Str_t * p, char Entry ) } p->pArray[p->nSize++] = Entry; } +static inline void Vec_StrPushTwo( Vec_Str_t * p, char Entry1, char Entry2 ) +{ + Vec_StrPush( p, Entry1 ); + Vec_StrPush( p, Entry2 ); +} static inline void Vec_StrPushBuffer( Vec_Str_t * p, char * pBuffer, int nSize ) { if ( p->nSize + nSize > p->nCap ) diff --git a/src/misc/vec/vecWec.h b/src/misc/vec/vecWec.h index fdbded9c..cd463e01 100644 --- a/src/misc/vec/vecWec.h +++ b/src/misc/vec/vecWec.h @@ -275,6 +275,13 @@ static inline void Vec_WecClear( Vec_Wec_t * p ) Vec_IntClear( vVec ); p->nSize = 0; } +static inline void Vec_WecClearLevels( Vec_Wec_t * p ) +{ + Vec_Int_t * vVec; + int i; + Vec_WecForEachLevel( p, vVec, i ) + Vec_IntClear( vVec ); +} /**Function************************************************************* @@ -296,6 +303,15 @@ static inline void Vec_WecPush( Vec_Wec_t * p, int Level, int Entry ) } Vec_IntPush( Vec_WecEntry(p, Level), Entry ); } +static inline void Vec_WecPushTwo( Vec_Wec_t * p, int Level, int Entry1, int Entry2 ) +{ + if ( p->nSize < Level + 1 ) + { + Vec_WecGrow( p, Abc_MaxInt(2*p->nSize, Level + 1) ); + p->nSize = Level + 1; + } + Vec_IntPushTwo( Vec_WecEntry(p, Level), Entry1, Entry2 ); +} static inline Vec_Int_t * Vec_WecPushLevel( Vec_Wec_t * p ) { if ( p->nSize == p->nCap ) @@ -422,7 +438,7 @@ static inline Vec_Wec_t * Vec_WecDup( Vec_Wec_t * p ) Vec_Wec_t * vNew; Vec_Int_t * vVec; int i, k, Entry; - vNew = Vec_WecAlloc( Vec_WecSize(p) ); + vNew = Vec_WecStart( Vec_WecSize(p) ); Vec_WecForEachLevel( p, vVec, i ) Vec_IntForEachEntry( vVec, Entry, k ) Vec_WecPush( vNew, i, Entry ); @@ -552,6 +568,29 @@ static inline void Vec_WecSortByLastInt( Vec_Wec_t * p, int fReverse ) SeeAlso [] ***********************************************************************/ +static inline void Vec_WecKeepLevels( Vec_Wec_t * p, int Limit ) +{ + Vec_Int_t * vLevel; int i, k = 0; + Vec_WecForEachLevel( p, vLevel, i ) + if ( Vec_IntSize(vLevel) > Limit ) + { + ABC_SWAP( Vec_Int_t, Vec_WecArray(p)[i], Vec_WecArray(p)[k] ); + k++; + } + Vec_WecShrink( p, k ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ static inline void Vec_WecPrint( Vec_Wec_t * p, int fSkipSingles ) { Vec_Int_t * vVec; @@ -637,6 +676,25 @@ static inline int Vec_WecCountNonTrivial( Vec_Wec_t * p, int * pnUsed ) SeeAlso [] ***********************************************************************/ +static inline int Vec_WecMaxLevelSize( Vec_Wec_t * p ) +{ + Vec_Int_t * vTemp; int i, Res = 0; + Vec_WecForEachLevel( p, vTemp, i ) + Res = Abc_MaxInt( Res, Vec_IntSize(vTemp) ); + return Res; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ static inline Vec_Int_t * Vec_WecCollectFirsts( Vec_Wec_t * p ) { Vec_Int_t * vFirsts, * vLevel; @@ -733,6 +791,83 @@ static inline void Vec_WecRemoveEmpty( Vec_Wec_t * vCubes ) } +/**Function************************************************************* + + Synopsis [File interface.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_WecDumpBin( char * pFileName, Vec_Wec_t * p, int fVerbose ) +{ + Vec_Int_t * vLevel; + int i, nSize, RetValue; + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + return; + } + nSize = Vec_WecSize(p); + RetValue = fwrite( &nSize, 1, sizeof(int), pFile ); + Vec_WecForEachLevel( p, vLevel, i ) + { + nSize = Vec_IntSize(vLevel); + RetValue += fwrite( &nSize, 1, sizeof(int), pFile ); + RetValue += fwrite( Vec_IntArray(vLevel), 1, sizeof(int)*nSize, pFile ); + } + fclose( pFile ); + if ( RetValue != (int)sizeof(int)*(Vec_WecSizeSize(p)+Vec_WecSize(p)+1) ) + printf( "Error writing data into file.\n" ); + if ( fVerbose ) + printf( "Written %d integer arrays into file \"%s\".\n", Vec_WecSize(p), pFileName ); +} +static inline Vec_Wec_t * Vec_WecReadBin( char * pFileName, int fVerbose ) +{ + Vec_Wec_t * p = NULL; Vec_Int_t * vLevel; int i, nSize, RetValue; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return NULL; + } + fseek( pFile, 0, SEEK_END ); + nSize = ftell( pFile ); + if ( nSize == 0 ) + { + printf( "The input file is empty.\n" ); + fclose( pFile ); + return NULL; + } + if ( nSize % sizeof(int) > 0 ) + { + printf( "Cannot read file with integers because it is not aligned at 4 bytes (remainder = %d).\n", (int)(nSize % sizeof(int)) ); + fclose( pFile ); + return NULL; + } + rewind( pFile ); + RetValue = fread( &nSize, 1, sizeof(int), pFile ); + assert( RetValue == 4 ); + p = Vec_WecStart( nSize ); + Vec_WecForEachLevel( p, vLevel, i ) + { + RetValue = fread( &nSize, 1, sizeof(int), pFile ); + assert( RetValue == 4 ); + Vec_IntFill( vLevel, nSize, 0 ); + RetValue = fread( Vec_IntArray(vLevel), 1, sizeof(int)*nSize, pFile ); + assert( RetValue == 4*nSize ); + } + fclose( pFile ); + if ( fVerbose ) + printf( "Read %d integer arrays from file \"%s\".\n", Vec_WecSize(p), pFileName ); + return p; +} + + ABC_NAMESPACE_HEADER_END #endif diff --git a/src/misc/vec/vecWrd.h b/src/misc/vec/vecWrd.h index e123c054..8275702a 100644 --- a/src/misc/vec/vecWrd.h +++ b/src/misc/vec/vecWrd.h @@ -61,6 +61,8 @@ struct Vec_Wrd_t_ for ( i = Start; (i < Stop) && (((Entry) = Vec_WrdEntry(vVec, i)), 1); i++ ) #define Vec_WrdForEachEntryReverse( vVec, pEntry, i ) \ for ( i = Vec_WrdSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_WrdEntry(vVec, i)), 1); i-- ) +#define Vec_WrdForEachEntryDouble( vVec, Entry1, Entry2, i ) \ + for ( i = 0; (i+1 < Vec_WrdSize(vVec)) && (((Entry1) = Vec_WrdEntry(vVec, i)), 1) && (((Entry2) = Vec_WrdEntry(vVec, i+1)), 1); i += 2 ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -167,6 +169,32 @@ static inline Vec_Wrd_t * Vec_WrdStartRandom( int nSize ) vSims->pArray[i] = Abc_RandomW(0); return vSims; } +static inline Vec_Wrd_t * Vec_WrdStartTruthTables( int nVars ) +{ + Vec_Wrd_t * p; + unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + int i, k, nWords; + nWords = nVars <= 6 ? 1 : (1 << (nVars - 6)); + p = Vec_WrdStart( nWords * nVars ); + for ( i = 0; i < nVars; i++ ) + { + unsigned * pTruth = (unsigned *)(p->pArray + nWords * i); + if ( i < 5 ) + { + for ( k = 0; k < 2*nWords; k++ ) + pTruth[k] = Masks[i]; + } + else + { + for ( k = 0; k < 2*nWords; k++ ) + if ( k & (1 << (i-5)) ) + pTruth[k] = ~(unsigned)0; + else + pTruth[k] = 0; + } + } + return p; +} /**Function************************************************************* @@ -354,6 +382,10 @@ static inline int Vec_WrdSize( Vec_Wrd_t * p ) { return p->nSize; } +static inline int Vec_WrdChangeSize( Vec_Wrd_t * p, int Shift ) +{ + return p->nSize += Shift; +} /**Function************************************************************* @@ -643,6 +675,30 @@ static inline void Vec_WrdPush( Vec_Wrd_t * p, word Entry ) } p->pArray[p->nSize++] = Entry; } +static inline void Vec_WrdPushTwo( Vec_Wrd_t * p, word Entry1, word Entry2 ) +{ + Vec_WrdPush( p, Entry1 ); + Vec_WrdPush( p, Entry2 ); +} +static inline void Vec_WrdPushThree( Vec_Wrd_t * p, word Entry1, word Entry2, word Entry3 ) +{ + Vec_WrdPush( p, Entry1 ); + Vec_WrdPush( p, Entry2 ); + Vec_WrdPush( p, Entry3 ); +} +static inline void Vec_WrdPushFour( Vec_Wrd_t * p, word Entry1, word Entry2, word Entry3, word Entry4 ) +{ + Vec_WrdPush( p, Entry1 ); + Vec_WrdPush( p, Entry2 ); + Vec_WrdPush( p, Entry3 ); + Vec_WrdPush( p, Entry4 ); +} +static inline void Vec_WrdPushArray( Vec_Wrd_t * p, word * pEntries, int nEntries ) +{ + int i; + for ( i = 0; i < nEntries; i++ ) + Vec_WrdPush( p, pEntries[i] ); +} /**Function************************************************************* @@ -851,6 +907,14 @@ static inline void Vec_WrdInsert( Vec_Wrd_t * p, int iHere, word Entry ) p->pArray[i] = p->pArray[i-1]; p->pArray[i] = Entry; } +static inline void Vec_WrdDrop( Vec_Wrd_t * p, int i ) +{ + int k; + assert( i >= 0 && i < Vec_WrdSize(p) ); + p->nSize--; + for ( k = i; k < p->nSize; k++ ) + p->pArray[k] = p->pArray[k+1]; +} /**Function************************************************************* @@ -1201,6 +1265,169 @@ static inline void Vec_WrdAppend( Vec_Wrd_t * vVec1, Vec_Wrd_t * vVec2 ) Vec_WrdPush( vVec1, Entry ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSimPatWriteOne( FILE * pFile, word * pSim, int nWords ) +{ + int k, Digit, nDigits = nWords*16; + for ( k = 0; k < nDigits; k++ ) + { + Digit = (int)((pSim[k/16] >> ((k%16) * 4)) & 15); + if ( Digit < 10 ) + fprintf( pFile, "%d", Digit ); + else + fprintf( pFile, "%c", 'A' + Digit-10 ); + } + fprintf( pFile, "\n" ); +} +static inline void Vec_WrdPrintHex( Vec_Wrd_t * p, int nWords ) +{ + int i, nNodes = Vec_WrdSize(p) / nWords; + assert( Vec_WrdSize(p) % nWords == 0 ); + for ( i = 0; i < nNodes; i++ ) + Gia_ManSimPatWriteOne( stdout, Vec_WrdEntryP(p, i*nWords), nWords ); +} +static inline void Vec_WrdDumpHex( char * pFileName, Vec_Wrd_t * p, int nWords, int fVerbose ) +{ + int i, nNodes = Vec_WrdSize(p) / nWords; + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + return; + } + assert( Vec_WrdSize(p) % nWords == 0 ); + for ( i = 0; i < nNodes; i++ ) + Gia_ManSimPatWriteOne( pFile, Vec_WrdEntryP(p, i*nWords), nWords ); + fclose( pFile ); + if ( fVerbose ) + printf( "Written %d words of simulation data for %d objects into file \"%s\".\n", nWords, Vec_WrdSize(p)/nWords, pFileName ); +} +static inline int Vec_WrdReadHexOne( char c ) +{ + int Digit = 0; + if ( c >= '0' && c <= '9' ) + Digit = c - '0'; + else if ( c >= 'A' && c <= 'F' ) + Digit = c - 'A' + 10; + else if ( c >= 'a' && c <= 'f' ) + Digit = c - 'a' + 10; + else assert( 0 ); + assert( Digit >= 0 && Digit < 16 ); + return Digit; +} +static inline Vec_Wrd_t * Vec_WrdReadHex( char * pFileName, int * pnWords, int fVerbose ) +{ + Vec_Wrd_t * p = NULL; + int c, nWords = -1, nChars = 0; word Num = 0; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return NULL; + } + p = Vec_WrdAlloc( 1000 ); + while ( (c = fgetc(pFile)) != EOF ) + { + if ( c == '\r' || c == '\t' || c == ' ' ) + continue; + if ( c == '\n' ) + { + if ( nChars > 0 ) + { + Vec_WrdPush( p, Num ); + nChars = 0; + Num = 0; + } + if ( nWords == -1 && Vec_WrdSize(p) > 0 ) + nWords = Vec_WrdSize(p); + continue; + } + Num |= (word)Vec_WrdReadHexOne((char)c) << (nChars * 4); + if ( ++nChars < 16 ) + continue; + Vec_WrdPush( p, Num ); + nChars = 0; + Num = 0; + } + assert( Vec_WrdSize(p) % nWords == 0 ); + fclose( pFile ); + if ( pnWords ) + *pnWords = nWords; + if ( fVerbose ) + printf( "Read %d words of simulation data for %d objects.\n", nWords, Vec_WrdSize(p)/nWords ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_WrdDumpBin( char * pFileName, Vec_Wrd_t * p, int fVerbose ) +{ + int RetValue; + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + return; + } + RetValue = fwrite( Vec_WrdArray(p), 1, 8*Vec_WrdSize(p), pFile ); + fclose( pFile ); + if ( RetValue != 8*Vec_WrdSize(p) ) + printf( "Error reading data from file.\n" ); + if ( fVerbose ) + printf( "Written %d words of simulation data into file \"%s\".\n", Vec_WrdSize(p), pFileName ); +} +static inline Vec_Wrd_t * Vec_WrdReadBin( char * pFileName, int fVerbose ) +{ + Vec_Wrd_t * p = NULL; int nSize, RetValue; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return NULL; + } + fseek( pFile, 0, SEEK_END ); + nSize = ftell( pFile ); + if ( nSize == 0 ) + { + printf( "The input file is empty.\n" ); + fclose( pFile ); + return NULL; + } + if ( nSize % 8 > 0 ) + { + printf( "Cannot read file with simulation data that is not aligned at 8 bytes (remainder = %d).\n", nSize % 8 ); + fclose( pFile ); + return NULL; + } + rewind( pFile ); + p = Vec_WrdStart( nSize/8 ); + RetValue = fread( Vec_WrdArray(p), 1, nSize, pFile ); + fclose( pFile ); + if ( RetValue != nSize ) + printf( "Error reading data from file.\n" ); + if ( fVerbose ) + printf( "Read %d words of simulation data from file \"%s\".\n", nSize/8, pFileName ); + return p; +} ABC_NAMESPACE_HEADER_END diff --git a/src/opt/cgt/cgtAig.c b/src/opt/cgt/cgtAig.c index 9421b75e..2a3b342c 100644 --- a/src/opt/cgt/cgtAig.c +++ b/src/opt/cgt/cgtAig.c @@ -133,7 +133,7 @@ void Cgt_ManDetectFanout( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_P Vec_PtrWriteEntry( vFanout, k++, pObj ); } Vec_PtrShrink( vFanout, k ); - Vec_PtrSort( vFanout, (int (*)(void))Aig_ObjCompareIdIncrease ); + Vec_PtrSort( vFanout, (int (*)(const void *, const void *))Aig_ObjCompareIdIncrease ); assert( Vec_PtrSize(vFanout) > 0 ); } diff --git a/src/opt/dar/darBalance.c b/src/opt/dar/darBalance.c index f51a7852..d8195762 100644 --- a/src/opt/dar/darBalance.c +++ b/src/opt/dar/darBalance.c @@ -59,7 +59,7 @@ void Dar_BalanceUniqify( Aig_Obj_t * pObj, Vec_Ptr_t * vNodes, int fExor ) Aig_Obj_t * pTemp, * pTempNext; int i, k; // sort the nodes by their literal - Vec_PtrSort( vNodes, (int (*)())Dar_ObjCompareLits ); + Vec_PtrSort( vNodes, (int (*)(const void *, const void *))Dar_ObjCompareLits ); // remove duplicates k = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pTemp, i ) @@ -402,7 +402,7 @@ Aig_Obj_t * Dar_BalanceBuildSuper( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t int LeftBound; assert( vSuper->nSize > 1 ); // sort the new nodes by level in the decreasing order - Vec_PtrSort( vSuper, (int (*)(void))Aig_NodeCompareLevelsDecrease ); + Vec_PtrSort( vSuper, (int (*)(const void *, const void *))Aig_NodeCompareLevelsDecrease ); // balance the nodes while ( vSuper->nSize > 1 ) { @@ -415,7 +415,7 @@ Aig_Obj_t * Dar_BalanceBuildSuper( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t pObj2 = (Aig_Obj_t *)Vec_PtrPop(vSuper); Dar_BalancePushUniqueOrderByLevel( vSuper, Aig_Oper(p, pObj1, pObj2, Type), Type == AIG_OBJ_EXOR ); } - return (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0); + return vSuper->nSize ? (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0) : Aig_ManConst0(p); } @@ -462,7 +462,7 @@ Aig_Obj_t * Dar_BalanceBuildSuperTop( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Typ int i, nBaseSizeAll, nBaseSize; assert( vSuper->nSize > 1 ); // sort the new nodes by level in the decreasing order - Vec_PtrSort( vSuper, (int (*)(void))Aig_NodeCompareLevelsDecrease ); + Vec_PtrSort( vSuper, (int (*)(const void *, const void *))Aig_NodeCompareLevelsDecrease ); // add one LUT at a time while ( Vec_PtrSize(vSuper) > 1 ) { diff --git a/src/opt/dar/darScript.c b/src/opt/dar/darScript.c index f8fa3788..d95c23d7 100644 --- a/src/opt/dar/darScript.c +++ b/src/opt/dar/darScript.c @@ -848,6 +848,7 @@ pPars->timeSynth = Abc_Clock() - clk; ***********************************************************************/ Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ) { + extern Aig_Man_t * Cec_ComputeChoicesNew( Gia_Man_t * pGia, int nConfs, int fVerbose ); extern Aig_Man_t * Cec_ComputeChoices( Gia_Man_t * pGia, Dch_Pars_t * pPars ); // extern Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs ); extern Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars ); @@ -870,15 +871,17 @@ clk = Abc_Clock(); pPars->timeSynth = Abc_Clock() - clk; // perform choice computation - if ( pPars->fUseGia ) + if ( pPars->fUseNew ) + pMan = Cec_ComputeChoicesNew( pGia, pPars->nBTLimit, pPars->fVerbose ); + else if ( pPars->fUseGia ) pMan = Cec_ComputeChoices( pGia, pPars ); else { pMan = Gia_ManToAigSkip( pGia, 3 ); - Gia_ManStop( pGia ); pMan = Dch_ComputeChoices( pTemp = pMan, pPars ); Aig_ManStop( pTemp ); } + Gia_ManStop( pGia ); // create guidence vPios = Aig_ManOrderPios( pMan, pAig ); diff --git a/src/opt/dau/dauDsd.c b/src/opt/dau/dauDsd.c index b1e7e0d8..3e11a15d 100644 --- a/src/opt/dau/dauDsd.c +++ b/src/opt/dau/dauDsd.c @@ -1973,6 +1973,14 @@ void Dau_DsdPrintFromTruth( word * pTruth, int nVarsInit ) Dau_DsdDecompose( pTemp, nVarsInit, 0, 1, pRes ); fprintf( stdout, "%s\n", pRes ); } +void Dau_DsdPrintFromTruth2( word * pTruth, int nVarsInit ) +{ + char pRes[DAU_MAX_STR]; + word pTemp[DAU_MAX_WORD]; + Abc_TtCopy( pTemp, pTruth, Abc_TtWordNum(nVarsInit), 0 ); + Dau_DsdDecompose( pTemp, nVarsInit, 0, 1, pRes ); + fprintf( stdout, "%s", pRes ); +} void Dau_DsdTest44() { diff --git a/src/opt/fxch/FxchSCHashTable.c b/src/opt/fxch/FxchSCHashTable.c index 28f925e1..c574509f 100644 --- a/src/opt/fxch/FxchSCHashTable.c +++ b/src/opt/fxch/FxchSCHashTable.c @@ -17,6 +17,10 @@ ***********************************************************************/ #include "Fxch.h" +#if (__GNUC__ >= 8) + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif + ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// diff --git a/src/opt/fxu/fxuReduce.c b/src/opt/fxu/fxuReduce.c index 7542a432..84e2bf87 100644 --- a/src/opt/fxu/fxuReduce.c +++ b/src/opt/fxu/fxuReduce.c @@ -86,8 +86,7 @@ int Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTota assert( iPair == nPairsTotal ); // allocate storage for counters of cube pairs by difference - pnPairCounters = ABC_FALLOC( int, 2 * nBitsMax ); - memset( pnPairCounters, 0, sizeof(int) * 2 * nBitsMax ); + pnPairCounters = ABC_CALLOC( int, 2 * nBitsMax ); // count the number of different pairs for ( k = 0; k < nPairsTotal; k++ ) pnPairCounters[ pnLitsDiff[k] ]++; diff --git a/src/opt/mfs/mfsDiv.c b/src/opt/mfs/mfsDiv.c index ece8ec64..535e8d23 100644 --- a/src/opt/mfs/mfsDiv.c +++ b/src/opt/mfs/mfsDiv.c @@ -282,7 +282,7 @@ Vec_Ptr_t * Abc_MfsComputeDivisors( Mfs_Man_t * p, Abc_Obj_t * pNode, int nLevDi p->nMaxDivs += (Vec_PtrSize(vDivs) >= p->pPars->nWinMax); // sort the divisors by level in the increasing order - Vec_PtrSort( vDivs, (int (*)(void))Abc_NodeCompareLevelsIncrease ); + Vec_PtrSort( vDivs, (int (*)(const void *, const void *))Abc_NodeCompareLevelsIncrease ); // add the fanins of the node Abc_ObjForEachFanin( pNode, pFanin, k ) diff --git a/src/opt/sbd/sbdCut2.c b/src/opt/sbd/sbdCut2.c index b4a8be74..b9ef4d82 100644 --- a/src/opt/sbd/sbdCut2.c +++ b/src/opt/sbd/sbdCut2.c @@ -193,7 +193,7 @@ static inline int Sbd_ManCutExpandOne( Gia_Man_t * p, Vec_Int_t * vMirrors, Vec_ Vec_IntPushOrder( vCut, Fan1 ); return 1; } -void Vec_IntIsOrdered( Vec_Int_t * vCut ) +void Vec_IntOrdered( Vec_Int_t * vCut ) { int i, Prev, Entry; Prev = Vec_IntEntry( vCut, 0 ); @@ -229,7 +229,7 @@ void Sbd_ManCutReload( Vec_Int_t * vMirrors, Vec_Int_t * vLutLevs, int LevStop, else Vec_IntPush( vCutBot, Entry ); } - Vec_IntIsOrdered( vCut ); + Vec_IntOrdered( vCut ); } int Sbd_ManCutCollect_rec( Gia_Man_t * p, Vec_Int_t * vMirrors, int iObj, int LevStop, Vec_Int_t * vLutLevs, Vec_Int_t * vCut ) { @@ -267,7 +267,7 @@ int Sbd_ManCutReduceTop( Gia_Man_t * p, Vec_Int_t * vMirrors, int iObj, Vec_Int_ { int i, Entry, Lit0m, Lit1m, Fan0, Fan1; int LevStop = Vec_IntEntry(vLutLevs, iObj) - 2; - Vec_IntIsOrdered( vCut ); + Vec_IntOrdered( vCut ); Vec_IntForEachEntryReverse( vCutTop, Entry, i ) { Gia_Obj_t * pObj = Gia_ManObj( p, Entry ); diff --git a/src/opt/sfm/sfm.h b/src/opt/sfm/sfm.h index 1aa8b7d0..f9c95c83 100644 --- a/src/opt/sfm/sfm.h +++ b/src/opt/sfm/sfm.h @@ -66,6 +66,7 @@ struct Sfm_Par_t_ int fUseAndOr; // enable internal detection of AND/OR gates int fZeroCost; // enable zero-cost replacement int fUseSim; // enable simulation + int fUseDcs; // enable deriving don't-cares int fPrintDecs; // enable printing decompositions int fAllBoxes; // enable preserving all boxes int fLibVerbose; // enable library stats diff --git a/src/opt/sfm/sfmCore.c b/src/opt/sfm/sfmCore.c index 27d584b4..356aea35 100644 --- a/src/opt/sfm/sfmCore.c +++ b/src/opt/sfm/sfmCore.c @@ -19,6 +19,7 @@ ***********************************************************************/ #include "sfmInt.h" +#include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START @@ -79,6 +80,8 @@ void Sfm_NtkPrintStats( Sfm_Ntk_t * p ) printf( "Attempts : " ); printf( "Remove %6d out of %6d (%6.2f %%) ", p->nRemoves, p->nTryRemoves, 100.0*p->nRemoves/Abc_MaxInt(1, p->nTryRemoves) ); printf( "Resub %6d out of %6d (%6.2f %%) ", p->nResubs, p->nTryResubs, 100.0*p->nResubs /Abc_MaxInt(1, p->nTryResubs) ); + if ( p->pPars->fUseDcs ) + printf( "Improves %6d out of %6d (%6.2f %%) ", p->nImproves,p->nTryImproves,100.0*p->nImproves/Abc_MaxInt(1, p->nTryImproves)); printf( "\n" ); printf( "Reduction: " ); @@ -213,7 +216,69 @@ finish: // update the network Sfm_NtkUpdate( p, iNode, f, (iVar == -1 ? iVar : Vec_IntEntry(p->vDivs, iVar)), uTruth ); return 1; - } +} + +/**Function************************************************************* + + Synopsis [Performs resubstitution for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sfm_NodeResubOne( Sfm_Ntk_t * p, int iNode ) +{ + int fSkipUpdate = 0; + int i, iFanin; + word uTruth; + abctime clk; + assert( Sfm_ObjIsNode(p, iNode) ); + p->nTryImproves++; + // report init stats + if ( p->pPars->fVeryVerbose ) + printf( "%5d : Lev =%3d. Leaf =%3d. Node =%3d. Div=%3d. Fanins = %d. MFFC = %d\n", + iNode, Sfm_ObjLevel(p, iNode), 0, Vec_IntSize(p->vNodes), Vec_IntSize(p->vDivs), + Sfm_ObjFaninNum(p, iNode), Sfm_ObjMffcSize(p, iNode) ); + // collect fanins + Vec_IntClear( p->vDivIds ); + Sfm_ObjForEachFanin( p, iNode, iFanin, i ) + Vec_IntPush( p->vDivIds, Sfm_ObjSatVar(p, iFanin) ); +clk = Abc_Clock(); + uTruth = Sfm_ComputeInterpolant2( p ); +p->timeSat += Abc_Clock() - clk; + // analyze outcomes + if ( uTruth == SFM_SAT_UNDEC ) + { + p->nTimeOuts++; + return 0; + } + assert( uTruth != SFM_SAT_SAT ); + if ( uTruth == Vec_WrdEntry(p->vTruths, iNode) ) + return 0; + else + { + word uTruth0 = Vec_WrdEntry(p->vTruths, iNode); + //word uTruth0N = ~uTruth0; + //word uTruthN = ~uTruth; + int Old = Kit_TruthLitNum((unsigned*)&uTruth0, Sfm_ObjFaninNum(p, iNode), p->vCover); + //int OldN = Kit_TruthLitNum((unsigned*)&uTruth0N, Sfm_ObjFaninNum(p, iNode), p->vCover); + int New = Kit_TruthLitNum((unsigned*)&uTruth, Sfm_ObjFaninNum(p, iNode), p->vCover); + //int NewN = Kit_TruthLitNum((unsigned*)&uTruthN, Sfm_ObjFaninNum(p, iNode), p->vCover); + //if ( Abc_MinInt(New, NewN) > Abc_MinInt(Old, OldN) ) + if ( New > Old ) + return 0; + } + p->nImproves++; + if ( fSkipUpdate ) + return 0; + // update truth table + Vec_WrdWriteEntry( p->vTruths, iNode, uTruth ); + Sfm_TruthToCnf( uTruth, NULL, Sfm_ObjFaninNum(p, iNode), p->vCover, (Vec_Str_t *)Vec_WecEntry(p->vCnfs, iNode) ); + return 1; +} int Sfm_NodeResub( Sfm_Ntk_t * p, int iNode ) { int i, iFanin; @@ -230,15 +295,18 @@ int Sfm_NodeResub( Sfm_Ntk_t * p, int iNode ) if ( Sfm_NodeResubSolve( p, iNode, i, 0 ) ) return 1; } - if ( p->pPars->fArea ) - return 0; // try removing redundant edges + if ( !p->pPars->fArea ) Sfm_ObjForEachFanin( p, iNode, iFanin, i ) if ( !(Sfm_ObjIsNode(p, iFanin) && Sfm_ObjFanoutNum(p, iFanin) == 1) ) { if ( Sfm_NodeResubSolve( p, iNode, i, 1 ) ) return 1; } + // try simplifying local functions + if ( p->pPars->fUseDcs ) + if ( Sfm_NodeResubOne( p, iNode ) ) + return 1; /* // try replacing area critical fanins while adding two new fanins if ( Sfm_ObjFaninNum(p, iNode) < p->nFaninMax ) diff --git a/src/opt/sfm/sfmInt.h b/src/opt/sfm/sfmInt.h index 80edd54d..08edf353 100644 --- a/src/opt/sfm/sfmInt.h +++ b/src/opt/sfm/sfmInt.h @@ -107,8 +107,10 @@ struct Sfm_Ntk_t_ sat_solver * pSat; // SAT solver int nSatVars; // the number of variables int nTryRemoves; // number of fanin removals + int nTryImproves;// number of node improvements int nTryResubs; // number of resubstitutions int nRemoves; // number of fanin removals + int nImproves; // number of node improvements int nResubs; // number of resubstitutions // counter-examples int nCexes; // number of CEXes @@ -218,6 +220,7 @@ extern void Sfm_NtkUpdate( Sfm_Ntk_t * p, int iNode, int f, int iFaninNe /*=== sfmSat.c ==========================================================*/ extern int Sfm_NtkWindowToSolver( Sfm_Ntk_t * p ); extern word Sfm_ComputeInterpolant( Sfm_Ntk_t * p ); +extern word Sfm_ComputeInterpolant2( Sfm_Ntk_t * p ); /*=== sfmTim.c ==========================================================*/ extern Sfm_Tim_t * Sfm_TimStart( Mio_Library_t * pLib, Scl_Con_t * pExt, Abc_Ntk_t * pNtk, int DeltaCrit ); extern void Sfm_TimStop( Sfm_Tim_t * p ); diff --git a/src/opt/sfm/sfmSat.c b/src/opt/sfm/sfmSat.c index 6ccdd903..ed38e681 100644 --- a/src/opt/sfm/sfmSat.c +++ b/src/opt/sfm/sfmSat.c @@ -19,6 +19,7 @@ ***********************************************************************/ #include "sfmInt.h" +#include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START @@ -27,15 +28,6 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static word s_Truths6[6] = { - ABC_CONST(0xAAAAAAAAAAAAAAAA), - ABC_CONST(0xCCCCCCCCCCCCCCCC), - ABC_CONST(0xF0F0F0F0F0F0F0F0), - ABC_CONST(0xFF00FF00FF00FF00), - ABC_CONST(0xFFFF0000FFFF0000), - ABC_CONST(0xFFFFFFFF00000000) -}; - //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -228,6 +220,100 @@ word Sfm_ComputeInterpolant( Sfm_Ntk_t * p ) /**Function************************************************************* + Synopsis [Takes SAT solver and returns interpolant.] + + Description [If interpolant does not exist, records difference variables.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sfm_ComputeInterpolantInt( Sfm_Ntk_t * p, word Truth[2] ) +{ + int fOnSet, iMint, iVar, nVars = sat_solver_nvars( p->pSat ); + int iVarPivot = Sfm_ObjSatVar( p, p->iPivotNode ); + int status, iNewLit, i, Div, nIter = 0; + Truth[0] = Truth[1] = 0; + sat_solver_setnvars( p->pSat, nVars + 1 ); + iNewLit = Abc_Var2Lit( nVars, 0 ); // iNewLit + assert( Vec_IntSize(p->vDivIds) <= 6 ); + Vec_IntFill( p->vValues, (1 << Vec_IntSize(p->vDivIds)) * Vec_IntSize(p->vDivVars), -1 ); + while ( 1 ) + { + // find care minterm + p->nSatCalls++; nIter++; + status = sat_solver_solve( p->pSat, &iNewLit, &iNewLit + 1, p->pPars->nBTLimit, 0, 0, 0 ); + if ( status == l_Undef ) + return l_Undef; + if ( status == l_False ) + return l_False; + assert( status == l_True ); + // collect values + iMint = 0; + fOnSet = sat_solver_var_value(p->pSat, iVarPivot); + Vec_IntClear( p->vLits ); + Vec_IntPush( p->vLits, Abc_LitNot(iNewLit) ); // NOT(iNewLit) + Vec_IntPush( p->vLits, Abc_LitNot(sat_solver_var_literal(p->pSat, iVarPivot)) ); + Vec_IntForEachEntry( p->vDivIds, Div, i ) + { + Vec_IntPush( p->vLits, Abc_LitNot(sat_solver_var_literal(p->pSat, Div)) ); + if ( sat_solver_var_value(p->pSat, Div) ) + iMint |= 1 << i; + } + if ( Truth[!fOnSet] & ((word)1 << iMint) ) + break; + assert( !(Truth[fOnSet] & ((word)1 << iMint)) ); + Truth[fOnSet] |= ((word)1 << iMint); + // remember variable values + Vec_IntForEachEntry( p->vDivVars, iVar, i ) + Vec_IntWriteEntry( p->vValues, iMint * Vec_IntSize(p->vDivVars) + i, sat_solver_var_value(p->pSat, iVar) ); + status = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntArray(p->vLits) + Vec_IntSize(p->vLits) ); + if ( status == 0 ) + return l_False; + } + assert( status == l_True ); + // store the counter-example + assert( iMint < (1 << Vec_IntSize(p->vDivIds)) ); + Vec_IntForEachEntry( p->vDivVars, iVar, i ) + { + int Value = Vec_IntEntry(p->vValues, iMint * Vec_IntSize(p->vDivVars) + i); + assert( Value != -1 ); + if ( Value ^ sat_solver_var_value(p->pSat, iVar) ) // insert 1 + { + word * pSign = Vec_WrdEntryP( p->vDivCexes, i ); + assert( !Abc_InfoHasBit( (unsigned *)pSign, p->nCexes) ); + Abc_InfoXorBit( (unsigned *)pSign, p->nCexes ); + } + } + p->nCexes++; + return l_True; +} +word Sfm_ComputeInterpolant2( Sfm_Ntk_t * p ) +{ + word Res, ResP, ResN, Truth[2]; + int nCubesP = 0, nCubesN = 0; + int RetValue = Sfm_ComputeInterpolantInt( p, Truth ); + if ( RetValue == l_Undef ) + return SFM_SAT_UNDEC; + if ( RetValue == l_True ) + return SFM_SAT_SAT; + assert( RetValue == l_False ); + //printf( "Offset = %2d. Onset = %2d. DC = %2d. Total = %2d.\n", + // Abc_TtCountOnes(Truth[0]), Abc_TtCountOnes(Truth[1]), + // (1<<Vec_IntSize(p->vDivIds)) - (Abc_TtCountOnes(Truth[0]) + Abc_TtCountOnes(Truth[1])), + // 1<<Vec_IntSize(p->vDivIds) ); + Truth[0] = Abc_Tt6Stretch( Truth[0], Vec_IntSize(p->vDivIds) ); + Truth[1] = Abc_Tt6Stretch( Truth[1], Vec_IntSize(p->vDivIds) ); + ResP = Abc_Tt6Isop( Truth[1], ~Truth[0], Vec_IntSize(p->vDivIds), &nCubesP ); + ResN = Abc_Tt6Isop( Truth[0], ~Truth[1], Vec_IntSize(p->vDivIds), &nCubesN ); + Res = nCubesP <= nCubesN ? ResP : ~ResN; + //Dau_DsdPrintFromTruth( &Res, Vec_IntSize(p->vDivIds) ); + return Res; +} + +/**Function************************************************************* + Synopsis [Checks resubstitution.] Description [] diff --git a/src/opt/sfm/sfmWin.c b/src/opt/sfm/sfmWin.c index 63750407..53f9a71e 100644 --- a/src/opt/sfm/sfmWin.c +++ b/src/opt/sfm/sfmWin.c @@ -365,15 +365,15 @@ int Sfm_NtkCreateWindow( Sfm_Ntk_t * p, int iNode, int fVerbose ) Vec_IntAppend( p->vDivs, p->vNodes ); Vec_IntPop( p->vDivs ); // add non-topological divisors - if ( Vec_IntSize(p->vDivs) < p->pPars->nWinSizeMax + 0 ) + if ( !p->pPars->nWinSizeMax || Vec_IntSize(p->vDivs) < p->pPars->nWinSizeMax + 0 ) { Sfm_NtkIncrementTravId2( p ); Vec_IntForEachEntry( p->vDivs, iTemp, i ) - if ( Vec_IntSize(p->vDivs) < p->pPars->nWinSizeMax + 0 ) + if ( !p->pPars->nWinSizeMax || Vec_IntSize(p->vDivs) < p->pPars->nWinSizeMax + 0 ) // Sfm_NtkAddDivisors( p, iTemp, Sfm_ObjLevel(p, iNode) - 1 ); Sfm_NtkAddDivisors( p, iTemp, p->nLevelMax - Sfm_ObjLevelR(p, iNode) ); } - if ( Vec_IntSize(p->vDivs) > p->pPars->nWinSizeMax ) + if ( p->pPars->nWinSizeMax && Vec_IntSize(p->vDivs) > p->pPars->nWinSizeMax ) { /* k = 0; @@ -383,8 +383,8 @@ int Sfm_NtkCreateWindow( Sfm_Ntk_t * p, int iNode, int fVerbose ) */ Vec_IntShrink( p->vDivs, p->pPars->nWinSizeMax ); } - assert( Vec_IntSize(p->vDivs) <= p->pPars->nWinSizeMax ); - p->nMaxDivs += (int)(Vec_IntSize(p->vDivs) == p->pPars->nWinSizeMax); + assert( !p->pPars->nWinSizeMax || Vec_IntSize(p->vDivs) <= p->pPars->nWinSizeMax ); + p->nMaxDivs += (int)(p->pPars->nWinSizeMax && Vec_IntSize(p->vDivs) == p->pPars->nWinSizeMax); // remove node/fanins from divisors // mark fanins Sfm_NtkIncrementTravId2( p ); @@ -397,7 +397,7 @@ int Sfm_NtkCreateWindow( Sfm_Ntk_t * p, int iNode, int fVerbose ) if ( !Sfm_ObjIsTravIdCurrent2(p, iTemp) && Sfm_ObjIsUseful(p, iTemp) ) Vec_IntWriteEntry( p->vDivs, k++, iTemp ); Vec_IntShrink( p->vDivs, k ); - assert( Vec_IntSize(p->vDivs) <= p->pPars->nWinSizeMax ); + assert( !p->pPars->nWinSizeMax || Vec_IntSize(p->vDivs) <= p->pPars->nWinSizeMax ); clkDiv = Abc_Clock() - clkDiv; p->timeDiv += clkDiv; p->nTotalDivs += Vec_IntSize(p->vDivs); diff --git a/src/proof/abs/absVta.c b/src/proof/abs/absVta.c index 597e4b72..b6001d3f 100644 --- a/src/proof/abs/absVta.c +++ b/src/proof/abs/absVta.c @@ -705,8 +705,8 @@ Abc_Cex_t * Vta_ManRefineAbstraction( Vta_Man_t * p, int f ) // objects with equal distance should receive priority based on number // those objects whose prototypes have been added in other timeframes // should have higher priority than the current object - Vec_PtrSort( vTermsUsed, (int (*)(void))Vta_ManComputeDepthIncrease ); - Vec_PtrSort( vTermsUnused, (int (*)(void))Vta_ManComputeDepthIncrease ); + Vec_PtrSort( vTermsUsed, (int (*)(const void *, const void *))Vta_ManComputeDepthIncrease ); + Vec_PtrSort( vTermsUnused, (int (*)(const void *, const void *))Vta_ManComputeDepthIncrease ); if ( Vec_PtrSize(vTermsUsed) > 1 ) { pThis0 = (Vta_Obj_t *)Vec_PtrEntry(vTermsUsed, 0); diff --git a/src/proof/acec/acecFadds.c b/src/proof/acec/acecFadds.c index d55eefe2..a2bdcfbe 100644 --- a/src/proof/acec/acecFadds.c +++ b/src/proof/acec/acecFadds.c @@ -314,16 +314,21 @@ void Dtc_ManCutMerge( Gia_Man_t * p, int iObj, int * pList0, int * pList1, Vec_I if ( Type == 0 ) continue; vTemp = Type == 1 ? vCutsXor : vCutsMaj; - if ( fVerbose ) - printf( "%d = %s(", iObj, Type == 1 ? "XOR" : "MAJ" ); - for ( c = 1; c <= pCut[0]; c++ ) + if ( 0 && Type == 2 ) { + fVerbose = 1; + if ( fVerbose ) + printf( "%d = %s(", iObj, Type == 1 ? "XOR" : "MAJ" ); + for ( c = 1; c <= pCut[0]; c++ ) + { + if ( fVerbose ) + printf( " %d", pCut[c] ); + Vec_IntPush( vTemp, pCut[c] ); + } if ( fVerbose ) - printf( " %d", pCut[c] ); - Vec_IntPush( vTemp, pCut[c] ); + printf( " )\n" ); + fVerbose = 0; } - if ( fVerbose ) - printf( " )\n" ); Vec_IntPush( vTemp, iObj ); } } @@ -450,6 +455,16 @@ Vec_Int_t * Gia_ManDetectFullAdders( Gia_Man_t * p, int fVerbose, Vec_Int_t ** p Vec_IntFree( vCutsMaj ); return vFadds; } +void Gia_ManDetectFullAdders2( Gia_Man_t * p, int fVerbose ) +{ + Vec_Int_t * vCutsXor2, * vCutsXor, * vCutsMaj; + Dtc_ManComputeCuts( p, &vCutsXor2, &vCutsXor, &vCutsMaj, fVerbose ); + if ( fVerbose ) + printf( "XOR3 cuts = %d. MAJ cuts = %d.\n", Vec_IntSize(vCutsXor)/4, Vec_IntSize(vCutsMaj)/4 ); + Vec_IntFree( vCutsXor2 ); + Vec_IntFree( vCutsXor ); + Vec_IntFree( vCutsMaj ); +} /**Function************************************************************* @@ -1238,6 +1253,7 @@ Gia_Man_t * Gia_ManDupWithArtificialBoxes( Gia_Man_t * p, int DelayC, int nPathM return pNew; } + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/proof/cec/cec.h b/src/proof/cec/cec.h index 757d9fd3..7c101570 100644 --- a/src/proof/cec/cec.h +++ b/src/proof/cec/cec.h @@ -43,6 +43,7 @@ ABC_NAMESPACE_HEADER_START typedef struct Cec_ParSat_t_ Cec_ParSat_t; struct Cec_ParSat_t_ { + int SolverType; // SAT solver type int nBTLimit; // conflict limit at a node int nSatVarMax; // the max number of SAT variables int nCallsRecycle; // calls to perform before recycling SAT solver @@ -95,13 +96,18 @@ struct Cec_ParSmf_t_ typedef struct Cec_ParFra_t_ Cec_ParFra_t; struct Cec_ParFra_t_ { + int jType; // solver type int nWords; // the number of simulation words int nRounds; // the number of simulation rounds int nItersMax; // the maximum number of iterations of SAT sweeping int nBTLimit; // conflict limit at a node + int nBTLimitPo; // conflict limit at an output int TimeLimit; // the runtime limit in seconds int nLevelMax; // restriction on the level nodes to be swept int nDepthMax; // the depth in terms of steps of speculative reduction + int nCallsRecycle; // calls to perform before recycling SAT solver + int nSatVarMax; // the max number of SAT variables + int nGenIters; // pattern generation iterations int fRewriting; // enables AIG rewriting int fCheckMiter; // the circuit is the miter // int fFirstStop; // stop on the first sat output @@ -215,7 +221,7 @@ extern void Cec_ManCecSetDefaultParams( Cec_ParCec_t * p ); extern void Cec_ManCorSetDefaultParams( Cec_ParCor_t * p ); extern void Cec_ManChcSetDefaultParams( Cec_ParChc_t * p ); extern Gia_Man_t * Cec_ManSatSweeping( Gia_Man_t * pAig, Cec_ParFra_t * pPars, int fSilent ); -extern Gia_Man_t * Cec_ManSatSolving( Gia_Man_t * pAig, Cec_ParSat_t * pPars ); +extern Gia_Man_t * Cec_ManSatSolving( Gia_Man_t * pAig, Cec_ParSat_t * pPars, int f0Proved ); extern void Cec_ManSimulation( Gia_Man_t * pAig, Cec_ParSim_t * pPars ); /*=== cecSeq.c ==========================================================*/ extern int Cec_ManSeqResimulateCounter( Gia_Man_t * pAig, Cec_ParSim_t * pPars, Abc_Cex_t * pCex ); diff --git a/src/proof/cec/cecCec.c b/src/proof/cec/cecCec.c index ee45aa6c..cfa07ff8 100644 --- a/src/proof/cec/cecCec.c +++ b/src/proof/cec/cecCec.c @@ -349,12 +349,18 @@ int Cec_ManVerify( Gia_Man_t * pInit, Cec_ParCec_t * pPars ) Gia_ManStop( p ); return RetValue; } + if ( pInit->vSimsPi ) + { + p->vSimsPi = Vec_WrdDup(pInit->vSimsPi); + p->nSimWords = pInit->nSimWords; + } // sweep for equivalences Cec_ManFraSetDefaultParams( pParsFra ); pParsFra->nItersMax = 1000; pParsFra->nBTLimit = pPars->nBTLimit; pParsFra->TimeLimit = pPars->TimeLimit; pParsFra->fVerbose = pPars->fVerbose; + pParsFra->fVeryVerbose = pPars->fVeryVerbose; pParsFra->fCheckMiter = 1; pParsFra->fDualOut = 1; pNew = Cec_ManSatSweeping( p, pParsFra, pPars->fSilent ); diff --git a/src/proof/cec/cecChoice.c b/src/proof/cec/cecChoice.c index 49025630..db0059fd 100644 --- a/src/proof/cec/cecChoice.c +++ b/src/proof/cec/cecChoice.c @@ -256,7 +256,7 @@ int Cec_ManChoiceComputation_int( Gia_Man_t * pAig, Cec_ParChc_t * pPars ) // found counter-examples to speculation clk2 = Abc_Clock(); if ( pPars->fUseCSat ) - vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 ); + vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0, 0 ); else vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); Gia_ManStop( pSrm ); @@ -401,6 +401,29 @@ Aig_Man_t * Cec_ComputeChoices( Gia_Man_t * pGia, Dch_Pars_t * pPars ) return pAig; } +/**Function************************************************************* + + Synopsis [Performs computation of AIGs with choices.] + + Description [Takes several AIGs and performs choicing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Cec_ComputeChoicesNew( Gia_Man_t * pGia, int nConfs, int fVerbose ) +{ + extern void Cec4_ManSimulateTest2( Gia_Man_t * p, int nConfs, int fVerbose ); + Aig_Man_t * pAig; + Cec4_ManSimulateTest2( pGia, nConfs, fVerbose ); + pGia = Gia_ManEquivToChoices( pGia, 3 ); + Gia_ManSetRegNum( pGia, Gia_ManRegNum(pGia) ); + pAig = Gia_ManToAig( pGia, 1 ); + Gia_ManStop( pGia ); + return pAig; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/proof/cec/cecClass.c b/src/proof/cec/cecClass.c index 2d820c39..be88b9be 100644 --- a/src/proof/cec/cecClass.c +++ b/src/proof/cec/cecClass.c @@ -878,19 +878,34 @@ int Cec_ManSimClassesPrepare( Cec_ManSim_t * p, int LevelMax ) if ( pObj->Value ) Gia_ObjSetRepr( p->pAig, Gia_ObjId(p->pAig, pObj), 0 ); // perform simulation - p->nWords = 1; - do { + if ( p->pAig->nSimWords ) + { + p->nWords = 2*p->pAig->nSimWords; + assert( Vec_WrdSize(p->pAig->vSimsPi) == Gia_ManCiNum(p->pAig) * p->pAig->nSimWords ); + //Cec_ManSimCreateInfo( p, p->vCiSimInfo, p->vCoSimInfo ); + for ( i = 0; i < Gia_ManCiNum(p->pAig); i++ ) + memmove( Vec_PtrEntry(p->vCiSimInfo, i), Vec_WrdEntryP(p->pAig->vSimsPi, i*p->pAig->nSimWords), sizeof(word)*p->pAig->nSimWords ); + if ( Cec_ManSimSimulateRound( p, p->vCiSimInfo, p->vCoSimInfo ) ) + return 1; if ( p->pPars->fVerbose ) Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) ); - for ( i = 0; i < 4; i++ ) - { - Cec_ManSimCreateInfo( p, p->vCiSimInfo, p->vCoSimInfo ); - if ( Cec_ManSimSimulateRound( p, p->vCiSimInfo, p->vCoSimInfo ) ) - return 1; + } + else + { + p->nWords = 1; + do { + if ( p->pPars->fVerbose ) + Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) ); + for ( i = 0; i < 4; i++ ) + { + Cec_ManSimCreateInfo( p, p->vCiSimInfo, p->vCoSimInfo ); + if ( Cec_ManSimSimulateRound( p, p->vCiSimInfo, p->vCoSimInfo ) ) + return 1; + } + p->nWords = 2 * p->nWords + 1; } - p->nWords = 2 * p->nWords + 1; + while ( p->nWords <= p->pPars->nWords ); } - while ( p->nWords <= p->pPars->nWords ); return 0; } diff --git a/src/proof/cec/cecCore.c b/src/proof/cec/cecCore.c index b9529658..f94bd27f 100644 --- a/src/proof/cec/cecCore.c +++ b/src/proof/cec/cecCore.c @@ -45,6 +45,7 @@ ABC_NAMESPACE_IMPL_START void Cec_ManSatSetDefaultParams( Cec_ParSat_t * p ) { memset( p, 0, sizeof(Cec_ParSat_t) ); + p->SolverType = -1; // SAT solver type p->nBTLimit = 100; // conflict limit at a node p->nSatVarMax = 2000; // the max number of SAT variables p->nCallsRecycle = 200; // calls to perform before recycling SAT solver @@ -232,14 +233,17 @@ void Cec_ManChcSetDefaultParams( Cec_ParChc_t * p ) SeeAlso [] ***********************************************************************/ -Gia_Man_t * Cec_ManSatSolving( Gia_Man_t * pAig, Cec_ParSat_t * pPars ) +Gia_Man_t * Cec_ManSatSolving( Gia_Man_t * pAig, Cec_ParSat_t * pPars, int f0Proved ) { Gia_Man_t * pNew; Cec_ManPat_t * pPat; pPat = Cec_ManPatStart(); - Cec_ManSatSolve( pPat, pAig, pPars, NULL, NULL, NULL ); + if ( pPars->SolverType == -1 ) + Cec_ManSatSolve( pPat, pAig, pPars, NULL, NULL, NULL, f0Proved ); + else + CecG_ManSatSolve( pPat, pAig, pPars, f0Proved ); // pNew = Gia_ManDupDfsSkip( pAig ); - pNew = Gia_ManDup( pAig ); + pNew = Gia_ManCleanup( pAig ); Cec_ManPatStop( pPat ); pNew->vSeqModelVec = pAig->vSeqModelVec; pAig->vSeqModelVec = NULL; @@ -348,6 +352,8 @@ Gia_Man_t * Cec_ManSatSweeping( Gia_Man_t * pAig, Cec_ParFra_t * pPars, int fSil Cec_ManPat_t * pPat; int i, fTimeOut = 0, nMatches = 0; abctime clk, clk2, clkTotal = Abc_Clock(); + if ( pPars->fVerbose ) + printf( "Simulating %d words for %d rounds. SAT solving with %d conflicts.\n", pPars->nWords, pPars->nRounds, pPars->nBTLimit ); // duplicate AIG and transfer equivalence classes Gia_ManRandom( 1 ); @@ -360,6 +366,11 @@ Gia_Man_t * Cec_ManSatSweeping( Gia_Man_t * pAig, Cec_ParFra_t * pPars, int fSil Vec_IntFreeP( &pAig->vIdsEquiv ); pAig->vIdsEquiv = Vec_IntAlloc( 1000 ); } + if ( pAig->vSimsPi ) + { + pIni->vSimsPi = Vec_WrdDup(pAig->vSimsPi); + pIni->nSimWords = pAig->nSimWords; + } // prepare the managers // SAT sweeping @@ -368,25 +379,25 @@ Gia_Man_t * Cec_ManSatSweeping( Gia_Man_t * pAig, Cec_ParFra_t * pPars, int fSil pPars->fColorDiff = 1; // simulation Cec_ManSimSetDefaultParams( pParsSim ); - pParsSim->nWords = pPars->nWords; + pParsSim->nWords = Abc_MaxInt(2*pAig->nSimWords, pPars->nWords); pParsSim->nFrames = pPars->nRounds; pParsSim->fCheckMiter = pPars->fCheckMiter; pParsSim->fDualOut = pPars->fDualOut; pParsSim->fVerbose = pPars->fVerbose; - pSim = Cec_ManSimStart( p->pAig, pParsSim ); + pSim = Cec_ManSimStart( pIni, pParsSim ); // SAT solving Cec_ManSatSetDefaultParams( pParsSat ); pParsSat->nBTLimit = pPars->nBTLimit; pParsSat->fVerbose = pPars->fVeryVerbose; // simulation patterns pPat = Cec_ManPatStart(); - pPat->fVerbose = pPars->fVeryVerbose; + //pPat->fVerbose = pPars->fVeryVerbose; // start equivalence classes clk = Abc_Clock(); if ( p->pAig->pReprs == NULL ) { - if ( Cec_ManSimClassesPrepare(pSim, -1) || Cec_ManSimClassesRefine(pSim) ) + if ( Cec_ManSimClassesPrepare(pSim, -1) || (!p->pAig->nSimWords && Cec_ManSimClassesRefine(pSim)) ) { Gia_ManStop( p->pAig ); p->pAig = NULL; @@ -438,7 +449,7 @@ clk = Abc_Clock(); if ( pPars->fRunCSat ) Cec_ManSatSolveCSat( pPat, pSrm, pParsSat ); else - Cec_ManSatSolve( pPat, pSrm, pParsSat, p->pAig->vIdsOrig, p->vXorNodes, pAig->vIdsEquiv ); + Cec_ManSatSolve( pPat, pSrm, pParsSat, p->pAig->vIdsOrig, p->vXorNodes, pAig->vIdsEquiv, 0 ); p->timeSat += Abc_Clock() - clk; if ( Cec_ManFraClassesUpdate( p, pSim, pPat, pSrm ) ) { @@ -514,6 +525,9 @@ p->timeSat += Abc_Clock() - clk; } } finalize: + if ( pPars->fVerbose ) + printf( "Performed %d SAT calls: P = %d D = %d F = %d\n", + p->nAllProvedS + p->nAllDisprovedS + p->nAllFailedS, p->nAllProvedS, p->nAllDisprovedS, p->nAllFailedS ); if ( p->pPars->fVerbose && p->pAig ) { Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", @@ -543,6 +557,8 @@ finalize: Cec_ManSimStop( pSim ); Cec_ManPatStop( pPat ); Cec_ManFraStop( p ); + if ( pTemp ) ABC_FREE( pTemp->pReprs ); + if ( pTemp ) ABC_FREE( pTemp->pNexts ); return pTemp; } diff --git a/src/proof/cec/cecCorr.c b/src/proof/cec/cecCorr.c index 8f708910..ce7e0885 100644 --- a/src/proof/cec/cecCorr.c +++ b/src/proof/cec/cecCorr.c @@ -996,7 +996,7 @@ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) // found counter-examples to speculation clk2 = Abc_Clock(); if ( pPars->fUseCSat ) - vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 ); + vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0, 0 ); else vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); Gia_ManStop( pSrm ); diff --git a/src/proof/cec/cecInt.h b/src/proof/cec/cecInt.h index d93e5e86..f78e5f25 100644 --- a/src/proof/cec/cecInt.h +++ b/src/proof/cec/cecInt.h @@ -27,6 +27,7 @@ //////////////////////////////////////////////////////////////////////// #include "sat/bsat/satSolver.h" +#include "sat/glucose2/AbcGlucose2.h" #include "misc/bar/bar.h" #include "aig/gia/gia.h" #include "cec.h" @@ -80,7 +81,8 @@ struct Cec_ManSat_t_ Gia_Man_t * pAig; // the AIG whose outputs are considered Vec_Int_t * vStatus; // status for each output // SAT solving - sat_solver * pSat; // recyclable SAT solver + sat_solver * pSat; // recyclable SAT solver (MiniSAT) + bmcg2_sat_solver*pSat2; // recyclable SAT solver (Glucose) int nSatVars; // the counter of SAT variables int * pSatVars; // mapping of each node into its SAT var Vec_Ptr_t * vUsedNodes; // nodes whose SAT vars are assigned @@ -153,6 +155,9 @@ struct Cec_ManFra_t_ int nAllProved; // total number of proved nodes int nAllDisproved; // total number of disproved nodes int nAllFailed; // total number of failed nodes + int nAllProvedS; // total number of proved nodes + int nAllDisprovedS; // total number of disproved nodes + int nAllFailedS; // total number of failed nodes // runtime stats abctime timeSim; // unsat abctime timePat; // unsat @@ -201,7 +206,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, Vec_Int_t * vIdsOrig, Vec_Int_t * vMiterPairs, Vec_Int_t * vEquivPairs ); +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, int f0Proved ); 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 ); @@ -209,6 +214,8 @@ extern int Cec_ManSatCheckNode( Cec_ManSat_t * p, Gia_Obj_t * p extern int Cec_ManSatCheckNodeTwo( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 ); extern void Cec_ManSavePattern( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 ); extern Vec_Int_t * Cec_ManSatReadCex( Cec_ManSat_t * p ); +/*=== cecSolveG.c ============================================================*/ +extern void CecG_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars, int f0Proved ); /*=== ceFraeep.c ============================================================*/ extern Gia_Man_t * Cec_ManFraSpecReduction( Cec_ManFra_t * p ); extern int Cec_ManFraClassesUpdate( Cec_ManFra_t * p, Cec_ManSim_t * pSim, Cec_ManPat_t * pPat, Gia_Man_t * pNew ); diff --git a/src/proof/cec/cecMan.c b/src/proof/cec/cecMan.c index 1d32b99e..c636a00d 100644 --- a/src/proof/cec/cecMan.c +++ b/src/proof/cec/cecMan.c @@ -73,6 +73,7 @@ Cec_ManSat_t * Cec_ManSatCreate( Gia_Man_t * pAig, Cec_ParSat_t * pPars ) ***********************************************************************/ void Cec_ManSatPrintStats( Cec_ManSat_t * p ) { + printf( "SAT solver statistics:\n" ); Abc_Print( 1, "CO = %8d ", Gia_ManCoNum(p->pAig) ); Abc_Print( 1, "AND = %8d ", Gia_ManAndNum(p->pAig) ); Abc_Print( 1, "Conf = %5d ", p->pPars->nBTLimit ); diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c new file mode 100644 index 00000000..ce299c66 --- /dev/null +++ b/src/proof/cec/cecSatG2.c @@ -0,0 +1,1921 @@ +/**CFile**************************************************************** + + FileName [cecSatG2.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Detection of structural isomorphism.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecSatG2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig/gia/gia.h" +#include "misc/util/utilTruth.h" +#include "cec.h" + +#define USE_GLUCOSE2 + +#ifdef USE_GLUCOSE2 + +#include "sat/glucose2/AbcGlucose2.h" + +#define sat_solver bmcg2_sat_solver +#define sat_solver_start bmcg2_sat_solver_start +#define sat_solver_stop bmcg2_sat_solver_stop +#define sat_solver_addclause bmcg2_sat_solver_addclause +#define sat_solver_add_and bmcg2_sat_solver_add_and +#define sat_solver_add_xor bmcg2_sat_solver_add_xor +#define sat_solver_addvar bmcg2_sat_solver_addvar +#define sat_solver_read_cex_varvalue bmcg2_sat_solver_read_cex_varvalue +#define sat_solver_reset bmcg2_sat_solver_reset +#define sat_solver_set_conflict_budget bmcg2_sat_solver_set_conflict_budget +#define sat_solver_conflictnum bmcg2_sat_solver_conflictnum +#define sat_solver_solve bmcg2_sat_solver_solve +#define sat_solver_read_cex_varvalue bmcg2_sat_solver_read_cex_varvalue +#define sat_solver_read_cex bmcg2_sat_solver_read_cex +#define sat_solver_jftr bmcg2_sat_solver_jftr +#define sat_solver_set_jftr bmcg2_sat_solver_set_jftr +#define sat_solver_set_var_fanin_lit bmcg2_sat_solver_set_var_fanin_lit +#define sat_solver_start_new_round bmcg2_sat_solver_start_new_round +#define sat_solver_mark_cone bmcg2_sat_solver_mark_cone + +#else + +#include "sat/glucose/AbcGlucose.h" + +#define sat_solver bmcg_sat_solver +#define sat_solver_start bmcg_sat_solver_start +#define sat_solver_stop bmcg_sat_solver_stop +#define sat_solver_addclause bmcg_sat_solver_addclause +#define sat_solver_add_and bmcg_sat_solver_add_and +#define sat_solver_add_xor bmcg_sat_solver_add_xor +#define sat_solver_addvar bmcg_sat_solver_addvar +#define sat_solver_read_cex_varvalue bmcg_sat_solver_read_cex_varvalue +#define sat_solver_reset bmcg_sat_solver_reset +#define sat_solver_set_conflict_budget bmcg_sat_solver_set_conflict_budget +#define sat_solver_conflictnum bmcg_sat_solver_conflictnum +#define sat_solver_solve bmcg_sat_solver_solve +#define sat_solver_read_cex_varvalue bmcg_sat_solver_read_cex_varvalue +#define sat_solver_read_cex bmcg_sat_solver_read_cex +#define sat_solver_jftr bmcg_sat_solver_jftr +#define sat_solver_set_jftr bmcg_sat_solver_set_jftr +#define sat_solver_set_var_fanin_lit bmcg_sat_solver_set_var_fanin_lit +#define sat_solver_start_new_round bmcg_sat_solver_start_new_round +#define sat_solver_mark_cone bmcg_sat_solver_mark_cone + +#endif + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// SAT solving manager +typedef struct Cec4_Man_t_ Cec4_Man_t; +struct Cec4_Man_t_ +{ + Cec_ParFra_t * pPars; // parameters + Gia_Man_t * pAig; // user's AIG + Gia_Man_t * pNew; // internal AIG + // SAT solving + sat_solver * pSat; // SAT solver + Vec_Ptr_t * vFrontier; // CNF construction + Vec_Ptr_t * vFanins; // CNF construction + Vec_Int_t * vCexMin; // minimized CEX + Vec_Int_t * vClassUpdates; // updated equiv classes + Vec_Int_t * vCexStamps; // time stamps + Vec_Int_t * vCands; + Vec_Int_t * vVisit; + Vec_Int_t * vPat; + Vec_Int_t * vDisprPairs; + Vec_Bit_t * vFails; + Vec_Bit_t * vCoDrivers; + int iPosRead; // candidate reading position + int iPosWrite; // candidate writing position + int iLastConst; // last const node proved + // refinement + Vec_Int_t * vRefClasses; + Vec_Int_t * vRefNodes; + Vec_Int_t * vRefBins; + int * pTable; + int nTableSize; + // statistics + int nItersSim; + int nItersSat; + int nAndNodes; + int nPatterns; + int nSatSat; + int nSatUnsat; + int nSatUndec; + int nCallsSince; + int nSimulates; + int nRecycles; + int nConflicts[2][3]; + int nGates[2]; + int nFaster[2]; + abctime timeCnf; + abctime timeGenPats; + abctime timeSatSat0; + abctime timeSatUnsat0; + abctime timeSatSat; + abctime timeSatUnsat; + abctime timeSatUndec; + abctime timeSim; + abctime timeRefine; + abctime timeResimGlo; + abctime timeResimLoc; + abctime timeStart; +}; + +static inline int Cec4_ObjSatId( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjCopy2Array(p, Gia_ObjId(p, pObj)); } +static inline int Cec4_ObjSetSatId( Gia_Man_t * p, Gia_Obj_t * pObj, int Num ) { assert(Cec4_ObjSatId(p, pObj) == -1); Gia_ObjSetCopy2Array(p, Gia_ObjId(p, pObj), Num); Vec_IntPush(&p->vSuppVars, Gia_ObjId(p, pObj)); if ( Gia_ObjIsCi(pObj) ) Vec_IntPushTwo(&p->vCopiesTwo, Gia_ObjId(p, pObj), Num); assert(Vec_IntSize(&p->vVarMap) == Num); Vec_IntPush(&p->vVarMap, Gia_ObjId(p, pObj)); return Num; } +static inline void Cec4_ObjCleanSatId( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert(Cec4_ObjSatId(p, pObj) != -1); Gia_ObjSetCopy2Array(p, Gia_ObjId(p, pObj), -1); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Cec4_EvalCombine( Vec_Int_t * vPats, int nPats, int nInputs, int nWords ) +{ + //Vec_Wrd_t * vSimsPi = Vec_WrdStart( nInputs * nWords ); + Vec_Wrd_t * vSimsPi = Vec_WrdStartRandom( nInputs * nWords ); + int i, k, iLit, iPat = 0; word * pSim; + for ( i = 0; i < Vec_IntSize(vPats); i += Vec_IntEntry(vPats, i), iPat++ ) + for ( k = 1; k < Vec_IntEntry(vPats, i)-1; k++ ) + if ( (iLit = Vec_IntEntry(vPats, i+k)) ) + { + assert( Abc_Lit2Var(iLit) > 0 && Abc_Lit2Var(iLit) <= nInputs ); + pSim = Vec_WrdEntryP( vSimsPi, (Abc_Lit2Var(iLit)-1)*nWords ); + if ( Abc_InfoHasBit( (unsigned*)pSim, iPat ) != Abc_LitIsCompl(iLit) ) + Abc_InfoXorBit( (unsigned*)pSim, iPat ); + } + assert( iPat == nPats ); + return vSimsPi; +} +void Cec4_EvalPatterns( Gia_Man_t * p, Vec_Int_t * vPats, int nPats ) +{ + int nWords = Abc_Bit6WordNum(nPats); + Vec_Wrd_t * vSimsPi = Cec4_EvalCombine( vPats, nPats, Gia_ManCiNum(p), nWords ); + Vec_Wrd_t * vSimsPo = Gia_ManSimPatSimOut( p, vSimsPi, 1 ); + int i, Count = 0, nErrors = 0; + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + { + int CountThis = Abc_TtCountOnesVec( Vec_WrdEntryP(vSimsPo, i*nWords), nWords ); + if ( CountThis == 0 ) + continue; + printf( "%d ", CountThis ); + nErrors += CountThis; + Count++; + } + printf( "\nDetected %d error POs with %d errors (average %.2f).\n", Count, nErrors, 1.0*nErrors/Abc_MaxInt(1, Count) ); + Vec_WrdFree( vSimsPi ); + Vec_WrdFree( vSimsPo ); +} + +/**Function************************************************************* + + Synopsis [Default parameter settings.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec4_ManSetParams( Cec_ParFra_t * pPars ) +{ + memset( pPars, 0, sizeof(Cec_ParFra_t) ); + pPars->jType = 2; // solver type + pPars->fSatSweeping = 1; // conflict limit at a node + pPars->nWords = 4; // simulation words + pPars->nRounds = 10; // simulation rounds + pPars->nItersMax = 2000; // this is a miter + pPars->nBTLimit = 1000000; // use logic cones + pPars->nBTLimitPo = 0; // use logic outputs + pPars->nSatVarMax = 1000; // the max number of SAT variables before recycling SAT solver + pPars->nCallsRecycle = 500; // calls to perform before recycling SAT solver + pPars->nGenIters = 100; // pattern generation iterations +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cec4_Man_t * Cec4_ManCreate( Gia_Man_t * pAig, Cec_ParFra_t * pPars ) +{ + Cec4_Man_t * p = ABC_CALLOC( Cec4_Man_t, 1 ); + memset( p, 0, sizeof(Cec4_Man_t) ); + p->timeStart = Abc_Clock(); + p->pPars = pPars; + p->pAig = pAig; + p->pSat = sat_solver_start(); + sat_solver_set_jftr( p->pSat, pPars->jType ); + p->vFrontier = Vec_PtrAlloc( 1000 ); + p->vFanins = Vec_PtrAlloc( 100 ); + p->vCexMin = Vec_IntAlloc( 100 ); + p->vClassUpdates = Vec_IntAlloc( 100 ); + p->vCexStamps = Vec_IntStart( Gia_ManObjNum(pAig) ); + p->vCands = Vec_IntAlloc( 100 ); + p->vVisit = Vec_IntAlloc( 100 ); + p->vPat = Vec_IntAlloc( 100 ); + p->vDisprPairs = Vec_IntAlloc( 100 ); + p->vFails = Vec_BitStart( Gia_ManObjNum(pAig) ); + //pAig->pData = p->pSat; // point AIG manager to the solver + //Vec_IntFreeP( &p->pAig->vPats ); + //p->pAig->vPats = Vec_IntAlloc( 1000 ); + if ( pPars->nBTLimitPo ) + { + int i, Driver; + p->vCoDrivers = Vec_BitStart( Gia_ManObjNum(pAig) ); + Gia_ManForEachCoDriverId( pAig, Driver, i ) + Vec_BitWriteEntry( p->vCoDrivers, Driver, 1 ); + } + return p; +} +void Cec4_ManDestroy( Cec4_Man_t * p ) +{ + if ( p->pPars->fVerbose ) + { + abctime timeTotal = Abc_Clock() - p->timeStart; + abctime timeSat = p->timeSatSat0 + p->timeSatSat + p->timeSatUnsat0 + p->timeSatUnsat + p->timeSatUndec; + abctime timeOther = timeTotal - timeSat - p->timeSim - p->timeRefine - p->timeResimLoc - p->timeGenPats;// - p->timeResimGlo; + ABC_PRTP( "SAT solving ", timeSat, timeTotal ); + ABC_PRTP( " sat(easy) ", p->timeSatSat0, timeTotal ); + ABC_PRTP( " sat ", p->timeSatSat, timeTotal ); + ABC_PRTP( " unsat(easy)", p->timeSatUnsat0, timeTotal ); + ABC_PRTP( " unsat ", p->timeSatUnsat, timeTotal ); + ABC_PRTP( " fail ", p->timeSatUndec, timeTotal ); + ABC_PRTP( "Generate CNF ", p->timeCnf, timeTotal ); + ABC_PRTP( "Generate pats", p->timeGenPats, timeTotal ); + ABC_PRTP( "Simulation ", p->timeSim, timeTotal ); + ABC_PRTP( "Refinement ", p->timeRefine, timeTotal ); + ABC_PRTP( "Resim global ", p->timeResimGlo, timeTotal ); + ABC_PRTP( "Resim local ", p->timeResimLoc, timeTotal ); + ABC_PRTP( "Other ", timeOther, timeTotal ); + ABC_PRTP( "TOTAL ", timeTotal, timeTotal ); + fflush( stdout ); + } + //printf( "Recorded %d patterns with %d literals (average %.2f).\n", + // p->pAig->nBitPats, Vec_IntSize(p->pAig->vPats) - 2*p->pAig->nBitPats, 1.0*Vec_IntSize(p->pAig->vPats)/Abc_MaxInt(1, p->pAig->nBitPats)-2 ); + //Cec4_EvalPatterns( p->pAig, p->pAig->vPats, p->pAig->nBitPats ); + //Vec_IntFreeP( &p->pAig->vPats ); + Vec_WrdFreeP( &p->pAig->vSims ); + Vec_WrdFreeP( &p->pAig->vSimsPi ); + Gia_ManCleanMark01( p->pAig ); + sat_solver_stop( p->pSat ); + Gia_ManStopP( &p->pNew ); + Vec_PtrFreeP( &p->vFrontier ); + Vec_PtrFreeP( &p->vFanins ); + Vec_IntFreeP( &p->vCexMin ); + Vec_IntFreeP( &p->vClassUpdates ); + Vec_IntFreeP( &p->vCexStamps ); + Vec_IntFreeP( &p->vCands ); + Vec_IntFreeP( &p->vVisit ); + Vec_IntFreeP( &p->vPat ); + Vec_IntFreeP( &p->vDisprPairs ); + Vec_BitFreeP( &p->vFails ); + Vec_BitFreeP( &p->vCoDrivers ); + Vec_IntFreeP( &p->vRefClasses ); + Vec_IntFreeP( &p->vRefNodes ); + Vec_IntFreeP( &p->vRefBins ); + ABC_FREE( p->pTable ); + ABC_FREE( p ); +} +Gia_Man_t * Cec4_ManStartNew( Gia_Man_t * pAig ) +{ + Gia_Obj_t * pObj; int i; + Gia_Man_t * pNew = Gia_ManStart( Gia_ManObjNum(pAig) ); + pNew->pName = Abc_UtilStrsav( pAig->pName ); + pNew->pSpec = Abc_UtilStrsav( pAig->pSpec ); + if ( pAig->pMuxes ) + pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); + Gia_ManFillValue( pAig ); + Gia_ManConst0(pAig)->Value = 0; + Gia_ManForEachCi( pAig, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + Vec_IntFill( &pNew->vCopies2, Gia_ManObjNum(pAig), -1 ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(pAig) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Adds clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec4_AddClausesMux( Gia_Man_t * p, Gia_Obj_t * pNode, sat_solver * pSat ) +{ + int fPolarFlip = 0; + Gia_Obj_t * pNodeI, * pNodeT, * pNodeE; + int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; + + assert( !Gia_IsComplement( pNode ) ); + assert( pNode->fMark0 ); + // get nodes (I = if, T = then, E = else) + pNodeI = Gia_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); + // get the variable numbers + VarF = Cec4_ObjSatId(p, pNode); + VarI = Cec4_ObjSatId(p, pNodeI); + VarT = Cec4_ObjSatId(p, Gia_Regular(pNodeT)); + VarE = Cec4_ObjSatId(p, Gia_Regular(pNodeE)); + // get the complementation flags + fCompT = Gia_IsComplement(pNodeT); + fCompE = Gia_IsComplement(pNodeE); + + // f = ITE(i, t, e) + + // i' + t' + f + // i' + t + f' + // i + e' + f + // i + e + f' + + // create four clauses + pLits[0] = Abc_Var2Lit(VarI, 1); + pLits[1] = Abc_Var2Lit(VarT, 1^fCompT); + pLits[2] = Abc_Var2Lit(VarF, 0); + if ( fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); + if ( Gia_Regular(pNodeT)->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = Abc_LitNot( pLits[2] ); + } + RetValue = sat_solver_addclause( pSat, pLits, 3 ); + assert( RetValue ); + pLits[0] = Abc_Var2Lit(VarI, 1); + pLits[1] = Abc_Var2Lit(VarT, 0^fCompT); + pLits[2] = Abc_Var2Lit(VarF, 1); + if ( fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); + if ( Gia_Regular(pNodeT)->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = Abc_LitNot( pLits[2] ); + } + RetValue = sat_solver_addclause( pSat, pLits, 3 ); + assert( RetValue ); + pLits[0] = Abc_Var2Lit(VarI, 0); + pLits[1] = Abc_Var2Lit(VarE, 1^fCompE); + pLits[2] = Abc_Var2Lit(VarF, 0); + if ( fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); + if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = Abc_LitNot( pLits[2] ); + } + RetValue = sat_solver_addclause( pSat, pLits, 3 ); + assert( RetValue ); + pLits[0] = Abc_Var2Lit(VarI, 0); + pLits[1] = Abc_Var2Lit(VarE, 0^fCompE); + pLits[2] = Abc_Var2Lit(VarF, 1); + if ( fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); + if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = Abc_LitNot( pLits[2] ); + } + RetValue = sat_solver_addclause( pSat, pLits, 3 ); + assert( RetValue ); + + // two additional clauses + // t' & e' -> f' + // t & e -> f + + // t + e + f' + // t' + e' + f + + if ( VarT == VarE ) + { +// assert( fCompT == !fCompE ); + return; + } + + pLits[0] = Abc_Var2Lit(VarT, 0^fCompT); + pLits[1] = Abc_Var2Lit(VarE, 0^fCompE); + pLits[2] = Abc_Var2Lit(VarF, 1); + if ( fPolarFlip ) + { + if ( Gia_Regular(pNodeT)->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); + if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = Abc_LitNot( pLits[2] ); + } + RetValue = sat_solver_addclause( pSat, pLits, 3 ); + assert( RetValue ); + pLits[0] = Abc_Var2Lit(VarT, 1^fCompT); + pLits[1] = Abc_Var2Lit(VarE, 1^fCompE); + pLits[2] = Abc_Var2Lit(VarF, 0); + if ( fPolarFlip ) + { + if ( Gia_Regular(pNodeT)->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); + if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = Abc_LitNot( pLits[2] ); + } + RetValue = sat_solver_addclause( pSat, pLits, 3 ); + assert( RetValue ); +} +void Cec4_AddClausesSuper( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Ptr_t * vSuper, sat_solver * pSat ) +{ + int fPolarFlip = 0; + Gia_Obj_t * pFanin; + int * pLits, nLits, RetValue, i; + assert( !Gia_IsComplement(pNode) ); + assert( Gia_ObjIsAnd( pNode ) ); + // create storage for literals + nLits = Vec_PtrSize(vSuper) + 1; + pLits = ABC_ALLOC( int, nLits ); + // suppose AND-gate is A & B = C + // add !A => !C or A + !C + Vec_PtrForEachEntry( Gia_Obj_t *, vSuper, pFanin, i ) + { + pLits[0] = Abc_Var2Lit(Cec4_ObjSatId(p, Gia_Regular(pFanin)), Gia_IsComplement(pFanin)); + pLits[1] = Abc_Var2Lit(Cec4_ObjSatId(p, pNode), 1); + if ( fPolarFlip ) + { + if ( Gia_Regular(pFanin)->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); + if ( pNode->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); + } + RetValue = sat_solver_addclause( pSat, pLits, 2 ); + assert( RetValue ); + } + // add A & B => C or !A + !B + C + Vec_PtrForEachEntry( Gia_Obj_t *, vSuper, pFanin, i ) + { + pLits[i] = Abc_Var2Lit(Cec4_ObjSatId(p, Gia_Regular(pFanin)), !Gia_IsComplement(pFanin)); + if ( fPolarFlip ) + { + if ( Gia_Regular(pFanin)->fPhase ) pLits[i] = Abc_LitNot( pLits[i] ); + } + } + pLits[nLits-1] = Abc_Var2Lit(Cec4_ObjSatId(p, pNode), 0); + if ( fPolarFlip ) + { + if ( pNode->fPhase ) pLits[nLits-1] = Abc_LitNot( pLits[nLits-1] ); + } + RetValue = sat_solver_addclause( pSat, pLits, nLits ); + assert( RetValue ); + ABC_FREE( pLits ); +} + +/**Function************************************************************* + + Synopsis [Adds clauses and returns CNF variable of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec4_CollectSuper_rec( Gia_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) +{ + // if the new node is complemented or a PI, another gate begins + if ( Gia_IsComplement(pObj) || Gia_ObjIsCi(pObj) || + (!fFirst && Gia_ObjValue(pObj) > 1) || + (fUseMuxes && pObj->fMark0) ) + { + Vec_PtrPushUnique( vSuper, pObj ); + return; + } + // go through the branches + Cec4_CollectSuper_rec( Gia_ObjChild0(pObj), vSuper, 0, fUseMuxes ); + Cec4_CollectSuper_rec( Gia_ObjChild1(pObj), vSuper, 0, fUseMuxes ); +} +void Cec4_CollectSuper( Gia_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper ) +{ + assert( !Gia_IsComplement(pObj) ); + assert( !Gia_ObjIsCi(pObj) ); + Vec_PtrClear( vSuper ); + Cec4_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); +} +void Cec4_ObjAddToFrontier( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Ptr_t * vFrontier, sat_solver * pSat ) +{ + assert( !Gia_IsComplement(pObj) ); + assert( !Gia_ObjIsConst0(pObj) ); + if ( Cec4_ObjSatId(p, pObj) >= 0 ) + return; + assert( Cec4_ObjSatId(p, pObj) == -1 ); + Cec4_ObjSetSatId( p, pObj, sat_solver_addvar(pSat) ); + if ( Gia_ObjIsAnd(pObj) ) + Vec_PtrPush( vFrontier, pObj ); +} +int Cec4_ObjGetCnfVar( Cec4_Man_t * p, int iObj ) +{ + int fUseSimple = 1; // enable simple CNF + int fUseMuxes = 1; // enable MUXes when using complex CNF + Gia_Obj_t * pNode, * pFanin; + Gia_Obj_t * pObj = Gia_ManObj(p->pNew, iObj); + int i, k; + // quit if CNF is ready + if ( Cec4_ObjSatId(p->pNew,pObj) >= 0 ) + return Cec4_ObjSatId(p->pNew,pObj); + assert( iObj > 0 ); + if ( Gia_ObjIsCi(pObj) ) + return Cec4_ObjSetSatId( p->pNew, pObj, sat_solver_addvar(p->pSat) ); + assert( Gia_ObjIsAnd(pObj) ); + if ( fUseSimple ) + { + Gia_Obj_t * pFan0, * pFan1; + //if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) + // printf( "%d", (Gia_IsComplement(pFan1) << 1) + Gia_IsComplement(pFan0) ); + if ( p->pNew->pMuxes == NULL && Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) && Gia_IsComplement(pFan0) == Gia_IsComplement(pFan1) ) + { + int iVar0 = Cec4_ObjGetCnfVar( p, Gia_ObjId(p->pNew, Gia_Regular(pFan0)) ); + int iVar1 = Cec4_ObjGetCnfVar( p, Gia_ObjId(p->pNew, Gia_Regular(pFan1)) ); + int iVar = Cec4_ObjSetSatId( p->pNew, pObj, sat_solver_addvar(p->pSat) ); + if ( p->pPars->jType < 2 ) + sat_solver_add_xor( p->pSat, iVar, iVar0, iVar1, 0 ); + if ( p->pPars->jType > 0 ) + { + int Lit0 = Abc_Var2Lit( iVar0, 0 ); + int Lit1 = Abc_Var2Lit( iVar1, 0 ); + if ( Lit0 < Lit1 ) + Lit1 ^= Lit0, Lit0 ^= Lit1, Lit1 ^= Lit0; + assert( Lit0 > Lit1 ); + sat_solver_set_var_fanin_lit( p->pSat, iVar, Lit0, Lit1 ); + p->nGates[1]++; + } + } + else + { + int iVar0 = Cec4_ObjGetCnfVar( p, Gia_ObjFaninId0(pObj, iObj) ); + int iVar1 = Cec4_ObjGetCnfVar( p, Gia_ObjFaninId1(pObj, iObj) ); + int iVar = Cec4_ObjSetSatId( p->pNew, pObj, sat_solver_addvar(p->pSat) ); + if ( p->pPars->jType < 2 ) + { + if ( Gia_ObjIsXor(pObj) ) + sat_solver_add_xor( p->pSat, iVar, iVar0, iVar1, Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pObj) ); + else + sat_solver_add_and( p->pSat, iVar, iVar0, iVar1, Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + } + if ( p->pPars->jType > 0 ) + { + int Lit0 = Abc_Var2Lit( iVar0, Gia_ObjFaninC0(pObj) ); + int Lit1 = Abc_Var2Lit( iVar1, Gia_ObjFaninC1(pObj) ); + if ( (Lit0 > Lit1) ^ Gia_ObjIsXor(pObj) ) + Lit1 ^= Lit0, Lit0 ^= Lit1, Lit1 ^= Lit0; + sat_solver_set_var_fanin_lit( p->pSat, iVar, Lit0, Lit1 ); + p->nGates[Gia_ObjIsXor(pObj)]++; + } + } + return Cec4_ObjSatId( p->pNew, pObj ); + } + assert( !Gia_ObjIsXor(pObj) ); + // start the frontier + Vec_PtrClear( p->vFrontier ); + Cec4_ObjAddToFrontier( p->pNew, pObj, p->vFrontier, p->pSat ); + // explore nodes in the frontier + Vec_PtrForEachEntry( Gia_Obj_t *, p->vFrontier, pNode, i ) + { + // create the supergate + assert( Cec4_ObjSatId(p->pNew,pNode) >= 0 ); + if ( fUseMuxes && pNode->fMark0 ) + { + Vec_PtrClear( p->vFanins ); + Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin0( Gia_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin0( Gia_ObjFanin1(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin1( Gia_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin1( Gia_ObjFanin1(pNode) ) ); + Vec_PtrForEachEntry( Gia_Obj_t *, p->vFanins, pFanin, k ) + Cec4_ObjAddToFrontier( p->pNew, Gia_Regular(pFanin), p->vFrontier, p->pSat ); + Cec4_AddClausesMux( p->pNew, pNode, p->pSat ); + } + else + { + Cec4_CollectSuper( pNode, fUseMuxes, p->vFanins ); + Vec_PtrForEachEntry( Gia_Obj_t *, p->vFanins, pFanin, k ) + Cec4_ObjAddToFrontier( p->pNew, Gia_Regular(pFanin), p->vFrontier, p->pSat ); + Cec4_AddClausesSuper( p->pNew, pNode, p->vFanins, p->pSat ); + } + assert( Vec_PtrSize(p->vFanins) > 1 ); + } + return Cec4_ObjSatId(p->pNew,pObj); +} + + +/**Function************************************************************* + + Synopsis [Refinement of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline word * Cec4_ObjSim( Gia_Man_t * p, int iObj ) +{ + return Vec_WrdEntryP( p->vSims, p->nSimWords * iObj ); +} +static inline int Cec4_ObjSimEqual( Gia_Man_t * p, int iObj0, int iObj1 ) +{ + int w; + word * pSim0 = Cec4_ObjSim( p, iObj0 ); + word * pSim1 = Cec4_ObjSim( p, iObj1 ); + if ( (pSim0[0] & 1) == (pSim1[0] & 1) ) + { + for ( w = 0; w < p->nSimWords; w++ ) + if ( pSim0[w] != pSim1[w] ) + return 0; + return 1; + } + else + { + for ( w = 0; w < p->nSimWords; w++ ) + if ( pSim0[w] != ~pSim1[w] ) + return 0; + return 1; + } +} +int Cec4_ManSimHashKey( word * pSim, int nSims, int nTableSize ) +{ + static int s_Primes[16] = { + 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, + 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 }; + unsigned uHash = 0, * pSimU = (unsigned *)pSim; + int i, nSimsU = 2 * nSims; + if ( pSimU[0] & 1 ) + for ( i = 0; i < nSimsU; i++ ) + uHash ^= ~pSimU[i] * s_Primes[i & 0xf]; + else + for ( i = 0; i < nSimsU; i++ ) + uHash ^= pSimU[i] * s_Primes[i & 0xf]; + return (int)(uHash % nTableSize); + +} +void Cec4_RefineOneClassIter( Gia_Man_t * p, int iRepr ) +{ + int iObj, iPrev = iRepr, iPrev2, iRepr2; + assert( Gia_ObjRepr(p, iRepr) == GIA_VOID ); + assert( Gia_ObjNext(p, iRepr) > 0 ); + Gia_ClassForEachObj1( p, iRepr, iRepr2 ) + if ( Cec4_ObjSimEqual(p, iRepr, iRepr2) ) + iPrev = iRepr2; + else + break; + if ( iRepr2 <= 0 ) // no refinement + return; + // relink remaining nodes of the class + // nodes that are equal to iRepr, remain in the class of iRepr + // nodes that are not equal to iRepr, move to the class of iRepr2 + Gia_ObjSetRepr( p, iRepr2, GIA_VOID ); + iPrev2 = iRepr2; + for ( iObj = Gia_ObjNext(p, iRepr2); iObj > 0; iObj = Gia_ObjNext(p, iObj) ) + { + if ( Cec4_ObjSimEqual(p, iRepr, iObj) ) // remains with iRepr + { + Gia_ObjSetNext( p, iPrev, iObj ); + iPrev = iObj; + } + else // moves to iRepr2 + { + Gia_ObjSetRepr( p, iObj, iRepr2 ); + Gia_ObjSetNext( p, iPrev2, iObj ); + iPrev2 = iObj; + } + } + Gia_ObjSetNext( p, iPrev, -1 ); + Gia_ObjSetNext( p, iPrev2, -1 ); + // refine incrementally + if ( Gia_ObjNext(p, iRepr2) > 0 ) + Cec4_RefineOneClassIter( p, iRepr2 ); +} +void Cec4_RefineOneClass( Gia_Man_t * p, Cec4_Man_t * pMan, Vec_Int_t * vNodes ) +{ + int k, iObj, Bin; + Vec_IntClear( pMan->vRefBins ); + Vec_IntForEachEntryReverse( vNodes, iObj, k ) + { + int Key = Cec4_ManSimHashKey( Cec4_ObjSim(p, iObj), p->nSimWords, pMan->nTableSize ); + assert( Key >= 0 && Key < pMan->nTableSize ); + if ( pMan->pTable[Key] == -1 ) + Vec_IntPush( pMan->vRefBins, Key ); + p->pNexts[iObj] = pMan->pTable[Key]; + pMan->pTable[Key] = iObj; + } + Vec_IntForEachEntry( pMan->vRefBins, Bin, k ) + { + int iRepr = pMan->pTable[Bin]; + pMan->pTable[Bin] = -1; + assert( p->pReprs[iRepr].iRepr == GIA_VOID ); + assert( p->pNexts[iRepr] != 0 ); + if ( p->pNexts[iRepr] == -1 ) + continue; + for ( iObj = p->pNexts[iRepr]; iObj > 0; iObj = p->pNexts[iObj] ) + p->pReprs[iObj].iRepr = iRepr; + Cec4_RefineOneClassIter( p, iRepr ); + } + Vec_IntClear( pMan->vRefBins ); +} +void Cec4_RefineClasses( Gia_Man_t * p, Cec4_Man_t * pMan, Vec_Int_t * vClasses ) +{ + if ( Vec_IntSize(pMan->vRefClasses) == 0 ) + return; + if ( Vec_IntSize(pMan->vRefNodes) > 0 ) + Cec4_RefineOneClass( p, pMan, pMan->vRefNodes ); + else + { + int i, k, iObj, iRepr; + Vec_IntForEachEntry( pMan->vRefClasses, iRepr, i ) + { + assert( p->pReprs[iRepr].fColorA ); + p->pReprs[iRepr].fColorA = 0; + Vec_IntClear( pMan->vRefNodes ); + Vec_IntPush( pMan->vRefNodes, iRepr ); + Gia_ClassForEachObj1( p, iRepr, k ) + Vec_IntPush( pMan->vRefNodes, k ); + Vec_IntForEachEntry( pMan->vRefNodes, iObj, k ) + { + p->pReprs[iObj].iRepr = GIA_VOID; + p->pNexts[iObj] = -1; + } + Cec4_RefineOneClass( p, pMan, pMan->vRefNodes ); + } + } + Vec_IntClear( pMan->vRefClasses ); + Vec_IntClear( pMan->vRefNodes ); +} +void Cec4_RefineInit( Gia_Man_t * p, Cec4_Man_t * pMan ) +{ + Gia_Obj_t * pObj; int i; + ABC_FREE( p->pReprs ); + ABC_FREE( p->pNexts ); + p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); + p->pNexts = ABC_FALLOC( int, Gia_ManObjNum(p) ); + pMan->nTableSize = Abc_PrimeCudd( Gia_ManObjNum(p) ); + pMan->pTable = ABC_FALLOC( int, pMan->nTableSize ); + pMan->vRefNodes = Vec_IntAlloc( Gia_ManObjNum(p) ); + Gia_ManForEachObj( p, pObj, i ) + { + p->pReprs[i].iRepr = GIA_VOID; + if ( !Gia_ObjIsCo(pObj) && (!pMan->pPars->nLevelMax || Gia_ObjLevel(p, pObj) <= pMan->pPars->nLevelMax) ) + Vec_IntPush( pMan->vRefNodes, i ); + } + pMan->vRefBins = Vec_IntAlloc( Gia_ManObjNum(p)/2 ); + pMan->vRefClasses = Vec_IntAlloc( Gia_ManObjNum(p)/2 ); + Vec_IntPush( pMan->vRefClasses, 0 ); +} + + +/**Function************************************************************* + + Synopsis [Internal simulation APIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cec4_ObjSimSetInputBit( Gia_Man_t * p, int iObj, int Bit ) +{ + word * pSim = Cec4_ObjSim( p, iObj ); + if ( Abc_InfoHasBit( (unsigned*)pSim, p->iPatsPi ) != Bit ) + Abc_InfoXorBit( (unsigned*)pSim, p->iPatsPi ); +} +static inline int Cec4_ObjSimGetInputBit( Gia_Man_t * p, int iObj ) +{ + word * pSim = Cec4_ObjSim( p, iObj ); + return Abc_InfoHasBit( (unsigned*)pSim, p->iPatsPi ); +} +static inline void Cec4_ObjSimRo( Gia_Man_t * p, int iObj ) +{ + int w; + word * pSimRo = Cec4_ObjSim( p, iObj ); + word * pSimRi = Cec4_ObjSim( p, Gia_ObjRoToRiId(p, iObj) ); + for ( w = 0; w < p->nSimWords; w++ ) + pSimRo[w] = pSimRi[w]; +} +static inline void Cec4_ObjSimCo( Gia_Man_t * p, int iObj ) +{ + int w; + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + word * pSimCo = Cec4_ObjSim( p, iObj ); + word * pSimDri = Cec4_ObjSim( p, Gia_ObjFaninId0(pObj, iObj) ); + if ( Gia_ObjFaninC0(pObj) ) + for ( w = 0; w < p->nSimWords; w++ ) + pSimCo[w] = ~pSimDri[w]; + else + for ( w = 0; w < p->nSimWords; w++ ) + pSimCo[w] = pSimDri[w]; +} +static inline void Cec4_ObjSimAnd( Gia_Man_t * p, int iObj ) +{ + int w; + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + word * pSim = Cec4_ObjSim( p, iObj ); + word * pSim0 = Cec4_ObjSim( p, Gia_ObjFaninId0(pObj, iObj) ); + word * pSim1 = Cec4_ObjSim( p, Gia_ObjFaninId1(pObj, iObj) ); + if ( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = ~pSim0[w] & ~pSim1[w]; + else if ( Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ) + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = ~pSim0[w] & pSim1[w]; + else if ( !Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = pSim0[w] & ~pSim1[w]; + else + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = pSim0[w] & pSim1[w]; +} +static inline void Cec4_ObjSimXor( Gia_Man_t * p, int iObj ) +{ + int w; + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + word * pSim = Cec4_ObjSim( p, iObj ); + word * pSim0 = Cec4_ObjSim( p, Gia_ObjFaninId0(pObj, iObj) ); + word * pSim1 = Cec4_ObjSim( p, Gia_ObjFaninId1(pObj, iObj) ); + if ( Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pObj) ) + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = ~pSim0[w] ^ pSim1[w]; + else + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = pSim0[w] ^ pSim1[w]; +} +static inline void Cec4_ObjSimCi( Gia_Man_t * p, int iObj ) +{ + int w; + word * pSim = Cec4_ObjSim( p, iObj ); + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = Gia_ManRandomW( 0 ); + pSim[0] <<= 1; +} +static inline void Cec4_ObjClearSimCi( Gia_Man_t * p, int iObj ) +{ + int w; + word * pSim = Cec4_ObjSim( p, iObj ); + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = 0; +} +void Cec4_ManSimulateCis( Gia_Man_t * p ) +{ + int i, Id; + Gia_ManForEachCiId( p, Id, i ) + Cec4_ObjSimCi( p, Id ); + p->iPatsPi = 0; +} +void Cec4_ManClearCis( Gia_Man_t * p ) +{ + int i, Id; + Gia_ManForEachCiId( p, Id, i ) + Cec4_ObjClearSimCi( p, Id ); + p->iPatsPi = 0; +} +Abc_Cex_t * Cec4_ManDeriveCex( Gia_Man_t * p, int iOut, int iPat ) +{ + Abc_Cex_t * pCex; + int i, Id; + pCex = Abc_CexAlloc( 0, Gia_ManCiNum(p), 1 ); + pCex->iPo = iOut; + if ( iPat == -1 ) + return pCex; + Gia_ManForEachCiId( p, Id, i ) + if ( Abc_InfoHasBit((unsigned *)Cec4_ObjSim(p, Id), iPat) ) + Abc_InfoSetBit( pCex->pData, i ); + return pCex; +} +int Cec4_ManSimulateCos( Gia_Man_t * p ) +{ + int i, Id; + // check outputs and generate CEX if they fail + Gia_ManForEachCoId( p, Id, i ) + { + Cec4_ObjSimCo( p, Id ); + if ( Cec4_ObjSimEqual(p, Id, 0) ) + continue; + p->pCexSeq = Cec4_ManDeriveCex( p, i, Abc_TtFindFirstBit2(Cec4_ObjSim(p, Id), p->nSimWords) ); + return 0; + } + return 1; +} +void Cec4_ManSimulate( Gia_Man_t * p, Cec4_Man_t * pMan ) +{ + abctime clk = Abc_Clock(); + Gia_Obj_t * pObj; int i; + pMan->nSimulates++; + if ( pMan->pTable == NULL ) + Cec4_RefineInit( p, pMan ); + else + assert( Vec_IntSize(pMan->vRefClasses) == 0 ); + Gia_ManForEachAnd( p, pObj, i ) + { + int iRepr = Gia_ObjRepr( p, i ); + if ( Gia_ObjIsXor(pObj) ) + Cec4_ObjSimXor( p, i ); + else + Cec4_ObjSimAnd( p, i ); + if ( iRepr == GIA_VOID || p->pReprs[iRepr].fColorA || Cec4_ObjSimEqual(p, iRepr, i) ) + continue; + p->pReprs[iRepr].fColorA = 1; + Vec_IntPush( pMan->vRefClasses, iRepr ); + } + pMan->timeSim += Abc_Clock() - clk; + clk = Abc_Clock(); + Cec4_RefineClasses( p, pMan, pMan->vRefClasses ); + pMan->timeRefine += Abc_Clock() - clk; +} +void Cec4_ManSimulate_rec( Gia_Man_t * p, Cec4_Man_t * pMan, int iObj ) +{ + Gia_Obj_t * pObj; + if ( !iObj || Vec_IntEntry(pMan->vCexStamps, iObj) == p->iPatsPi ) + return; + Vec_IntWriteEntry( pMan->vCexStamps, iObj, p->iPatsPi ); + pObj = Gia_ManObj(p, iObj); + if ( Gia_ObjIsCi(pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Cec4_ManSimulate_rec( p, pMan, Gia_ObjFaninId0(pObj, iObj) ); + Cec4_ManSimulate_rec( p, pMan, Gia_ObjFaninId1(pObj, iObj) ); + if ( Gia_ObjIsXor(pObj) ) + Cec4_ObjSimXor( p, iObj ); + else + Cec4_ObjSimAnd( p, iObj ); +} +void Cec4_ManSimAlloc( Gia_Man_t * p, int nWords ) +{ + Vec_WrdFreeP( &p->vSims ); + Vec_WrdFreeP( &p->vSimsPi ); + p->vSims = Vec_WrdStart( Gia_ManObjNum(p) * nWords ); + p->vSimsPi = Vec_WrdStart( (Gia_ManCiNum(p) + 1) * nWords ); + p->nSimWords = nWords; +} + + +/**Function************************************************************* + + Synopsis [Creating initial equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec4_ManPrintTfiConeStats( Gia_Man_t * p ) +{ + Vec_Int_t * vRoots = Vec_IntAlloc( 100 ); + Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); + Vec_Int_t * vLeaves = Vec_IntAlloc( 100 ); + int i, k; + Gia_ManForEachClass0( p, i ) + { + Vec_IntClear( vRoots ); + if ( i % 100 != 0 ) + continue; + Vec_IntPush( vRoots, i ); + Gia_ClassForEachObj1( p, i, k ) + Vec_IntPush( vRoots, k ); + Gia_ManCollectTfi( p, vRoots, vNodes ); + printf( "Class %6d : ", i ); + printf( "Roots = %6d ", Vec_IntSize(vRoots) ); + printf( "Nodes = %6d ", Vec_IntSize(vNodes) ); + printf( "\n" ); + } + Vec_IntFree( vRoots ); + Vec_IntFree( vNodes ); + Vec_IntFree( vLeaves ); +} +void Cec4_ManPrintStats( Gia_Man_t * p, Cec_ParFra_t * pPars, Cec4_Man_t * pMan, int fSim ) +{ + static abctime clk = 0; + abctime clkThis = 0; + int i, nLits, Counter = 0, Counter0 = 0, CounterX = 0; + if ( !pPars->fVerbose ) + return; + if ( pMan->nItersSim + pMan->nItersSat ) + clkThis = Abc_Clock() - clk; + clk = Abc_Clock(); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + { + if ( Gia_ObjIsHead(p, i) ) + Counter++; + else if ( Gia_ObjIsConst(p, i) ) + Counter0++; + else if ( Gia_ObjIsNone(p, i) ) + CounterX++; + } + nLits = Gia_ManObjNum(p) - Counter - CounterX; + if ( fSim ) + { + printf( "Sim %4d : ", pMan->nItersSim++ + pMan->nItersSat ); + printf( "%6.2f %% ", 100.0*nLits/Gia_ManCandNum(p) ); + } + else + { + printf( "SAT %4d : ", pMan->nItersSim + pMan->nItersSat++ ); + printf( "%6.2f %% ", 100.0*pMan->nAndNodes/Gia_ManAndNum(p) ); + } + printf( "P =%7d ", pMan ? pMan->nSatUnsat : 0 ); + printf( "D =%7d ", pMan ? pMan->nSatSat : 0 ); + printf( "F =%8d ", pMan ? pMan->nSatUndec : 0 ); + //printf( "Last =%6d ", pMan ? pMan->iLastConst : 0 ); + Abc_Print( 1, "cst =%9d cls =%8d lit =%9d ", Counter0, Counter, nLits ); + Abc_PrintTime( 1, "Time", clkThis ); +} +void Cec4_ManPrintClasses2( Gia_Man_t * p ) +{ + int i, k; + Gia_ManForEachClass0( p, i ) + { + printf( "Class %d : ", i ); + Gia_ClassForEachObj1( p, i, k ) + printf( "%d ", k ); + printf( "\n" ); + } +} +void Cec4_ManPrintClasses( Gia_Man_t * p ) +{ + int k, Count = 0; + Gia_ClassForEachObj1( p, 0, k ) + Count++; + printf( "Const0 class has %d entries.\n", Count ); +} + + +/**Function************************************************************* + + Synopsis [Verify counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec4_ManVerify_rec( Gia_Man_t * p, int iObj, sat_solver * pSat ) +{ + int Value0, Value1; + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + if ( iObj == 0 ) return 0; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return pObj->fMark1; + Gia_ObjSetTravIdCurrentId(p, iObj); + if ( Gia_ObjIsCi(pObj) ) + return pObj->fMark1 = sat_solver_read_cex_varvalue(pSat, Cec4_ObjSatId(p, pObj)); + assert( Gia_ObjIsAnd(pObj) ); + Value0 = Cec4_ManVerify_rec( p, Gia_ObjFaninId0(pObj, iObj), pSat ) ^ Gia_ObjFaninC0(pObj); + Value1 = Cec4_ManVerify_rec( p, Gia_ObjFaninId1(pObj, iObj), pSat ) ^ Gia_ObjFaninC1(pObj); + return pObj->fMark1 = Gia_ObjIsXor(pObj) ? Value0 ^ Value1 : Value0 & Value1; +} +void Cec4_ManVerify( Gia_Man_t * p, int iObj0, int iObj1, int fPhase, sat_solver * pSat ) +{ + int Value0, Value1; + Gia_ManIncrementTravId( p ); + Value0 = Cec4_ManVerify_rec( p, iObj0, pSat ); + Value1 = Cec4_ManVerify_rec( p, iObj1, pSat ); + if ( (Value0 ^ Value1) == fPhase ) + printf( "CEX verification FAILED for obj %d and obj %d.\n", iObj0, iObj1 ); +// else +// printf( "CEX verification succeeded for obj %d and obj %d.\n", iObj0, iObj1 );; +} + + +/**Function************************************************************* + + Synopsis [Verify counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec4_ManCexVerify_rec( Gia_Man_t * p, int iObj ) +{ + int Value0, Value1; + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + if ( iObj == 0 ) return 0; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return pObj->fMark1; + Gia_ObjSetTravIdCurrentId(p, iObj); + if ( Gia_ObjIsCi(pObj) ) + return pObj->fMark1 = Cec4_ObjSimGetInputBit(p, iObj); + assert( Gia_ObjIsAnd(pObj) ); + Value0 = Cec4_ManCexVerify_rec( p, Gia_ObjFaninId0(pObj, iObj) ) ^ Gia_ObjFaninC0(pObj); + Value1 = Cec4_ManCexVerify_rec( p, Gia_ObjFaninId1(pObj, iObj) ) ^ Gia_ObjFaninC1(pObj); + return pObj->fMark1 = Gia_ObjIsXor(pObj) ? Value0 ^ Value1 : Value0 & Value1; +} +void Cec4_ManCexVerify( Gia_Man_t * p, int iObj0, int iObj1, int fPhase ) +{ + int Value0, Value1; + Gia_ManIncrementTravId( p ); + Value0 = Cec4_ManCexVerify_rec( p, iObj0 ); + Value1 = Cec4_ManCexVerify_rec( p, iObj1 ); + if ( (Value0 ^ Value1) == fPhase ) + printf( "CEX verification FAILED for obj %d and obj %d.\n", iObj0, iObj1 ); +// else +// printf( "CEX verification succeeded for obj %d and obj %d.\n", iObj0, iObj1 );; +} + +/**Function************************************************************* + + Synopsis [Packs simulation patterns into array of simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +*************************************`**********************************/ +void Cec4_ManPackAddPatterns( Gia_Man_t * p, int iBit, Vec_Int_t * vLits ) +{ + int k, Limit = Abc_MinInt( Vec_IntSize(vLits), 64 * p->nSimWords - 1 ); + for ( k = 0; k < Limit; k++ ) + { + int i, Lit, iBitLocal = (iBit + k + 1) % Limit + 1; + assert( iBitLocal > 0 && iBitLocal < 64 * p->nSimWords ); + Vec_IntForEachEntry( vLits, Lit, i ) + { + word * pInfo = Vec_WrdEntryP( p->vSims, p->nSimWords * Abc_Lit2Var(Lit) ); + word * pPres = Vec_WrdEntryP( p->vSimsPi, p->nSimWords * Abc_Lit2Var(Lit) ); + if ( Abc_InfoHasBit( (unsigned *)pPres, iBitLocal ) ) + continue; + if ( Abc_InfoHasBit( (unsigned *)pInfo, iBitLocal ) != Abc_LitIsCompl(Lit ^ (i == k)) ) + Abc_InfoXorBit( (unsigned *)pInfo, iBitLocal ); + } + } +} +int Cec4_ManPackAddPatternTry( Gia_Man_t * p, int iBit, Vec_Int_t * vLits ) +{ + int i, Lit; + assert( p->iPatsPi > 0 && p->iPatsPi < 64 * p->nSimWords ); + Vec_IntForEachEntry( vLits, Lit, i ) + { + word * pInfo = Vec_WrdEntryP( p->vSims, p->nSimWords * Abc_Lit2Var(Lit) ); + word * pPres = Vec_WrdEntryP( p->vSimsPi, p->nSimWords * Abc_Lit2Var(Lit) ); + if ( Abc_InfoHasBit( (unsigned *)pPres, iBit ) && + Abc_InfoHasBit( (unsigned *)pInfo, iBit ) != Abc_LitIsCompl(Lit) ) + return 0; + } + Vec_IntForEachEntry( vLits, Lit, i ) + { + word * pInfo = Vec_WrdEntryP( p->vSims, p->nSimWords * Abc_Lit2Var(Lit) ); + word * pPres = Vec_WrdEntryP( p->vSimsPi, p->nSimWords * Abc_Lit2Var(Lit) ); + Abc_InfoSetBit( (unsigned *)pPres, iBit ); + if ( Abc_InfoHasBit( (unsigned *)pInfo, iBit ) != Abc_LitIsCompl(Lit) ) + Abc_InfoXorBit( (unsigned *)pInfo, iBit ); + } + return 1; +} +int Cec4_ManPackAddPattern( Gia_Man_t * p, Vec_Int_t * vLits, int fExtend ) +{ + int k; + for ( k = 1; k < 64 * p->nSimWords - 1; k++ ) + { + if ( ++p->iPatsPi == 64 * p->nSimWords - 1 ) + p->iPatsPi = 1; + if ( Cec4_ManPackAddPatternTry( p, p->iPatsPi, vLits ) ) + { + if ( fExtend ) + Cec4_ManPackAddPatterns( p, p->iPatsPi, vLits ); + break; + } + } + if ( k == 64 * p->nSimWords - 1 ) + { + p->iPatsPi = k; + if ( !Cec4_ManPackAddPatternTry( p, p->iPatsPi, vLits ) ) + printf( "Internal error.\n" ); + else if ( fExtend ) + Cec4_ManPackAddPatterns( p, p->iPatsPi, vLits ); + return 64 * p->nSimWords; + } + return k; +} + +/**Function************************************************************* + + Synopsis [Generates counter-examples to refine the candidate equivalences.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cec4_ObjFan0IsAssigned( Gia_Obj_t * pObj ) +{ + return Gia_ObjFanin0(pObj)->fMark0 || Gia_ObjFanin0(pObj)->fMark1; +} +static inline int Cec4_ObjFan1IsAssigned( Gia_Obj_t * pObj ) +{ + return Gia_ObjFanin1(pObj)->fMark0 || Gia_ObjFanin1(pObj)->fMark1; +} +static inline int Cec4_ObjFan0HasValue( Gia_Obj_t * pObj, int v ) +{ + return (v ^ Gia_ObjFaninC0(pObj)) ? Gia_ObjFanin0(pObj)->fMark1 : Gia_ObjFanin0(pObj)->fMark0; +} +static inline int Cec4_ObjFan1HasValue( Gia_Obj_t * pObj, int v ) +{ + return (v ^ Gia_ObjFaninC1(pObj)) ? Gia_ObjFanin1(pObj)->fMark1 : Gia_ObjFanin1(pObj)->fMark0; +} +static inline int Cec4_ObjObjIsImpliedValue( Gia_Obj_t * pObj, int v ) +{ + assert( !pObj->fMark0 && !pObj->fMark1 ); // not visited + if ( v ) + return Cec4_ObjFan0HasValue(pObj, 1) && Cec4_ObjFan1HasValue(pObj, 1); + return Cec4_ObjFan0HasValue(pObj, 0) || Cec4_ObjFan1HasValue(pObj, 0); +} +static inline int Cec4_ObjFan0IsImpliedValue( Gia_Obj_t * pObj, int v ) +{ + return Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) && Cec4_ObjObjIsImpliedValue( Gia_ObjFanin0(pObj), v ^ Gia_ObjFaninC0(pObj) ); +} +static inline int Cec4_ObjFan1IsImpliedValue( Gia_Obj_t * pObj, int v ) +{ + return Gia_ObjIsAnd(Gia_ObjFanin1(pObj)) && Cec4_ObjObjIsImpliedValue( Gia_ObjFanin1(pObj), v ^ Gia_ObjFaninC1(pObj) ); +} +int Cec4_ManGeneratePatterns_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int Value, Vec_Int_t * vPat, Vec_Int_t * vVisit ) +{ + Gia_Obj_t * pFan0, * pFan1; + assert( !pObj->fMark0 && !pObj->fMark1 ); // not visited + if ( Value ) pObj->fMark1 = 1; else pObj->fMark0 = 1; + Vec_IntPush( vVisit, Gia_ObjId(p, pObj) ); + if ( Gia_ObjIsCi(pObj) ) + { + Vec_IntPush( vPat, Abc_Var2Lit(Gia_ObjId(p, pObj), Value) ); + return 1; + } + assert( Gia_ObjIsAnd(pObj) ); + pFan0 = Gia_ObjFanin0(pObj); + pFan1 = Gia_ObjFanin1(pObj); + if ( Gia_ObjIsXor(pObj) ) + { + int Ass0 = Cec4_ObjFan0IsAssigned(pObj); + int Ass1 = Cec4_ObjFan1IsAssigned(pObj); + assert( Gia_ObjFaninC0(pObj) == 0 && Gia_ObjFaninC1(pObj) == 0 ); + if ( Ass0 && Ass1 ) + return Value == (Cec4_ObjFan0HasValue(pObj, 1) ^ Cec4_ObjFan1HasValue(pObj, 1)); + if ( Ass0 ) + { + int ValueInt = Value ^ Cec4_ObjFan0HasValue(pObj, 1); + if ( !Cec4_ManGeneratePatterns_rec(p, pFan1, ValueInt, vPat, vVisit) ) + return 0; + } + else if ( Ass1 ) + { + int ValueInt = Value ^ Cec4_ObjFan1HasValue(pObj, 1); + if ( !Cec4_ManGeneratePatterns_rec(p, pFan0, ValueInt, vPat, vVisit) ) + return 0; + } + else if ( Abc_Random(0) & 1 ) + { + if ( !Cec4_ManGeneratePatterns_rec(p, pFan0, 0, vPat, vVisit) ) + return 0; + if ( Cec4_ObjFan1HasValue(pObj, !Value) || (!Cec4_ObjFan1HasValue(pObj, Value) && !Cec4_ManGeneratePatterns_rec(p, pFan1, Value, vPat, vVisit)) ) + return 0; + } + else + { + if ( !Cec4_ManGeneratePatterns_rec(p, pFan0, 1, vPat, vVisit) ) + return 0; + if ( Cec4_ObjFan1HasValue(pObj, Value) || (!Cec4_ObjFan1HasValue(pObj, !Value) && !Cec4_ManGeneratePatterns_rec(p, pFan1, !Value, vPat, vVisit)) ) + return 0; + } + assert( Value == (Cec4_ObjFan0HasValue(pObj, 1) ^ Cec4_ObjFan1HasValue(pObj, 1)) ); + return 1; + } + else if ( Value ) + { + if ( Cec4_ObjFan0HasValue(pObj, 0) || Cec4_ObjFan1HasValue(pObj, 0) ) + return 0; + if ( !Cec4_ObjFan0HasValue(pObj, 1) && !Cec4_ManGeneratePatterns_rec(p, pFan0, !Gia_ObjFaninC0(pObj), vPat, vVisit) ) + return 0; + if ( !Cec4_ObjFan1HasValue(pObj, 1) && !Cec4_ManGeneratePatterns_rec(p, pFan1, !Gia_ObjFaninC1(pObj), vPat, vVisit) ) + return 0; + assert( Cec4_ObjFan0HasValue(pObj, 1) && Cec4_ObjFan1HasValue(pObj, 1) ); + return 1; + } + else + { + if ( Cec4_ObjFan0HasValue(pObj, 1) && Cec4_ObjFan1HasValue(pObj, 1) ) + return 0; + if ( Cec4_ObjFan0HasValue(pObj, 0) || Cec4_ObjFan1HasValue(pObj, 0) ) + return 1; + if ( Cec4_ObjFan0HasValue(pObj, 1) ) + { + if ( !Cec4_ManGeneratePatterns_rec(p, pFan1, Gia_ObjFaninC1(pObj), vPat, vVisit) ) + return 0; + } + else if ( Cec4_ObjFan1HasValue(pObj, 1) ) + { + if ( !Cec4_ManGeneratePatterns_rec(p, pFan0, Gia_ObjFaninC0(pObj), vPat, vVisit) ) + return 0; + } + else + { + if ( Cec4_ObjFan0IsImpliedValue( pObj, 0 ) ) + { + if ( !Cec4_ManGeneratePatterns_rec(p, pFan0, Gia_ObjFaninC0(pObj), vPat, vVisit) ) + return 0; + } + else if ( Cec4_ObjFan1IsImpliedValue( pObj, 0 ) ) + { + if ( !Cec4_ManGeneratePatterns_rec(p, pFan1, Gia_ObjFaninC1(pObj), vPat, vVisit) ) + return 0; + } + else if ( Cec4_ObjFan0IsImpliedValue( pObj, 1 ) ) + { + if ( !Cec4_ManGeneratePatterns_rec(p, pFan1, Gia_ObjFaninC1(pObj), vPat, vVisit) ) + return 0; + } + else if ( Cec4_ObjFan1IsImpliedValue( pObj, 1 ) ) + { + if ( !Cec4_ManGeneratePatterns_rec(p, pFan0, Gia_ObjFaninC0(pObj), vPat, vVisit) ) + return 0; + } + else if ( Abc_Random(0) & 1 ) + { + if ( !Cec4_ManGeneratePatterns_rec(p, pFan1, Gia_ObjFaninC1(pObj), vPat, vVisit) ) + return 0; + } + else + { + if ( !Cec4_ManGeneratePatterns_rec(p, pFan0, Gia_ObjFaninC0(pObj), vPat, vVisit) ) + return 0; + } + } + assert( Cec4_ObjFan0HasValue(pObj, 0) || Cec4_ObjFan1HasValue(pObj, 0) ); + return 1; + } +} +int Cec4_ManGeneratePatternOne( Gia_Man_t * p, int iRepr, int iReprVal, int iCand, int iCandVal, Vec_Int_t * vPat, Vec_Int_t * vVisit ) +{ + int Res, k; + Gia_Obj_t * pObj; + assert( iCand > 0 ); + if ( !iRepr && iReprVal ) + return 0; + Vec_IntClear( vPat ); + Vec_IntClear( vVisit ); + //Gia_ManForEachObj( p, pObj, k ) + // assert( !pObj->fMark0 && !pObj->fMark1 ); + Res = (!iRepr || Cec4_ManGeneratePatterns_rec(p, Gia_ManObj(p, iRepr), iReprVal, vPat, vVisit)) && Cec4_ManGeneratePatterns_rec(p, Gia_ManObj(p, iCand), iCandVal, vPat, vVisit); + Gia_ManForEachObjVec( vVisit, p, pObj, k ) + pObj->fMark0 = pObj->fMark1 = 0; + return Res; +} +void Cec4_ManCandIterStart( Cec4_Man_t * p ) +{ + int i, * pArray; + assert( p->iPosWrite == 0 ); + assert( p->iPosRead == 0 ); + assert( Vec_IntSize(p->vCands) == 0 ); + for ( i = 1; i < Gia_ManObjNum(p->pAig); i++ ) + if ( Gia_ObjRepr(p->pAig, i) != GIA_VOID ) + Vec_IntPush( p->vCands, i ); + pArray = Vec_IntArray( p->vCands ); + for ( i = 0; i < Vec_IntSize(p->vCands); i++ ) + { + int iNew = Abc_Random(0) % Vec_IntSize(p->vCands); + ABC_SWAP( int, pArray[i], pArray[iNew] ); + } +} +int Cec4_ManCandIterNext( Cec4_Man_t * p ) +{ + while ( Vec_IntSize(p->vCands) > 0 ) + { + int fStop, iCand = Vec_IntEntry( p->vCands, p->iPosRead ); + if ( (fStop = (Gia_ObjRepr(p->pAig, iCand) != GIA_VOID)) ) + Vec_IntWriteEntry( p->vCands, p->iPosWrite++, iCand ); + if ( ++p->iPosRead == Vec_IntSize(p->vCands) ) + { + Vec_IntShrink( p->vCands, p->iPosWrite ); + p->iPosWrite = 0; + p->iPosRead = 0; + } + if ( fStop ) + return iCand; + } + return 0; +} +int Cec4_ManGeneratePatterns( Cec4_Man_t * p ) +{ + abctime clk = Abc_Clock(); + int i, iCand, nPats = 100 * 64 * p->pAig->nSimWords, CountPat = 0, Packs = 0; + //int iRepr; + //Vec_IntForEachEntryDouble( p->vDisprPairs, iRepr, iCand, i ) + // if ( iRepr == Gia_ObjRepr(p->pAig, iCand) ) + // printf( "Pair %6d (%6d, %6d) (new repr = %9d) is FAILED to disprove.\n", i, iRepr, iCand, Gia_ObjRepr(p->pAig, iCand) ); + // else + // printf( "Pair %6d (%6d, %6d) (new repr = %9d) is disproved.\n", i, iRepr, iCand, Gia_ObjRepr(p->pAig, iCand) ); + //Vec_IntClear( p->vDisprPairs ); + p->pAig->iPatsPi = 0; + Vec_WrdFill( p->pAig->vSimsPi, Vec_WrdSize(p->pAig->vSimsPi), 0 ); + for ( i = 0; i < nPats; i++ ) + if ( (iCand = Cec4_ManCandIterNext(p)) ) + { + int iRepr = Gia_ObjRepr( p->pAig, iCand ); + int iCandVal = Gia_ManObj(p->pAig, iCand)->fPhase; + int iReprVal = Gia_ManObj(p->pAig, iRepr)->fPhase; + int Res = Cec4_ManGeneratePatternOne( p->pAig, iRepr, iReprVal, iCand, !iCandVal, p->vPat, p->vVisit ); + if ( !Res ) + Res = Cec4_ManGeneratePatternOne( p->pAig, iRepr, !iReprVal, iCand, iCandVal, p->vPat, p->vVisit ); + if ( Res ) + { + int Ret = Cec4_ManPackAddPattern( p->pAig, p->vPat, 1 ); + if ( p->pAig->vPats ) + { + Vec_IntPush( p->pAig->vPats, Vec_IntSize(p->vPat)+2 ); + Vec_IntAppend( p->pAig->vPats, p->vPat ); + Vec_IntPush( p->pAig->vPats, -1 ); + } + //Vec_IntPushTwo( p->vDisprPairs, iRepr, iCand ); + Packs += Ret; + if ( Ret == 64 * p->pAig->nSimWords ) + break; + if ( ++CountPat == 8 * 64 * p->pAig->nSimWords ) + break; + //Cec4_ManCexVerify( p->pAig, iRepr, iCand, iReprVal ^ iCandVal ); + //Gia_ManCleanMark01( p->pAig ); + } + } + p->timeGenPats += Abc_Clock() - clk; + p->nSatSat += CountPat; + //printf( "%3d : %6.2f %% : Generated %6d CEXs after trying %6d pairs. Ave packs = %9.2f Ave tries = %9.2f (Limit = %9.2f)\n", + // p->nItersSim++, 100.0*Vec_IntSize(p->vCands)/Gia_ManAndNum(p->pAig), + // CountPat, i, (float)Packs / Abc_MaxInt(1, CountPat), (float)i / Abc_MaxInt(1, CountPat), (float)nPats / p->pPars->nItersMax ); + return CountPat >= i / p->pPars->nItersMax; +} + + +/**Function************************************************************* + + Synopsis [Internal simulation APIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec4_ManSatSolverRecycle( Cec4_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + //printf( "Solver size = %d.\n", sat_solver_varnum(p->pSat) ); + p->nRecycles++; + p->nCallsSince = 0; + sat_solver_reset( p->pSat ); + // clean mapping of AigIds into SatIds + Gia_ManForEachObjVec( &p->pNew->vSuppVars, p->pNew, pObj, i ) + Cec4_ObjCleanSatId( p->pNew, pObj ); + Vec_IntClear( &p->pNew->vSuppVars ); // AigIds for which SatId is defined + Vec_IntClear( &p->pNew->vCopiesTwo ); // pairs (CiAigId, SatId) + Vec_IntClear( &p->pNew->vVarMap ); // mapping of SatId into AigId +} +int Cec4_ManSolveTwo( Cec4_Man_t * p, int iObj0, int iObj1, int fPhase, int * pfEasy, int fVerbose, int fEffort ) +{ + abctime clk; + int nBTLimit = fEffort ? p->pPars->nBTLimitPo : (Vec_BitEntry(p->vFails, iObj0) || Vec_BitEntry(p->vFails, iObj1)) ? Abc_MaxInt(1, p->pPars->nBTLimit/10) : p->pPars->nBTLimit; + int nConfEnd, nConfBeg, status, iVar0, iVar1, Lits[2]; + int UnsatConflicts[3] = {0}; + //printf( "%d ", nBTLimit ); + if ( iObj1 < iObj0 ) + iObj1 ^= iObj0, iObj0 ^= iObj1, iObj1 ^= iObj0; + assert( iObj0 < iObj1 ); + *pfEasy = 0; + // check if SAT solver needs recycling + p->nCallsSince++; + if ( p->nCallsSince > p->pPars->nCallsRecycle && + Vec_IntSize(&p->pNew->vSuppVars) > p->pPars->nSatVarMax && p->pPars->nSatVarMax ) + Cec4_ManSatSolverRecycle( p ); + // add more logic to the solver + if ( !iObj0 && Cec4_ObjSatId(p->pNew, Gia_ManConst0(p->pNew)) == -1 ) + Cec4_ObjSetSatId( p->pNew, Gia_ManConst0(p->pNew), sat_solver_addvar(p->pSat) ); + clk = Abc_Clock(); + iVar0 = Cec4_ObjGetCnfVar( p, iObj0 ); + iVar1 = Cec4_ObjGetCnfVar( p, iObj1 ); + if( p->pPars->jType > 0 ) + { + sat_solver_start_new_round( p->pSat ); + sat_solver_mark_cone( p->pSat, Cec4_ObjSatId(p->pNew, Gia_ManObj(p->pNew, iObj0)) ); + sat_solver_mark_cone( p->pSat, Cec4_ObjSatId(p->pNew, Gia_ManObj(p->pNew, iObj1)) ); + } + p->timeCnf += Abc_Clock() - clk; + // perform solving + Lits[0] = Abc_Var2Lit(iVar0, 1); + Lits[1] = Abc_Var2Lit(iVar1, fPhase); + sat_solver_set_conflict_budget( p->pSat, nBTLimit ); + nConfBeg = sat_solver_conflictnum( p->pSat ); + status = sat_solver_solve( p->pSat, Lits, 2 ); + nConfEnd = sat_solver_conflictnum( p->pSat ); + assert( nConfEnd >= nConfBeg ); + if ( fVerbose ) + { + if ( status == GLUCOSE_SAT ) + { + p->nConflicts[0][0] += nConfEnd == nConfBeg; + p->nConflicts[0][1] += nConfEnd - nConfBeg; + p->nConflicts[0][2] = Abc_MaxInt(p->nConflicts[0][2], nConfEnd - nConfBeg); + *pfEasy = nConfEnd == nConfBeg; + } + else if ( status == GLUCOSE_UNSAT ) + { + if ( iObj0 > 0 ) + { + UnsatConflicts[0] = nConfEnd == nConfBeg; + UnsatConflicts[1] = nConfEnd - nConfBeg; + UnsatConflicts[2] = Abc_MaxInt(p->nConflicts[1][2], nConfEnd - nConfBeg); + } + else + { + p->nConflicts[1][0] += nConfEnd == nConfBeg; + p->nConflicts[1][1] += nConfEnd - nConfBeg; + p->nConflicts[1][2] = Abc_MaxInt(p->nConflicts[1][2], nConfEnd - nConfBeg); + *pfEasy = nConfEnd == nConfBeg; + } + } + } + if ( status == GLUCOSE_UNSAT && iObj0 > 0 ) + { + Lits[0] = Abc_Var2Lit(iVar0, 0); + Lits[1] = Abc_Var2Lit(iVar1, !fPhase); + sat_solver_set_conflict_budget( p->pSat, nBTLimit ); + nConfBeg = sat_solver_conflictnum( p->pSat ); + status = sat_solver_solve( p->pSat, Lits, 2 ); + nConfEnd = sat_solver_conflictnum( p->pSat ); + assert( nConfEnd >= nConfBeg ); + if ( fVerbose ) + { + if ( status == GLUCOSE_SAT ) + { + p->nConflicts[0][0] += nConfEnd == nConfBeg; + p->nConflicts[0][1] += nConfEnd - nConfBeg; + p->nConflicts[0][2] = Abc_MaxInt(p->nConflicts[0][2], nConfEnd - nConfBeg); + *pfEasy = nConfEnd == nConfBeg; + } + else if ( status == GLUCOSE_UNSAT ) + { + UnsatConflicts[0] &= nConfEnd == nConfBeg; + UnsatConflicts[1] += nConfEnd - nConfBeg; + UnsatConflicts[2] = Abc_MaxInt(p->nConflicts[1][2], nConfEnd - nConfBeg); + + p->nConflicts[1][0] += UnsatConflicts[0]; + p->nConflicts[1][1] += UnsatConflicts[1]; + p->nConflicts[1][2] = Abc_MaxInt(p->nConflicts[1][2], UnsatConflicts[2]); + *pfEasy = UnsatConflicts[0]; + } + } + } + //if ( status == GLUCOSE_UNDEC ) + // printf( "* " ); + return status; +} +int Cec4_ManSweepNode( Cec4_Man_t * p, int iObj, int iRepr ) +{ + abctime clk = Abc_Clock(); + int i, IdAig, IdSat, status, fEasy, RetValue = 1; + Gia_Obj_t * pObj = Gia_ManObj( p->pAig, iObj ); + Gia_Obj_t * pRepr = Gia_ManObj( p->pAig, iRepr ); + int fCompl = Abc_LitIsCompl(pObj->Value) ^ Abc_LitIsCompl(pRepr->Value) ^ pObj->fPhase ^ pRepr->fPhase; + int fEffort = p->vCoDrivers ? Vec_BitEntry(p->vCoDrivers, iObj) || Vec_BitEntry(p->vCoDrivers, iRepr) : 0; + status = Cec4_ManSolveTwo( p, Abc_Lit2Var(pRepr->Value), Abc_Lit2Var(pObj->Value), fCompl, &fEasy, p->pPars->fVerbose, fEffort ); + if ( status == GLUCOSE_SAT ) + { + int iLit; + //int iPatsOld = p->pAig->iPatsPi; + //printf( "Disproved: %d == %d.\n", Abc_Lit2Var(pRepr->Value), Abc_Lit2Var(pObj->Value) ); + p->nSatSat++; + p->nPatterns++; + Vec_IntClear( p->vPat ); + if ( p->pPars->jType == 0 ) + { + Vec_IntForEachEntryDouble( &p->pNew->vCopiesTwo, IdAig, IdSat, i ) + Vec_IntPush( p->vPat, Abc_Var2Lit(IdAig, sat_solver_read_cex_varvalue(p->pSat, IdSat)) ); + } + else + { + int * pCex = sat_solver_read_cex( p->pSat ); + int * pMap = Vec_IntArray(&p->pNew->vVarMap); + for ( i = 0; i < pCex[0]; ) + Vec_IntPush( p->vPat, Abc_Lit2LitV(pMap, Abc_LitNot(pCex[++i])) ); + } + assert( p->pAig->iPatsPi >= 0 && p->pAig->iPatsPi < 64 * p->pAig->nSimWords - 1 ); + p->pAig->iPatsPi++; + Vec_IntForEachEntry( p->vPat, iLit, i ) + Cec4_ObjSimSetInputBit( p->pAig, Abc_Lit2Var(iLit), Abc_LitIsCompl(iLit) ); + if ( p->pAig->vPats ) + { + Vec_IntPush( p->pAig->vPats, Vec_IntSize(p->vPat)+2 ); + Vec_IntAppend( p->pAig->vPats, p->vPat ); + Vec_IntPush( p->pAig->vPats, -1 ); + } + //Cec4_ManPackAddPattern( p->pAig, p->vPat, 0 ); + //assert( iPatsOld + 1 == p->pAig->iPatsPi ); + if ( fEasy ) + p->timeSatSat0 += Abc_Clock() - clk; + else + p->timeSatSat += Abc_Clock() - clk; + RetValue = 0; + // this is not needed, but we keep it here anyway, because it takes very little time + //Cec4_ManVerify( p->pNew, Abc_Lit2Var(pRepr->Value), Abc_Lit2Var(pObj->Value), fCompl, p->pSat ); + // resimulated once in a while + if ( p->pAig->iPatsPi == 64 * p->pAig->nSimWords - 2 ) + { + abctime clk2 = Abc_Clock(); + Cec4_ManSimulate( p->pAig, p ); + //printf( "FasterSmall = %d. FasterBig = %d.\n", p->nFaster[0], p->nFaster[1] ); + p->nFaster[0] = p->nFaster[1] = 0; + //if ( p->nSatSat && p->nSatSat % 100 == 0 ) + Cec4_ManPrintStats( p->pAig, p->pPars, p, 0 ); + Vec_IntFill( p->vCexStamps, Gia_ManObjNum(p->pAig), 0 ); + p->pAig->iPatsPi = 0; + Vec_WrdFill( p->pAig->vSimsPi, Vec_WrdSize(p->pAig->vSimsPi), 0 ); + p->timeResimGlo += Abc_Clock() - clk2; + } + } + else if ( status == GLUCOSE_UNSAT ) + { + //printf( "Proved: %d == %d.\n", Abc_Lit2Var(pRepr->Value), Abc_Lit2Var(pObj->Value) ); + p->nSatUnsat++; + pObj->Value = Abc_LitNotCond( pRepr->Value, fCompl ); + Gia_ObjSetProved( p->pAig, iObj ); + if ( iRepr == 0 ) + p->iLastConst = iObj; + if ( fEasy ) + p->timeSatUnsat0 += Abc_Clock() - clk; + else + p->timeSatUnsat += Abc_Clock() - clk; + RetValue = 1; + } + else + { + p->nSatUndec++; + assert( status == GLUCOSE_UNDEC ); + Gia_ObjSetFailed( p->pAig, iObj ); + Vec_BitWriteEntry( p->vFails, iObj, 1 ); + //if ( iRepr ) + //Vec_BitWriteEntry( p->vFails, iRepr, 1 ); + p->timeSatUndec += Abc_Clock() - clk; + RetValue = 2; + } + return RetValue; +} +Gia_Obj_t * Cec4_ManFindRepr( Gia_Man_t * p, Cec4_Man_t * pMan, int iObj ) +{ + abctime clk = Abc_Clock(); + int iMem, iRepr; + assert( Gia_ObjHasRepr(p, iObj) ); + assert( !Gia_ObjProved(p, iObj) ); + iRepr = Gia_ObjRepr(p, iObj); + assert( iRepr != iObj ); + assert( !Gia_ObjProved(p, iRepr) ); + Cec4_ManSimulate_rec( p, pMan, iObj ); + Cec4_ManSimulate_rec( p, pMan, iRepr ); + if ( Cec4_ObjSimEqual(p, iObj, iRepr) ) + { + pMan->timeResimLoc += Abc_Clock() - clk; + return Gia_ManObj(p, iRepr); + } + Gia_ClassForEachObj1( p, iRepr, iMem ) + { + if ( iObj == iMem ) + break; + if ( Gia_ObjProved(p, iMem) || Gia_ObjFailed(p, iMem) ) + continue; + Cec4_ManSimulate_rec( p, pMan, iMem ); + if ( Cec4_ObjSimEqual(p, iObj, iMem) ) + { + pMan->nFaster[0]++; + pMan->timeResimLoc += Abc_Clock() - clk; + return Gia_ManObj(p, iMem); + } + } + pMan->nFaster[1]++; + pMan->timeResimLoc += Abc_Clock() - clk; + return NULL; +} +int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** ppNew, int fSimOnly ) +{ + Cec4_Man_t * pMan = Cec4_ManCreate( p, pPars ); + Gia_Obj_t * pObj, * pRepr; + int i, fSimulate = 1; + if ( pPars->fVerbose ) + printf( "Solver type = %d. Simulate %d words in %d rounds. SAT with %d confs. Recycle after %d SAT calls.\n", + pPars->jType, pPars->nWords, pPars->nRounds, pPars->nBTLimit, pPars->nCallsRecycle ); + + // this is currently needed to have a correct mapping + Gia_ManForEachCi( p, pObj, i ) + assert( Gia_ObjId(p, pObj) == i+1 ); + + // check if any output trivially fails under all-0 pattern + Gia_ManRandom( 1 ); + Gia_ManSetPhase( p ); + if ( pPars->nLevelMax ) + Gia_ManLevelNum(p); + //Gia_ManStaticFanoutStart( p ); + if ( pPars->fCheckMiter ) + { + Gia_ManForEachCo( p, pObj, i ) + if ( pObj->fPhase ) + { + p->pCexSeq = Cec4_ManDeriveCex( p, i, -1 ); + goto finalize; + } + } + + // simulate one round and create classes + Cec4_ManSimAlloc( p, pPars->nWords ); + Cec4_ManSimulateCis( p ); + Cec4_ManSimulate( p, pMan ); + if ( pPars->fCheckMiter && !Cec4_ManSimulateCos(p) ) // cex detected + goto finalize; + if ( pPars->fVerbose ) + Cec4_ManPrintStats( p, pPars, pMan, 1 ); + + // perform simulation + for ( i = 0; i < pPars->nRounds; i++ ) + { + Cec4_ManSimulateCis( p ); + Cec4_ManSimulate( p, pMan ); + if ( pPars->fCheckMiter && !Cec4_ManSimulateCos(p) ) // cex detected + goto finalize; + if ( i && i % (pPars->nRounds / 5) == 0 && pPars->fVerbose ) + Cec4_ManPrintStats( p, pPars, pMan, 1 ); + } + if ( fSimOnly ) + goto finalize; + + // perform additional simulation + Cec4_ManCandIterStart( pMan ); + for ( i = 0; fSimulate && i < pPars->nGenIters; i++ ) + { + Cec4_ManSimulateCis( p ); + fSimulate = Cec4_ManGeneratePatterns( pMan ); + Cec4_ManSimulate( p, pMan ); + if ( pPars->fCheckMiter && !Cec4_ManSimulateCos(p) ) // cex detected + goto finalize; + if ( i && i % 5 == 0 && pPars->fVerbose ) + Cec4_ManPrintStats( p, pPars, pMan, 1 ); + } + if ( i && i % 5 && pPars->fVerbose ) + Cec4_ManPrintStats( p, pPars, pMan, 1 ); + + p->iPatsPi = 0; + Vec_WrdFill( p->vSimsPi, Vec_WrdSize(p->vSimsPi), 0 ); + pMan->nSatSat = 0; + pMan->pNew = Cec4_ManStartNew( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + Gia_Obj_t * pObjNew; + pMan->nAndNodes++; + if ( Gia_ObjIsXor(pObj) ) + pObj->Value = Gia_ManHashXorReal( pMan->pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + pObj->Value = Gia_ManHashAnd( pMan->pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( pPars->nLevelMax && Gia_ObjLevel(p, pObj) > pPars->nLevelMax ) + continue; + pObjNew = Gia_ManObj( pMan->pNew, Abc_Lit2Var(pObj->Value) ); + if ( Gia_ObjIsAnd(pObjNew) ) + if ( Vec_BitEntry(pMan->vFails, Gia_ObjFaninId0(pObjNew, Abc_Lit2Var(pObj->Value))) || + Vec_BitEntry(pMan->vFails, Gia_ObjFaninId1(pObjNew, Abc_Lit2Var(pObj->Value))) ) + Vec_BitWriteEntry( pMan->vFails, Abc_Lit2Var(pObjNew->Value), 1 ); + //if ( Gia_ObjIsAnd(pObjNew) ) + // Gia_ObjSetAndLevel( pMan->pNew, pObjNew ); + // select representative based on candidate equivalence classes + pRepr = Gia_ObjReprObj( p, i ); + if ( pRepr == NULL ) + continue; + if ( 1 ) // select representative based on recent counter-examples + { + pRepr = Cec4_ManFindRepr( p, pMan, i ); + if ( pRepr == NULL ) + continue; + } + if ( Abc_Lit2Var(pObj->Value) == Abc_Lit2Var(pRepr->Value) ) + { + assert( (pObj->Value ^ pRepr->Value) == (pObj->fPhase ^ pRepr->fPhase) ); + Gia_ObjSetProved( p, i ); + if ( Gia_ObjId(p, pRepr) == 0 ) + pMan->iLastConst = i; + continue; + } + if ( Cec4_ManSweepNode(pMan, i, Gia_ObjId(p, pRepr)) && Gia_ObjProved(p, i) ) + pObj->Value = Abc_LitNotCond( pRepr->Value, pObj->fPhase ^ pRepr->fPhase ); + } + if ( p->iPatsPi > 0 ) + { + abctime clk2 = Abc_Clock(); + Cec4_ManSimulate( p, pMan ); + p->iPatsPi = 0; + Vec_IntFill( pMan->vCexStamps, Gia_ManObjNum(p), 0 ); + pMan->timeResimGlo += Abc_Clock() - clk2; + } + if ( pPars->fVerbose ) + Cec4_ManPrintStats( p, pPars, pMan, 0 ); + if ( ppNew ) + { + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pMan->pNew, Gia_ObjFanin0Copy(pObj) ); + *ppNew = Gia_ManCleanup( pMan->pNew ); + } +finalize: + if ( pPars->fVerbose ) + printf( "SAT calls = %d: P = %d (0=%d a=%.2f m=%d) D = %d (0=%d a=%.2f m=%d) F = %d Sim = %d Recyc = %d Xor = %.2f %%\n", + pMan->nSatUnsat + pMan->nSatSat + pMan->nSatUndec, + pMan->nSatUnsat, pMan->nConflicts[1][0], (float)pMan->nConflicts[1][1]/Abc_MaxInt(1, pMan->nSatUnsat-pMan->nConflicts[1][0]), pMan->nConflicts[1][2], + pMan->nSatSat, pMan->nConflicts[0][0], (float)pMan->nConflicts[0][1]/Abc_MaxInt(1, pMan->nSatSat -pMan->nConflicts[0][0]), pMan->nConflicts[0][2], + pMan->nSatUndec, + pMan->nSimulates, pMan->nRecycles, 100.0*pMan->nGates[1]/Abc_MaxInt(1, pMan->nGates[0]+pMan->nGates[1]) ); + Cec4_ManDestroy( pMan ); + //Gia_ManStaticFanoutStop( p ); + //Gia_ManEquivPrintClasses( p, 1, 0 ); + return p->pCexSeq ? 0 : 1; +} +Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ) +{ + Gia_Man_t * pNew = NULL; + Cec4_ManPerformSweeping( p, pPars, &pNew, 0 ); + return pNew; +} +void Cec4_ManSimulateTest2( Gia_Man_t * p, int nConfs, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Cec_ParFra_t ParsFra, * pPars = &ParsFra; + Cec4_ManSetParams( pPars ); + Cec4_ManPerformSweeping( p, pPars, NULL, 0 ); + pPars->fVerbose = fVerbose; + pPars->nBTLimit = nConfs; + if ( fVerbose ) + Abc_PrintTime( 1, "New choice computation time", Abc_Clock() - clk ); +} +Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ) +{ + Gia_Man_t * pNew = NULL; + Cec_ParFra_t ParsFra, * pPars = &ParsFra; + Cec4_ManSetParams( pPars ); + pPars->fVerbose = fVerbose; + pPars->nBTLimit = nBTLimit; + Cec4_ManPerformSweeping( p, pPars, &pNew, 0 ); + return pNew; +} +Gia_Man_t * Cec4_ManSimulateTest4( Gia_Man_t * p, int nBTLimit, int nBTLimitPo, int fVerbose ) +{ + Gia_Man_t * pNew = NULL; + Cec_ParFra_t ParsFra, * pPars = &ParsFra; + Cec4_ManSetParams( pPars ); + pPars->fVerbose = fVerbose; + pPars->nBTLimit = nBTLimit; + pPars->nBTLimitPo = nBTLimitPo; + Cec4_ManPerformSweeping( p, pPars, &pNew, 0 ); + return pNew; +} +int Cec4_ManSimulateOnlyTest( Gia_Man_t * p, int fVerbose ) +{ + Cec_ParFra_t ParsFra, * pPars = &ParsFra; + Cec4_ManSetParams( pPars ); + pPars->fVerbose = fVerbose; + return Cec4_ManPerformSweeping( p, pPars, NULL, 1 ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/cecSim.c b/src/proof/cec/cecSim.c index 92f8fc2e..48a789f3 100644 --- a/src/proof/cec/cecSim.c +++ b/src/proof/cec/cecSim.c @@ -6,7 +6,7 @@ PackageName [Combinational equivalence checking.] - Synopsis [Simulation manager.] + Synopsis [Simulation.] Author [Alan Mishchenko] @@ -19,14 +19,40 @@ ***********************************************************************/ #include "cecInt.h" +#include "aig/gia/giaAig.h" +#include "misc/util/utilTruth.h" -ABC_NAMESPACE_IMPL_START +ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +#define SIM_RANDS 113 + +typedef struct Cec_ManS_t_ Cec_ManS_t; +struct Cec_ManS_t_ +{ + int nWords; + int nLevelMax; + int nLevelMin; + int iRand; + Gia_Man_t * pAig; + Vec_Int_t * vInputs; + Vec_Wec_t * vLevels; + Vec_Wrd_t * vSims; + word * pTemp[4]; + word Rands[SIM_RANDS]; + int nSkipped; + int nVisited; + int nCexes; + abctime clkSat; + abctime clkUnsat; +}; + +static inline word * Cec_ManSSim( Cec_ManS_t * p, int iNode, int Value ) { return Vec_WrdEntryP(p->vSims, p->nWords*(iNode+iNode+Value)); } + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -36,12 +62,340 @@ ABC_NAMESPACE_IMPL_START Synopsis [] Description [] - + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cec_ManS_t * Cec_ManSStart( Gia_Man_t * pAig, int nWords ) +{ + Cec_ManS_t * p; int i; + p = ABC_ALLOC( Cec_ManS_t, 1 ); + memset( p, 0, sizeof(Cec_ManS_t) ); + p->nWords = nWords; + p->pAig = pAig; + p->vInputs = Vec_IntAlloc( 100 ); + p->vLevels = Vec_WecStart( Gia_ManLevelNum(pAig) + 1 ); + p->vSims = Vec_WrdStart( Gia_ManObjNum(pAig) * nWords * 2 ); + p->pTemp[0] = ABC_ALLOC( word, 4*nWords ); + for ( i = 1; i < 4; i++ ) + p->pTemp[i] = p->pTemp[i-1] + nWords; + for ( i = 0; i < SIM_RANDS; i++ ) + p->Rands[i] = Gia_ManRandomW(0); + return p; +} +void Cec_ManSStop( Cec_ManS_t * p ) +{ + Vec_IntFree( p->vInputs ); + Vec_WecFree( p->vLevels ); + Vec_WrdFree( p->vSims ); + ABC_FREE( p->pTemp[0] ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Verify counter-example.] + + Description [] + SideEffects [] SeeAlso [] ***********************************************************************/ +int Cec_ManSVerify_rec( Gia_Man_t * p, int iObj ) +{ + int Value0, Value1; + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + if ( iObj == 0 ) return 0; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return pObj->fMark1; + Gia_ObjSetTravIdCurrentId(p, iObj); + if ( Gia_ObjIsCi(pObj) ) + return pObj->fMark1; + assert( Gia_ObjIsAnd(pObj) ); + Value0 = Cec_ManSVerify_rec( p, Gia_ObjFaninId0(pObj, iObj) ) ^ Gia_ObjFaninC0(pObj); + Value1 = Cec_ManSVerify_rec( p, Gia_ObjFaninId1(pObj, iObj) ) ^ Gia_ObjFaninC1(pObj); + return pObj->fMark1 = Gia_ObjIsXor(pObj) ? Value0 ^ Value1 : Value0 & Value1; +} +void Cec_ManSVerifyTwo( Gia_Man_t * p, int iObj0, int iObj1 ) +{ + int Value0, Value1; + Gia_ManIncrementTravId( p ); + Value0 = Cec_ManSVerify_rec( p, iObj0 ); + Value1 = Cec_ManSVerify_rec( p, iObj1 ); + if ( (Value0 ^ Value1) == Gia_ObjPhaseDiff(p, iObj0, iObj1) ) + printf( "CEX verification FAILED for obj %d and obj %d.\n", iObj0, iObj1 ); +// else +// printf( "CEX verification succeeded for obj %d and obj %d.\n", iObj0, iObj1 );; +} +void Cec_ManSVerify( Cec_ManS_t * p, int iObj0, int iObj1 ) +{ + int fDoVerify = 0; + int w, i, iObj, nCares; + word * pCare = Vec_WrdArray(p->vSims); + if ( Vec_IntSize(p->vInputs) == 0 ) + { + printf( "No primary inputs.\n" ); + return; + } + Vec_IntForEachEntry( p->vInputs, iObj, i ) + { + word * pSim_0 = Cec_ManSSim( p, iObj, 0 ); + word * pSim_1 = Cec_ManSSim( p, iObj, 1 ); + if ( p->nWords == 1 ) + pCare[0] |= pSim_0[0] & pSim_1[0]; + else + Abc_TtOrAnd( pCare, pSim_0, pSim_1, p->nWords ); + } + nCares = Abc_TtCountOnesVec( pCare, p->nWords ); + if ( nCares == 64*p->nWords ) + { + printf( "No CEXes.\n" ); + return; + } + assert( Vec_IntSize(p->vInputs) > 0 ); + for ( w = 0; w < 64*p->nWords; w++ ) + { + if ( Abc_TtGetBit(pCare, w) ) + continue; + if ( !fDoVerify ) + continue; + Vec_IntForEachEntry( p->vInputs, iObj, i ) + Gia_ManObj(p->pAig, iObj)->fMark1 = Abc_TtGetBit( Cec_ManSSim(p, iObj, 1), w ); + Cec_ManSVerifyTwo( p->pAig, iObj0, iObj1 ); + } + printf( "Considered %d CEXes of nodes %d and %d.\n", 64*p->nWords - nCares, iObj0, iObj1 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSRunImply( Cec_ManS_t * p, int iNode ) +{ + Gia_Obj_t * pNode = Gia_ManObj( p->pAig, iNode ); + if ( Gia_ObjIsAnd(pNode) ) + { + int iFan0 = Gia_ObjFaninId0( pNode, iNode ); + int iFan1 = Gia_ObjFaninId1( pNode, iNode ); + word * pSim__ = Cec_ManSSim( p, 0, 0 ); + word * pSim_0 = Cec_ManSSim( p, iNode, 0 ); + word * pSim_1 = Cec_ManSSim( p, iNode, 1 ); + word * pSim00 = Cec_ManSSim( p, iFan0, Gia_ObjFaninC0(pNode) ); + word * pSim01 = Cec_ManSSim( p, iFan0, !Gia_ObjFaninC0(pNode) ); + word * pSim10 = Cec_ManSSim( p, iFan1, Gia_ObjFaninC1(pNode) ); + word * pSim11 = Cec_ManSSim( p, iFan1, !Gia_ObjFaninC1(pNode) ); + if ( p->nWords == 1 ) + { + pSim_0[0] |= pSim00[0] | pSim10[0]; + pSim_1[0] |= pSim01[0] & pSim11[0]; + pSim__[0] |= pSim_0[0] & pSim_1[0]; + pSim_0[0] &= ~pSim__[0]; + pSim_1[0] &= ~pSim__[0]; + } + else + { + Abc_TtOr( pSim_0, pSim_0, pSim00, p->nWords ); + Abc_TtOr( pSim_0, pSim_0, pSim10, p->nWords ); + Abc_TtOrAnd( pSim_1, pSim01, pSim11, p->nWords ); + Abc_TtOrAnd( pSim__, pSim_0, pSim_1, p->nWords ); + Abc_TtAndSharp( pSim_0, pSim_0, pSim__, p->nWords, 1 ); + Abc_TtAndSharp( pSim_1, pSim_1, pSim__, p->nWords, 1 ); + } + } +} +int Cec_ManSRunPropagate( Cec_ManS_t * p, int iNode ) +{ + Gia_Obj_t * pNode = Gia_ManObj( p->pAig, iNode ); + int iFan0 = Gia_ObjFaninId0( pNode, iNode ); + int iFan1 = Gia_ObjFaninId1( pNode, iNode ); + word * pSim_0 = Cec_ManSSim( p, iNode, 0 ); + word * pSim_1 = Cec_ManSSim( p, iNode, 1 ); + if ( Abc_TtIsConst0(pSim_0, p->nWords) && Abc_TtIsConst0(pSim_1, p->nWords) ) + { + p->nSkipped++; + return 0; + } + p->nVisited++; + //Cec_ManSRunImply( p, iFan0 ); + //Cec_ManSRunImply( p, iFan1 ); + { + word * pSim__ = Cec_ManSSim( p, 0, 0 ); + word * pSim00 = Cec_ManSSim( p, iFan0, Gia_ObjFaninC0(pNode) ); + word * pSim01 = Cec_ManSSim( p, iFan0, !Gia_ObjFaninC0(pNode) ); + word * pSim10 = Cec_ManSSim( p, iFan1, Gia_ObjFaninC1(pNode) ); + word * pSim11 = Cec_ManSSim( p, iFan1, !Gia_ObjFaninC1(pNode) ); + p->iRand = p->iRand == SIM_RANDS-1 ? 0 : p->iRand + 1; + if ( p->nWords == 1 ) + { + pSim01[0] |= pSim_1[0]; + pSim11[0] |= pSim_1[0]; + + pSim00[0] |= pSim_0[0] & (pSim11[0] | ~p->Rands[p->iRand]); + pSim10[0] |= pSim_0[0] & (pSim01[0] | p->Rands[p->iRand]); + + pSim__[0] |= pSim00[0] & pSim01[0]; + pSim__[0] |= pSim10[0] & pSim11[0]; + + pSim00[0] &= ~pSim__[0]; + pSim01[0] &= ~pSim__[0]; + pSim10[0] &= ~pSim__[0]; + pSim11[0] &= ~pSim__[0]; + } + else + { + int w; + for ( w = 0; w < p->nWords; w++ ) + p->pTemp[0][w] = ~p->Rands[(p->iRand + w) % SIM_RANDS]; + + Abc_TtOr( pSim01, pSim01, pSim_1, p->nWords ); + Abc_TtOr( pSim11, pSim11, pSim_1, p->nWords ); + + Abc_TtOr( p->pTemp[1], pSim11, p->pTemp[0], p->nWords ); + Abc_TtOrAnd( pSim00, pSim_0, p->pTemp[1], p->nWords ); + + Abc_TtNot( p->pTemp[0], p->nWords ); + Abc_TtOr( p->pTemp[1], pSim01, p->pTemp[0], p->nWords ); + Abc_TtOrAnd( pSim10, pSim_0, p->pTemp[1], p->nWords ); + + Abc_TtOrAnd( pSim__, pSim00, pSim01, p->nWords ); + Abc_TtOrAnd( pSim__, pSim10, pSim11, p->nWords ); + + Abc_TtAndSharp( pSim00, pSim00, pSim__, p->nWords, 1 ); + Abc_TtAndSharp( pSim01, pSim01, pSim__, p->nWords, 1 ); + Abc_TtAndSharp( pSim10, pSim10, pSim__, p->nWords, 1 ); + Abc_TtAndSharp( pSim11, pSim11, pSim__, p->nWords, 1 ); + } + } + return 1; +} +void Cec_ManSInsert( Cec_ManS_t * p, int iNode ) +{ + Gia_Obj_t * pNode; int Level; + assert( iNode > 0 ); + if ( Gia_ObjIsTravIdCurrentId(p->pAig, iNode) ) + return; + Gia_ObjSetTravIdCurrentId(p->pAig, iNode); + pNode = Gia_ManObj( p->pAig, iNode ); + if ( Gia_ObjIsCi(pNode) ) + { + Vec_IntPush( p->vInputs, iNode ); + return; + } + assert( Gia_ObjIsAnd(pNode) ); + Level = Gia_ObjLevelId( p->pAig, iNode ); + assert( Level > 0 ); + Vec_WecPush( p->vLevels, Level, iNode ); + p->nLevelMax = Abc_MaxInt( p->nLevelMax, Level ); + p->nLevelMin = Abc_MinInt( p->nLevelMin, Level ); + assert( p->nLevelMin <= p->nLevelMax ); +} +int Cec_ManSRunSimInt( Cec_ManS_t * p ) +{ + Vec_Int_t * vLevel; + int i, k, iNode, fSolved = 0; + Vec_WecForEachLevelReverseStartStop( p->vLevels, vLevel, i, p->nLevelMax+1, p->nLevelMin ) + { + Vec_IntForEachEntry( vLevel, iNode, k ) + { + Gia_Obj_t * pNode = Gia_ManObj( p->pAig, iNode ); + if ( !fSolved && Cec_ManSRunPropagate( p, iNode ) ) + { + Cec_ManSInsert( p, Gia_ObjFaninId0(pNode, iNode) ); + Cec_ManSInsert( p, Gia_ObjFaninId1(pNode, iNode) ); + if ( Abc_TtIsConst1(Vec_WrdArray(p->vSims), p->nWords) ) + fSolved = 1; + } + Abc_TtClear( Cec_ManSSim(p, iNode, 0), 2*p->nWords ); + } + Vec_IntClear( vLevel ); + } + //Vec_WecForEachLevel( p->vLevels, vLevel, i ) + // assert( Vec_IntSize(vLevel) == 0 ); + return fSolved; +} +int Cec_ManSRunSim( Cec_ManS_t * p, int iNode0, int iNode1 ) +{ + abctime clk = Abc_Clock(); + //Vec_Int_t * vLevel; + //int pNodes[2] = { iNode0, iNode1 }; + int i, iNode, Status, fDiff = Gia_ObjPhaseDiff( p->pAig, iNode0, iNode1 ); + word * pSim00 = Cec_ManSSim( p, iNode0, 0 ); + word * pSim01 = Cec_ManSSim( p, iNode0, 1 ); + word * pSim10 = Cec_ManSSim( p, iNode1, fDiff ); + word * pSim11 = Cec_ManSSim( p, iNode1, !fDiff ); + Abc_TtClear( Vec_WrdArray(p->vSims), p->nWords ); + //for ( i = 0; i < Vec_WrdSize(p->vSims); i++ ) + // assert( p->vSims->pArray[i] == 0 ); + assert( Vec_IntSize(p->vInputs) == 0 ); + if ( iNode0 == 0 ) + Abc_TtFill( pSim11, p->nWords ); + else + { + if ( p->nWords == 1 ) + { + pSim00[0] = (word)0xFFFFFFFF; + pSim11[0] = (word)0xFFFFFFFF; + pSim01[0] = pSim00[0] << 32; + pSim10[0] = pSim11[0] << 32; + } + else + { + assert( p->nWords % 2 == 0 ); + Abc_TtFill( pSim00, p->nWords/2 ); + Abc_TtFill( pSim11, p->nWords/2 ); + Abc_TtFill( pSim01 + p->nWords/2, p->nWords/2 ); + Abc_TtFill( pSim10 + p->nWords/2, p->nWords/2 ); + } + } + p->nLevelMin = ABC_INFINITY; + p->nLevelMax = 0; + Gia_ManIncrementTravId( p->pAig ); + if ( iNode0 ) + Cec_ManSInsert( p, iNode0 ); + Cec_ManSInsert( p, iNode1 ); + p->nSkipped = p->nVisited = 0; + Status = Cec_ManSRunSimInt( p ); + if ( Status == 0 ) + p->clkSat += Abc_Clock() - clk; + else + p->clkUnsat += Abc_Clock() - clk; +// if ( Status == 0 ) +// printf( "Solving %6d and %6d. Skipped = %6d. Visited = %6d. Cone = %6d. Min = %3d. Max = %3d.\n", +// iNode0, iNode1, p->nSkipped, p->nVisited, Gia_ManConeSize(p->pAig, pNodes, 2), p->nLevelMin, p->nLevelMax ); + if ( Status == 0 ) + Cec_ManSVerify( p, iNode0, iNode1 ), p->nCexes++; + Vec_IntForEachEntry( p->vInputs, iNode, i ) + Abc_TtClear( Cec_ManSSim(p, iNode, 0), 2*p->nWords ); + Vec_IntClear( p->vInputs ); + return Status; +} +void Cec_ManSRunTest( Gia_Man_t * pAig ) +{ + abctime clk = Abc_Clock(); + Cec_ManS_t * p; + int i, k, nWords = 1; + Gia_ManRandomW( 1 ); + p = Cec_ManSStart( pAig, nWords ); + Gia_ManForEachClass0( p->pAig, i ) + Gia_ClassForEachObj1( p->pAig, i, k ) + Cec_ManSRunSim( p, i, k ); + printf( "Detected %d CEXes. ", p->nCexes ); + Abc_PrintTime( 1, "Time ", Abc_Clock() - clk ); + Abc_PrintTime( 1, "Sat ", p->clkSat ); + Abc_PrintTime( 1, "Unsat", p->clkUnsat ); + Cec_ManSStop( p ); +} //////////////////////////////////////////////////////////////////////// diff --git a/src/proof/cec/cecSolve.c b/src/proof/cec/cecSolve.c index af6a4fdb..f8342859 100644 --- a/src/proof/cec/cecSolve.c +++ b/src/proof/cec/cecSolve.c @@ -696,7 +696,7 @@ Abc_Cex_t * Cex_ManGenCex( Cec_ManSat_t * p, int iOut ) } return pCex; } -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 ) +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, int f0Proved ) { Bar_Progress_t * pProgress = NULL; Cec_ManSat_t * p; @@ -747,6 +747,9 @@ clk2 = Abc_Clock(); if ( pPars->fSaveCexes && status != -1 ) Vec_PtrWriteEntry( pAig->vSeqModelVec, i, status ? (Abc_Cex_t *)(ABC_PTRINT_T)1 : Cex_ManGenCex(p, i) ); + if ( f0Proved && status == 1 ) + Gia_ManPatchCoDriver( pAig, i, 0 ); + /* if ( status == -1 ) { @@ -807,7 +810,7 @@ void Cec_ManSatSolveCSat( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * { Vec_Str_t * vStatus; Vec_Int_t * vPat = Vec_IntAlloc( 1000 ); - Vec_Int_t * vCexStore = Cbs_ManSolveMiterNc( pAig, pPars->nBTLimit, &vStatus, 0 ); + Vec_Int_t * vCexStore = Cbs_ManSolveMiterNc( pAig, pPars->nBTLimit, &vStatus, 0, 0 ); Gia_Obj_t * pObj; int i, status, iStart = 0; assert( Vec_StrSize(vStatus) == Gia_ManCoNum(pAig) ); diff --git a/src/proof/cec/cecSolveG.c b/src/proof/cec/cecSolveG.c new file mode 100644 index 00000000..0bb68a7f --- /dev/null +++ b/src/proof/cec/cecSolveG.c @@ -0,0 +1,641 @@ +/**CFile**************************************************************** + + FileName [cecSolve.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Performs one round of SAT solving.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecSolve.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + + +#define USE_GLUCOSE2 + +#ifdef USE_GLUCOSE2 + +#include "sat/glucose2/AbcGlucose2.h" + +#define sat_solver bmcg2_sat_solver +#define sat_solver_start bmcg2_sat_solver_start +#define sat_solver_stop bmcg2_sat_solver_stop +#define sat_solver_addclause bmcg2_sat_solver_addclause +#define sat_solver_add_and bmcg2_sat_solver_add_and +#define sat_solver_add_xor bmcg2_sat_solver_add_xor +#define sat_solver_addvar bmcg2_sat_solver_addvar +#define sat_solver_reset bmcg2_sat_solver_reset +#define sat_solver_set_conflict_budget bmcg2_sat_solver_set_conflict_budget +#define sat_solver_conflictnum bmcg2_sat_solver_conflictnum +#define sat_solver_solve bmcg2_sat_solver_solve +#define sat_solver_read_cex_varvalue bmcg2_sat_solver_read_cex_varvalue +#define sat_solver_read_cex bmcg2_sat_solver_read_cex +#define sat_solver_jftr bmcg2_sat_solver_jftr +#define sat_solver_set_jftr bmcg2_sat_solver_set_jftr +#define sat_solver_set_var_fanin_lit bmcg2_sat_solver_set_var_fanin_lit +#define sat_solver_start_new_round bmcg2_sat_solver_start_new_round +#define sat_solver_mark_cone bmcg2_sat_solver_mark_cone +//#define sat_solver_set_nvars bmcg2_sat_solver_set_nvars +#define sat_solver_varnum bmcg2_sat_solver_varnum +#else + +#include "sat/glucose/AbcGlucose.h" + +#define sat_solver bmcg_sat_solver +#define sat_solver_start bmcg_sat_solver_start +#define sat_solver_stop bmcg_sat_solver_stop +#define sat_solver_addclause bmcg_sat_solver_addclause +#define sat_solver_add_and bmcg_sat_solver_add_and +#define sat_solver_add_xor bmcg_sat_solver_add_xor +#define sat_solver_addvar bmcg_sat_solver_addvar +#define sat_solver_reset bmcg_sat_solver_reset +#define sat_solver_set_conflict_budget bmcg_sat_solver_set_conflict_budget +#define sat_solver_conflictnum bmcg_sat_solver_conflictnum +#define sat_solver_solve bmcg_sat_solver_solve +#define sat_solver_read_cex_varvalue bmcg_sat_solver_read_cex_varvalue +#define sat_solver_read_cex bmcg_sat_solver_read_cex +#define sat_solver_jftr bmcg_sat_solver_jftr +#define sat_solver_set_jftr bmcg_sat_solver_set_jftr +#define sat_solver_set_var_fanin_lit bmcg_sat_solver_set_var_fanin_lit +#define sat_solver_start_new_round bmcg_sat_solver_start_new_round +#define sat_solver_mark_cone bmcg_sat_solver_mark_cone +#define sat_solver_set_nvars bmcg_sat_solver_set_nvars + +#endif + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int CecG_ObjSatNum( Cec_ManSat_t * p, Gia_Obj_t * pObj ) { return p->pSatVars[Gia_ObjId(p->pAig,pObj)]; } +static inline void CecG_ObjSetSatNum( Cec_ManSat_t * p, Gia_Obj_t * pObj, int Num ) { p->pSatVars[Gia_ObjId(p->pAig,pObj)] = Num; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns value of the SAT variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int CecG_ObjSatVarValue( Cec_ManSat_t * p, Gia_Obj_t * pObj ) +{ + return sat_solver_read_cex_varvalue( p->pSat, CecG_ObjSatNum(p, pObj) ); +} + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CecG_AddClausesMux( Cec_ManSat_t * p, Gia_Obj_t * pNode ) +{ + Gia_Obj_t * pNodeI, * pNodeT, * pNodeE; + int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; + + assert( !Gia_IsComplement( pNode ) ); + assert( Gia_ObjIsMuxType( pNode ) ); + // get nodes (I = if, T = then, E = else) + pNodeI = Gia_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); + // get the variable numbers + VarF = CecG_ObjSatNum(p,pNode); + VarI = CecG_ObjSatNum(p,pNodeI); + VarT = CecG_ObjSatNum(p,Gia_Regular(pNodeT)); + VarE = CecG_ObjSatNum(p,Gia_Regular(pNodeE)); + // get the complementation flags + fCompT = Gia_IsComplement(pNodeT); + fCompE = Gia_IsComplement(pNodeE); + + // f = ITE(i, t, e) + + // i' + t' + f + // i' + t + f' + // i + e' + f + // i + e + f' + + // create four clauses + pLits[0] = toLitCond(VarI, 1); + pLits[1] = toLitCond(VarT, 1^fCompT); + pLits[2] = toLitCond(VarF, 0); + if ( p->pPars->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Gia_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarI, 1); + pLits[1] = toLitCond(VarT, 0^fCompT); + pLits[2] = toLitCond(VarF, 1); + if ( p->pPars->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Gia_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarI, 0); + pLits[1] = toLitCond(VarE, 1^fCompE); + pLits[2] = toLitCond(VarF, 0); + if ( p->pPars->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarI, 0); + pLits[1] = toLitCond(VarE, 0^fCompE); + pLits[2] = toLitCond(VarF, 1); + if ( p->pPars->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, 3 ); + assert( RetValue ); + + // two additional clauses + // t' & e' -> f' + // t & e -> f + + // t + e + f' + // t' + e' + f + + if ( VarT == VarE ) + { +// assert( fCompT == !fCompE ); + return; + } + + pLits[0] = toLitCond(VarT, 0^fCompT); + pLits[1] = toLitCond(VarE, 0^fCompE); + pLits[2] = toLitCond(VarF, 1); + if ( p->pPars->fPolarFlip ) + { + if ( Gia_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarT, 1^fCompT); + pLits[1] = toLitCond(VarE, 1^fCompE); + pLits[2] = toLitCond(VarF, 0); + if ( p->pPars->fPolarFlip ) + { + if ( Gia_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, 3 ); + assert( RetValue ); +} + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CecG_AddClausesSuper( Cec_ManSat_t * p, Gia_Obj_t * pNode, Vec_Ptr_t * vSuper ) +{ + Gia_Obj_t * pFanin; + int * pLits, nLits, RetValue, i; + assert( !Gia_IsComplement(pNode) ); + assert( Gia_ObjIsAnd( pNode ) ); + // create storage for literals + nLits = Vec_PtrSize(vSuper) + 1; + pLits = ABC_ALLOC( int, nLits ); + // suppose AND-gate is A & B = C + // add !A => !C or A + !C + Vec_PtrForEachEntry( Gia_Obj_t *, vSuper, pFanin, i ) + { + pLits[0] = toLitCond(CecG_ObjSatNum(p,Gia_Regular(pFanin)), Gia_IsComplement(pFanin)); + pLits[1] = toLitCond(CecG_ObjSatNum(p,pNode), 1); + if ( p->pPars->fPolarFlip ) + { + if ( Gia_Regular(pFanin)->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( pNode->fPhase ) pLits[1] = lit_neg( pLits[1] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, 2 ); + assert( RetValue ); + } + // add A & B => C or !A + !B + C + Vec_PtrForEachEntry( Gia_Obj_t *, vSuper, pFanin, i ) + { + pLits[i] = toLitCond(CecG_ObjSatNum(p,Gia_Regular(pFanin)), !Gia_IsComplement(pFanin)); + if ( p->pPars->fPolarFlip ) + { + if ( Gia_Regular(pFanin)->fPhase ) pLits[i] = lit_neg( pLits[i] ); + } + } + pLits[nLits-1] = toLitCond(CecG_ObjSatNum(p,pNode), 0); + if ( p->pPars->fPolarFlip ) + { + if ( pNode->fPhase ) pLits[nLits-1] = lit_neg( pLits[nLits-1] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, nLits ); + assert( RetValue ); + ABC_FREE( pLits ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CecG_CollectSuper_rec( Gia_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes, int fUseSuper ) +{ + // if the new node is complemented or a PI, another gate begins + if ( Gia_IsComplement(pObj) || Gia_ObjIsCi(pObj) || + (!fFirst && Gia_ObjValue(pObj) > 1) || + (fUseMuxes && Gia_ObjIsMuxType(pObj)) ) + { + Vec_PtrPushUnique( vSuper, pObj ); + return; + } + if( !fUseSuper ){ + Vec_PtrPushUnique( vSuper, Gia_ObjChild0(pObj) ); + Vec_PtrPushUnique( vSuper, Gia_ObjChild1(pObj) ); + return ; + } + // go through the branches + CecG_CollectSuper_rec( Gia_ObjChild0(pObj), vSuper, 0, fUseMuxes, fUseSuper ); + CecG_CollectSuper_rec( Gia_ObjChild1(pObj), vSuper, 0, fUseMuxes, fUseSuper ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CecG_CollectSuper( Gia_Obj_t * pObj, int fUseMuxes, int fUseSuper, Vec_Ptr_t * vSuper ) +{ + assert( !Gia_IsComplement(pObj) ); + assert( !Gia_ObjIsCi(pObj) ); + Vec_PtrClear( vSuper ); + CecG_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes, fUseSuper ); +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CecG_ObjAddToFrontier( Cec_ManSat_t * p, Gia_Obj_t * pObj, Vec_Ptr_t * vFrontier ) +{ + assert( !Gia_IsComplement(pObj) ); + if ( CecG_ObjSatNum(p,pObj) ) + return; + assert( CecG_ObjSatNum(p,pObj) == 0 ); + if ( Gia_ObjIsConst0(pObj) ) + return; + Vec_PtrPush( p->vUsedNodes, pObj ); + CecG_ObjSetSatNum( p, pObj, sat_solver_addvar( p->pSat ) ); + if ( Gia_ObjIsAnd(pObj) ) + Vec_PtrPush( vFrontier, pObj ); +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CecG_CnfNodeAddToSolver( Cec_ManSat_t * p, Gia_Obj_t * pObj ) +{ + Vec_Ptr_t * vFrontier; + Gia_Obj_t * pNode, * pFanin; + int i, k, fUseMuxes = 0 == p->pPars->SolverType; + // quit if CNF is ready + if ( CecG_ObjSatNum(p,pObj) ) + return; + if ( Gia_ObjIsCi(pObj) ) + { + Vec_PtrPush( p->vUsedNodes, pObj ); + CecG_ObjSetSatNum( p, pObj, sat_solver_addvar( p->pSat ) ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + + // start the frontier + vFrontier = Vec_PtrAlloc( 100 ); + CecG_ObjAddToFrontier( p, pObj, vFrontier ); + // explore nodes in the frontier + Vec_PtrForEachEntry( Gia_Obj_t *, vFrontier, pNode, i ) + { + // create the supergate + assert( CecG_ObjSatNum(p,pNode) ); + if ( fUseMuxes && Gia_ObjIsMuxType(pNode) ) + { + Vec_PtrClear( p->vFanins ); + Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin0( Gia_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin0( Gia_ObjFanin1(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin1( Gia_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin1( Gia_ObjFanin1(pNode) ) ); + Vec_PtrForEachEntry( Gia_Obj_t *, p->vFanins, pFanin, k ) + CecG_ObjAddToFrontier( p, Gia_Regular(pFanin), vFrontier ); + CecG_AddClausesMux( p, pNode ); + } + else + { + CecG_CollectSuper( pNode, fUseMuxes, 0 == p->pPars->SolverType, p->vFanins ); + Vec_PtrForEachEntry( Gia_Obj_t *, p->vFanins, pFanin, k ) + CecG_ObjAddToFrontier( p, Gia_Regular(pFanin), vFrontier ); + + if( p->pPars->SolverType < 2 ) + CecG_AddClausesSuper( p, pNode, p->vFanins ); + } + assert( Vec_PtrSize(p->vFanins) > 1 ); + } + if( p->pPars->SolverType ) + Vec_PtrForEachEntry( Gia_Obj_t *, vFrontier, pNode, i ){ + int var = CecG_ObjSatNum( p, pNode ); + int Lit0 = Abc_Var2Lit( CecG_ObjSatNum( p, Gia_ObjFanin0(pNode) ), Gia_ObjFaninC0(pNode) ); + int Lit1 = Abc_Var2Lit( CecG_ObjSatNum( p, Gia_ObjFanin1(pNode) ), Gia_ObjFaninC1(pNode) ); + assert(Gia_ObjIsAnd(pNode)); + if ( (Lit0 > Lit1) ^ Gia_ObjIsXor(pNode) ) + Lit1 ^= Lit0, Lit0 ^= Lit1, Lit1 ^= Lit0; + sat_solver_set_var_fanin_lit( p->pSat, var, Lit0, Lit1 ); + } + Vec_PtrFree( vFrontier ); +} + + +/**Function************************************************************* + + Synopsis [Recycles the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CecG_ManSatSolverRecycle( Cec_ManSat_t * p ) +{ + int Lit; + if ( p->pSat ) + { + Gia_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( Gia_Obj_t *, p->vUsedNodes, pObj, i ) + CecG_ObjSetSatNum( p, pObj, 0 ); + Vec_PtrClear( p->vUsedNodes ); +// memset( p->pSatVars, 0, sizeof(int) * Gia_ManObjNumMax(p->pAigTotal) ); + sat_solver_stop( p->pSat ); + } + p->pSat = sat_solver_start(); + assert( 0 <= p->pPars->SolverType && p->pPars->SolverType <= 2 ); + sat_solver_set_jftr( p->pSat, p->pPars->SolverType ); + //sat_solver_setnvars( p->pSat, 1000 ); // minisat only + //p->pSat->factors = ABC_CALLOC( double, p->pSat->cap ); + // var 0 is not used + // var 1 is reserved for const0 node - add the clause + +// p->nSatVars = 0; + CecG_ObjSetSatNum( p, Gia_ManConst0(p->pAig), sat_solver_addvar( p->pSat ) ); + Lit = toLitCond( CecG_ObjSatNum( p, Gia_ManConst0(p->pAig) ), 1 ); + sat_solver_addclause( p->pSat, &Lit, 1 ); +// if ( p->pPars->fPolarFlip ) // no need to normalize const0 node (bug fix by SS on 9/17/2012) +// Lit = lit_neg( Lit ); + + p->nRecycles++; + p->nCallsSince = 0; +} + + +/**Function************************************************************* + + Synopsis [Runs equivalence test for the two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int CecG_ManSatCheckNode( Cec_ManSat_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pObjR = Gia_Regular(pObj); + int nBTLimit = p->pPars->nBTLimit; + int Lit, RetValue, nConflicts; + abctime clk = Abc_Clock(); + + if ( pObj == Gia_ManConst0(p->pAig) ) + return 1; + if ( pObj == Gia_ManConst1(p->pAig) ) + { + assert( 0 ); + return 0; + } + + p->nCallsSince++; // experiment with this!!! + p->nSatTotal++; + + // check if SAT solver needs recycling + if ( p->pSat == NULL || + (p->pPars->nSatVarMax && + sat_solver_varnum(p->pSat) > p->pPars->nSatVarMax && + p->nCallsSince > p->pPars->nCallsRecycle) ) + CecG_ManSatSolverRecycle( p ); + + // if the nodes do not have SAT variables, allocate them + CecG_CnfNodeAddToSolver( p, pObjR ); + + if( p->pPars->SolverType ){ + sat_solver_start_new_round( p->pSat ); + sat_solver_mark_cone( p->pSat, CecG_ObjSatNum(p, pObjR) ); + } + + // propage unit clauses // minisat only + //if ( p->pSat->qtail != p->pSat->qhead ) + //{ + // status = sat_solver_simplify(p->pSat); + // assert( status != 0 ); + // assert( p->pSat->qtail == p->pSat->qhead ); + //} + + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 + Lit = toLitCond( CecG_ObjSatNum(p,pObjR), Gia_IsComplement(pObj) ); + if ( p->pPars->fPolarFlip ) + { + if ( pObjR->fPhase ) Lit = lit_neg( Lit ); + } + nConflicts = sat_solver_conflictnum(p->pSat); + + sat_solver_set_conflict_budget( p->pSat, nBTLimit ); + RetValue = sat_solver_solve( p->pSat, &Lit, 1 ); + //RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, + // (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + if ( RetValue == l_False ) + { +p->timeSatUnsat += Abc_Clock() - clk; + Lit = lit_neg( Lit ); + RetValue = sat_solver_addclause( p->pSat, &Lit, 1 ); + assert( RetValue ); + p->nSatUnsat++; + p->nConfUnsat += sat_solver_conflictnum(p->pSat) - nConflicts; +//Abc_Print( 1, "UNSAT after %d conflicts\n", sat_solver_conflictnum(p->pSat) - nConflicts ); + return 1; + } + else if ( RetValue == l_True ) + { +p->timeSatSat += Abc_Clock() - clk; + p->nSatSat++; + p->nConfSat += sat_solver_conflictnum(p->pSat) - nConflicts; +//Abc_Print( 1, "SAT after %d conflicts\n", sat_solver_conflictnum(p->pSat) - nConflicts ); + return 0; + } + else // if ( RetValue == l_Undef ) + { +p->timeSatUndec += Abc_Clock() - clk; + p->nSatUndec++; + p->nConfUndec += sat_solver_conflictnum(p->pSat) - nConflicts; +//Abc_Print( 1, "UNDEC after %d conflicts\n", sat_solver_conflictnum(p->pSat) - nConflicts ); + return -1; + } +} + +void CecG_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars, int f0Proved ) +{ + Bar_Progress_t * pProgress = NULL; + Cec_ManSat_t * p; + Gia_Obj_t * pObj; + int i, status; + abctime clk = Abc_Clock(), clk2; + Vec_PtrFreeP( &pAig->vSeqModelVec ); + if( pPars->SolverType ) + pPars->fPolarFlip = 0; + // reset the manager + if ( pPat ) + { + pPat->iStart = Vec_StrSize(pPat->vStorage); + pPat->nPats = 0; + pPat->nPatLits = 0; + pPat->nPatLitsMin = 0; + } + Gia_ManSetPhase( pAig ); + Gia_ManLevelNum( pAig ); + Gia_ManIncrementTravId( pAig ); + p = Cec_ManSatCreate( pAig, pPars ); + pProgress = Bar_ProgressStart( stdout, Gia_ManPoNum(pAig) ); + Gia_ManForEachCo( pAig, pObj, i ) + { + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + { + status = !Gia_ObjFaninC0(pObj); + pObj->fMark0 = (status == 0); + pObj->fMark1 = (status == 1); + continue; + } + Bar_ProgressUpdate( pProgress, i, "SAT..." ); +clk2 = Abc_Clock(); + status = CecG_ManSatCheckNode( p, Gia_ObjChild0(pObj) ); + pObj->fMark0 = (status == 0); + pObj->fMark1 = (status == 1); + + if ( f0Proved && status == 1 ) + Gia_ManPatchCoDriver( pAig, i, 0 ); +/* + if ( status == -1 ) + { + Gia_Man_t * pTemp = Gia_ManDupDfsCone( pAig, pObj ); + Gia_AigerWrite( pTemp, "gia_hard.aig", 0, 0, 0 ); + Gia_ManStop( pTemp ); + Abc_Print( 1, "Dumping hard cone into file \"%s\".\n", "gia_hard.aig" ); + } +*/ + if ( status != 0 ) + continue; + // save the pattern + //if ( pPat ) + //{ + // abctime clk3 = Abc_Clock(); + // Cec_ManPatSavePattern( pPat, p, pObj ); + // pPat->timeTotalSave += Abc_Clock() - clk3; + //} + // quit if one of them is solved + if ( pPars->fCheckMiter ) + break; + } + p->timeTotal = Abc_Clock() - clk; + printf("Recycles %d\n", p->nRecycles); + Bar_ProgressStop( pProgress ); + if ( pPars->fVerbose ) + Cec_ManSatPrintStats( p ); + if( p->pSat ) + sat_solver_stop( p->pSat ); + p->pSat = NULL; + Cec_ManSatStop( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/cecSweep.c b/src/proof/cec/cecSweep.c index 55f2219f..abe77960 100644 --- a/src/proof/cec/cecSweep.c +++ b/src/proof/cec/cecSweep.c @@ -289,6 +289,9 @@ p->timeSim += Abc_Clock() - clk; p->nAllFailed++; } } + p->nAllProvedS += p->nAllProved; + p->nAllDisprovedS += p->nAllDisproved; + p->nAllFailedS += p->nAllFailed; return 0; } diff --git a/src/proof/cec/module.make b/src/proof/cec/module.make index 86ec2677..23595f23 100644 --- a/src/proof/cec/module.make +++ b/src/proof/cec/module.make @@ -8,8 +8,11 @@ SRC += src/proof/cec/cecCec.c \ src/proof/cec/cecPat.c \ src/proof/cec/cecSat.c \ src/proof/cec/cecSatG.c \ + src/proof/cec/cecSatG2.c \ src/proof/cec/cecSeq.c \ + src/proof/cec/cecSim.c \ src/proof/cec/cecSolve.c \ + src/proof/cec/cecSolveG.c \ src/proof/cec/cecSplit.c \ src/proof/cec/cecSynth.c \ src/proof/cec/cecSweep.c diff --git a/src/proof/dch/dch.h b/src/proof/dch/dch.h index 5d644643..07f6a1d2 100644 --- a/src/proof/dch/dch.h +++ b/src/proof/dch/dch.h @@ -52,6 +52,7 @@ struct Dch_Pars_t_ int fPower; // uses power-aware rewriting int fUseGia; // uses GIA package int fUseCSat; // uses circuit-based solver + int fUseNew; // uses new implementation int fLightSynth; // uses lighter version of synthesis int fSkipRedSupp; // skip choices with redundant support vars int fVerbose; // verbose stats diff --git a/src/proof/dch/dchCore.c b/src/proof/dch/dchCore.c index 0da65bee..19907f00 100644 --- a/src/proof/dch/dchCore.c +++ b/src/proof/dch/dchCore.c @@ -90,7 +90,7 @@ Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars ) { Dch_Man_t * p; Aig_Man_t * pResult; - abctime clk, clkTotal = Abc_Clock(); + abctime clk, clk2 = Abc_Clock(), clkTotal = Abc_Clock(); // reset random numbers Aig_ManRandom(1); // start the choicing manager @@ -106,6 +106,8 @@ p->timeSimInit = Abc_Clock() - clk; // free memory ahead of time p->timeTotal = Abc_Clock() - clkTotal; Dch_ManStop( p ); + if ( pPars->fVerbose ) + Abc_PrintTime( 1, "Old choice computation time", Abc_Clock() - clk2 ); // create choices ABC_FREE( pAig->pTable ); pResult = Dch_DeriveChoiceAig( pAig, pPars->fSkipRedSupp ); diff --git a/src/proof/dch/dchSimSat.c b/src/proof/dch/dchSimSat.c index d3dbbe16..bbab0529 100644 --- a/src/proof/dch/dchSimSat.c +++ b/src/proof/dch/dchSimSat.c @@ -91,8 +91,8 @@ void Dch_ManCollectTfoCands( Dch_Man_t * p, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 Aig_ObjSetTravIdCurrent( p->pAigTotal, Aig_ManConst1(p->pAigTotal) ); Dch_ManCollectTfoCands_rec( p, pObj1 ); Dch_ManCollectTfoCands_rec( p, pObj2 ); - Vec_PtrSort( p->vSimRoots, (int (*)(void))Aig_ObjCompareIdIncrease ); - Vec_PtrSort( p->vSimClasses, (int (*)(void))Aig_ObjCompareIdIncrease ); + Vec_PtrSort( p->vSimRoots, (int (*)(const void *, const void *))Aig_ObjCompareIdIncrease ); + Vec_PtrSort( p->vSimClasses, (int (*)(const void *, const void *))Aig_ObjCompareIdIncrease ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimClasses, pObj, i ) pObj->fMarkA = 0; } diff --git a/src/proof/fra/fraSec.c b/src/proof/fra/fraSec.c index 7e382fc8..eadd06c9 100644 --- a/src/proof/fra/fraSec.c +++ b/src/proof/fra/fraSec.c @@ -20,6 +20,7 @@ #include "fra.h" #include "aig/ioa/ioa.h" +#include "aig/gia/giaAig.h" #include "proof/int/int.h" #include "proof/ssw/ssw.h" #include "aig/saig/saig.h" @@ -92,6 +93,28 @@ void Fra_SecSetDefaultParams( Fra_Sec_t * p ) SeeAlso [] ***********************************************************************/ +Aig_Man_t * Fra_FraigEquivence2( Aig_Man_t * pAig, int nConfs, int fVerbose ) +{ + extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); + Gia_Man_t * pGia = Gia_ManFromAig( pAig ); + Gia_Man_t * pGiaNew = Cec4_ManSimulateTest3( pGia, nConfs, 0 ); + Aig_Man_t * pAigNew = Gia_ManToAig( pGiaNew, 0 ); + Gia_ManStop( pGiaNew ); + Gia_ManStop( pGia ); + return pAigNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int Fra_FraigSec( Aig_Man_t * p, Fra_Sec_t * pParSec, Aig_Man_t ** ppResult ) { Ssw_Pars_t Pars2, * pPars2 = &Pars2; @@ -267,6 +290,7 @@ ABC_PRT( "Time", Abc_Clock() - clk ); { clk = Abc_Clock(); pNew = Fra_FraigEquivence( pTemp = pNew, 100, 0 ); + //pNew = Fra_FraigEquivence2( pTemp = pNew, 100, 0 ); Aig_ManStop( pTemp ); if ( pParSec->fVerbose ) { diff --git a/src/proof/int/int.h b/src/proof/int/int.h index 906d8aaf..3dc8490d 100644 --- a/src/proof/int/int.h +++ b/src/proof/int/int.h @@ -24,7 +24,7 @@ /* The interpolation algorithm implemented here was introduced in the paper: - K. L. McMillan. Interpolation and SAT-based model checking. CAV’03, pp. 1-13. + K. L. McMillan. Interpolation and SAT-based model checking. CAV 03, pp. 1-13. */ //////////////////////////////////////////////////////////////////////// diff --git a/src/proof/pdr/pdrCore.c b/src/proof/pdr/pdrCore.c index f71569a3..d77fd4e1 100644 --- a/src/proof/pdr/pdrCore.c +++ b/src/proof/pdr/pdrCore.c @@ -157,7 +157,7 @@ int Pdr_ManPushClauses( Pdr_Man_t * p ) assert( p->iUseFrame > 0 ); Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, k, iStartFrame, kMax ) { - Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare ); + Vec_PtrSort( vArrayK, (int (*)(const void *, const void *))Pdr_SetCompare ); vArrayK1 = Vec_VecEntry( p->vClauses, k+1 ); Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j ) { @@ -216,7 +216,7 @@ int Pdr_ManPushClauses( Pdr_Man_t * p ) // clean up the last one vArrayK = Vec_VecEntry( p->vClauses, kMax ); - Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare ); + Vec_PtrSort( vArrayK, (int (*)(const void *, const void *))Pdr_SetCompare ); Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j ) { // remove cubes in the same frame that are contained by pCubeK diff --git a/src/proof/pdr/pdrIncr.c b/src/proof/pdr/pdrIncr.c index f4f2c8c8..9ca72ba6 100644 --- a/src/proof/pdr/pdrIncr.c +++ b/src/proof/pdr/pdrIncr.c @@ -47,7 +47,7 @@ Vec_Ptr_t * IPdr_ManPushClausesK( Pdr_Man_t * p, int k ) assert( Vec_VecSize(p->vClauses) == k + 1 ); vArrayK = Vec_VecEntry( p->vClauses, k ); - Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare ); + Vec_PtrSort( vArrayK, (int (*)(const void *, const void *))Pdr_SetCompare ); vArrayK1 = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j ) { @@ -117,7 +117,7 @@ void IPdr_ManPrintClauses( Vec_Vec_t * vClauses, int kStart, int nRegs ) int i, k, Counter = 0; Vec_VecForEachLevelStart( vClauses, vArrayK, k, kStart ) { - Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare ); + Vec_PtrSort( vArrayK, (int (*)(const void *, const void *))Pdr_SetCompare ); Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCube, i ) { Abc_Print( 1, "Frame[%4d]Cube[%4d] = ", k, Counter++ ); diff --git a/src/proof/pdr/pdrInv.c b/src/proof/pdr/pdrInv.c index ba4f0448..ae61ce2c 100644 --- a/src/proof/pdr/pdrInv.c +++ b/src/proof/pdr/pdrInv.c @@ -248,7 +248,7 @@ void Pdr_ManPrintClauses( Pdr_Man_t * p, int kStart ) int i, k, Counter = 0; Vec_VecForEachLevelStart( p->vClauses, vArrayK, k, kStart ) { - Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare ); + Vec_PtrSort( vArrayK, (int (*)(const void *, const void *))Pdr_SetCompare ); Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCube, i ) { Abc_Print( 1, "C=%4d. F=%4d ", Counter++, k ); @@ -370,7 +370,7 @@ void Pdr_ManDumpClauses( Pdr_Man_t * p, char * pFileName, int fProved ) vCubes = Pdr_ManCollectCubes( p, kStart ); else vCubes = Vec_PtrDup( p->vInfCubes ); - Vec_PtrSort( vCubes, (int (*)(void))Pdr_SetCompare ); + Vec_PtrSort( vCubes, (int (*)(const void *, const void *))Pdr_SetCompare ); // Pdr_ManDumpAig( p->pAig, vCubes ); // count cubes Count = 0; @@ -446,7 +446,7 @@ Vec_Str_t * Pdr_ManDumpString( Pdr_Man_t * p ) vCubes = Pdr_ManCollectCubes( p, kStart ); else vCubes = Vec_PtrDup( p->vInfCubes ); - Vec_PtrSort( vCubes, (int (*)(void))Pdr_SetCompare ); + Vec_PtrSort( vCubes, (int (*)(const void *, const void *))Pdr_SetCompare ); // collect variable appearances vFlopCounts = p->pPars->fUseSupp ? Pdr_ManCountFlops( p, vCubes ) : NULL; // output cubes diff --git a/src/sat/bsat/satSolver.h b/src/sat/bsat/satSolver.h index f4126567..53f3ebe2 100644 --- a/src/sat/bsat/satSolver.h +++ b/src/sat/bsat/satSolver.h @@ -292,6 +292,24 @@ static inline int sat_solver_final(sat_solver* s, int ** ppArray) return s->conf_final.size; } +static inline void sat_solver_randomize( sat_solver * pSat, int iVar, int nVars ) +{ + int i, nPols = 0, * pVars = ABC_ALLOC( int, nVars ); + for ( i = 0; i < nVars; i++ ) + if ( Abc_Random(0) & 1 ) + pVars[nPols++] = iVar + i; + sat_solver_set_polarity( pSat, pVars, nPols ); + for ( i = 0; i < nVars; i++ ) + pVars[i] = iVar + i; + for ( i = 0; i < nVars; i++ ) + { + int j = Abc_Random(0) % nVars; + ABC_SWAP( int, pVars[i], pVars[j] ); + } + sat_solver_set_var_activity( pSat, pVars, nVars ); + ABC_FREE( pVars ); +} + static inline abctime sat_solver_set_runtime_limit(sat_solver* s, abctime Limit) { abctime nRuntimeLimit = s->nRuntimeLimit; diff --git a/src/sat/glucose/AbcGlucose.cpp b/src/sat/glucose/AbcGlucose.cpp index 247bc89a..ad595ab9 100644 --- a/src/sat/glucose/AbcGlucose.cpp +++ b/src/sat/glucose/AbcGlucose.cpp @@ -58,7 +58,7 @@ using namespace Gluco; SeeAlso [] ***********************************************************************/ -Gluco::SimpSolver * glucose_solver_start() +SimpSolver * glucose_solver_start() { SimpSolver * S = new SimpSolver; S->setIncrementalMode(); @@ -116,6 +116,11 @@ int glucose_solver_addvar(Gluco::SimpSolver* S) return S->nVars() - 1; } +int * glucose_solver_read_cex(Gluco::SimpSolver* S ) +{ + return S->getCex(); +} + int glucose_solver_read_cex_varvalue(Gluco::SimpSolver* S, int ivar) { return S->model[ivar] == l_True; @@ -208,6 +213,10 @@ int bmcg_sat_solver_elim_varnum(bmcg_sat_solver* s) return ((Gluco::SimpSolver*)s)->eliminated_vars; } +int * bmcg_sat_solver_read_cex(bmcg_sat_solver* s) +{ + return glucose_solver_read_cex((Gluco::SimpSolver*)s); +} int bmcg_sat_solver_read_cex_varvalue(bmcg_sat_solver* s, int ivar) { return glucose_solver_read_cex_varvalue((Gluco::SimpSolver*)s, ivar); @@ -317,6 +326,64 @@ int bmcg_sat_solver_add_and( bmcg_sat_solver * s, int iVar, int iVar0, int iVar1 return 1; } +int bmcg_solver_add_xor( bmcg_sat_solver * pSat, int iVarA, int iVarB, int iVarC, int fCompl ) +{ + int Lits[3]; + int Cid; + assert( iVarA >= 0 && iVarB >= 0 && iVarC >= 0 ); + + Lits[0] = Abc_Var2Lit( iVarA, !fCompl ); + Lits[1] = Abc_Var2Lit( iVarB, 1 ); + Lits[2] = Abc_Var2Lit( iVarC, 1 ); + Cid = bmcg_sat_solver_addclause( pSat, Lits, 3 ); + assert( Cid ); + + Lits[0] = Abc_Var2Lit( iVarA, !fCompl ); + Lits[1] = Abc_Var2Lit( iVarB, 0 ); + Lits[2] = Abc_Var2Lit( iVarC, 0 ); + Cid = bmcg_sat_solver_addclause( pSat, Lits, 3 ); + assert( Cid ); + + Lits[0] = Abc_Var2Lit( iVarA, fCompl ); + Lits[1] = Abc_Var2Lit( iVarB, 1 ); + Lits[2] = Abc_Var2Lit( iVarC, 0 ); + Cid = bmcg_sat_solver_addclause( pSat, Lits, 3 ); + assert( Cid ); + + Lits[0] = Abc_Var2Lit( iVarA, fCompl ); + Lits[1] = Abc_Var2Lit( iVarB, 0 ); + Lits[2] = Abc_Var2Lit( iVarC, 1 ); + Cid = bmcg_sat_solver_addclause( pSat, Lits, 3 ); + assert( Cid ); + return 4; +} + +int bmcg_sat_solver_jftr(bmcg_sat_solver* s) +{ + return ((Gluco::SimpSolver*)s)->jftr; +} + +void bmcg_sat_solver_set_jftr(bmcg_sat_solver* s, int jftr) +{ + ((Gluco::SimpSolver*)s)->jftr = jftr; +} + +void bmcg_sat_solver_set_var_fanin_lit(bmcg_sat_solver* s, int var, int lit0, int lit1) +{ + ((Gluco::SimpSolver*)s)->sat_solver_set_var_fanin_lit(var, lit0, lit1); +} + +void bmcg_sat_solver_start_new_round(bmcg_sat_solver* s) +{ + ((Gluco::SimpSolver*)s)->sat_solver_start_new_round(); +} + +void bmcg_sat_solver_mark_cone(bmcg_sat_solver* s, int var) +{ + ((Gluco::SimpSolver*)s)->sat_solver_mark_cone(var); +} + + #else /**Function************************************************************* @@ -330,7 +397,7 @@ int bmcg_sat_solver_add_and( bmcg_sat_solver * s, int iVar, int iVar0, int iVar1 SeeAlso [] ***********************************************************************/ -Gluco::Solver * glucose_solver_start() +Solver * glucose_solver_start() { Solver * S = new Solver; S->setIncrementalMode(); @@ -342,6 +409,11 @@ void glucose_solver_stop(Gluco::Solver* S) delete S; } +void glucose_solver_reset(Gluco::Solver* S) +{ + S->reset(); +} + int glucose_solver_addclause(Gluco::Solver* S, int * plits, int nlits) { vec<Lit> lits; @@ -383,6 +455,11 @@ int glucose_solver_addvar(Gluco::Solver* S) return S->nVars() - 1; } +int * glucose_solver_read_cex(Gluco::Solver* S ) +{ + return S->getCex(); +} + int glucose_solver_read_cex_varvalue(Gluco::Solver* S, int ivar) { return S->model[ivar] == l_True; @@ -413,6 +490,10 @@ void bmcg_sat_solver_stop(bmcg_sat_solver* s) { glucose_solver_stop((Gluco::Solver*)s); } +void bmcg_sat_solver_reset(bmcg_sat_solver* s) +{ + glucose_solver_reset((Gluco::Solver*)s); +} int bmcg_sat_solver_addclause(bmcg_sat_solver* s, int * plits, int nlits) { @@ -470,6 +551,11 @@ int bmcg_sat_solver_elim_varnum(bmcg_sat_solver* s) // return ((Gluco::SimpSolver*)s)->eliminated_vars; } +int * bmcg_sat_solver_read_cex(bmcg_sat_solver* s) +{ + return glucose_solver_read_cex((Gluco::Solver*)s); +} + int bmcg_sat_solver_read_cex_varvalue(bmcg_sat_solver* s, int ivar) { return glucose_solver_read_cex_varvalue((Gluco::Solver*)s, ivar); @@ -556,6 +642,86 @@ int bmcg_sat_solver_minimize_assumptions( bmcg_sat_solver * s, int * plits, int return nresL + nresR; } +int bmcg_sat_solver_add_and( bmcg_sat_solver * s, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1, int fCompl ) +{ + int Lits[3]; + + Lits[0] = Abc_Var2Lit( iVar, !fCompl ); + Lits[1] = Abc_Var2Lit( iVar0, fCompl0 ); + if ( !bmcg_sat_solver_addclause( s, Lits, 2 ) ) + return 0; + + Lits[0] = Abc_Var2Lit( iVar, !fCompl ); + Lits[1] = Abc_Var2Lit( iVar1, fCompl1 ); + if ( !bmcg_sat_solver_addclause( s, Lits, 2 ) ) + return 0; + + Lits[0] = Abc_Var2Lit( iVar, fCompl ); + Lits[1] = Abc_Var2Lit( iVar0, !fCompl0 ); + Lits[2] = Abc_Var2Lit( iVar1, !fCompl1 ); + if ( !bmcg_sat_solver_addclause( s, Lits, 3 ) ) + return 0; + + return 1; +} + +int bmcg_solver_add_xor( bmcg_sat_solver * pSat, int iVarA, int iVarB, int iVarC, int fCompl ) +{ + int Lits[3]; + int Cid; + assert( iVarA >= 0 && iVarB >= 0 && iVarC >= 0 ); + + Lits[0] = Abc_Var2Lit( iVarA, !fCompl ); + Lits[1] = Abc_Var2Lit( iVarB, 1 ); + Lits[2] = Abc_Var2Lit( iVarC, 1 ); + Cid = bmcg_sat_solver_addclause( pSat, Lits, 3 ); + assert( Cid ); + + Lits[0] = Abc_Var2Lit( iVarA, !fCompl ); + Lits[1] = Abc_Var2Lit( iVarB, 0 ); + Lits[2] = Abc_Var2Lit( iVarC, 0 ); + Cid = bmcg_sat_solver_addclause( pSat, Lits, 3 ); + assert( Cid ); + + Lits[0] = Abc_Var2Lit( iVarA, fCompl ); + Lits[1] = Abc_Var2Lit( iVarB, 1 ); + Lits[2] = Abc_Var2Lit( iVarC, 0 ); + Cid = bmcg_sat_solver_addclause( pSat, Lits, 3 ); + assert( Cid ); + + Lits[0] = Abc_Var2Lit( iVarA, fCompl ); + Lits[1] = Abc_Var2Lit( iVarB, 0 ); + Lits[2] = Abc_Var2Lit( iVarC, 1 ); + Cid = bmcg_sat_solver_addclause( pSat, Lits, 3 ); + assert( Cid ); + return 4; +} + +int bmcg_sat_solver_jftr(bmcg_sat_solver* s) +{ + return ((Gluco::Solver*)s)->jftr; +} + +void bmcg_sat_solver_set_jftr(bmcg_sat_solver* s, int jftr) +{ + ((Gluco::Solver*)s)->jftr = jftr; +} + +void bmcg_sat_solver_set_var_fanin_lit(bmcg_sat_solver* s, int var, int lit0, int lit1) +{ + ((Gluco::Solver*)s)->sat_solver_set_var_fanin_lit(var, lit0, lit1); +} + +void bmcg_sat_solver_start_new_round(bmcg_sat_solver* s) +{ + ((Gluco::Solver*)s)->sat_solver_start_new_round(); +} + +void bmcg_sat_solver_mark_cone(bmcg_sat_solver* s, int var) +{ + ((Gluco::Solver*)s)->sat_solver_mark_cone(var); +} + #endif diff --git a/src/sat/glucose/AbcGlucose.h b/src/sat/glucose/AbcGlucose.h index 4489adc7..89a3652f 100644 --- a/src/sat/glucose/AbcGlucose.h +++ b/src/sat/glucose/AbcGlucose.h @@ -83,6 +83,7 @@ extern int bmcg_sat_solver_eliminate( bmcg_sat_solver* s, int turn extern int bmcg_sat_solver_var_is_elim( bmcg_sat_solver* s, int v ); extern void bmcg_sat_solver_var_set_frozen( bmcg_sat_solver* s, int v, int freeze ); extern int bmcg_sat_solver_elim_varnum(bmcg_sat_solver* s); +extern int * bmcg_sat_solver_read_cex( bmcg_sat_solver* s ); extern int bmcg_sat_solver_read_cex_varvalue( bmcg_sat_solver* s, int ); extern void bmcg_sat_solver_set_stop( bmcg_sat_solver* s, int * pstop ); extern abctime bmcg_sat_solver_set_runtime_limit( bmcg_sat_solver* s, abctime Limit ); @@ -93,9 +94,16 @@ extern int bmcg_sat_solver_learntnum( bmcg_sat_solver* s ); extern int bmcg_sat_solver_conflictnum( bmcg_sat_solver* s ); extern int bmcg_sat_solver_minimize_assumptions( bmcg_sat_solver * s, int * plits, int nlits, int pivot ); extern int bmcg_sat_solver_add_and( bmcg_sat_solver * s, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1, int fCompl ); +extern int bmcg_sat_solver_add_xor( bmcg_sat_solver * s, int iVarA, int iVarB, int iVarC, int fCompl ); extern int bmcg_sat_solver_quantify( bmcg_sat_solver * s[], Gia_Man_t * p, int iLit, int fHash, int(*pFuncCiToKeep)(void *, int), void * pData, Vec_Int_t * vDLits ); extern int bmcg_sat_solver_equiv_overlap_check( bmcg_sat_solver * s, Gia_Man_t * p, int iLit0, int iLit1, int fEquiv ); extern Vec_Str_t * bmcg_sat_solver_sop( Gia_Man_t * p, int CubeLimit ); +extern int bmcg_sat_solver_jftr( bmcg_sat_solver * s ); +extern void bmcg_sat_solver_set_jftr( bmcg_sat_solver * s, int jftr ); +extern void bmcg_sat_solver_set_var_fanin_lit( bmcg_sat_solver * s, int var, int lit0, int lit1 ); +extern void bmcg_sat_solver_start_new_round( bmcg_sat_solver * s ); +extern void bmcg_sat_solver_mark_cone( bmcg_sat_solver * s, int var ); + extern void Glucose_SolveCnf( char * pFilename, Glucose_Pars * pPars ); extern int Glucose_SolveAig( Gia_Man_t * p, Glucose_Pars * pPars ); diff --git a/src/sat/glucose/Glucose.cpp b/src/sat/glucose/Glucose.cpp index 0f2d2fce..c975c6ca 100644 --- a/src/sat/glucose/Glucose.cpp +++ b/src/sat/glucose/Glucose.cpp @@ -609,7 +609,7 @@ void Solver::analyze(CRef confl, vec<Lit>& out_learnt,vec<Lit>&selectors, int& o for(i = 0;i<selectors.size();i++) out_learnt.push(selectors[i]); - out_learnt.copyTo(analyze_toclear); + out_learnt.copyTo_(analyze_toclear); if (ccmin_mode == 2){ uint32_t abstract_level = 0; for (i = 1; i < out_learnt.size(); i++) diff --git a/src/sat/glucose/Solver.h b/src/sat/glucose/Solver.h index df72660a..3d7d26ea 100644 --- a/src/sat/glucose/Solver.h +++ b/src/sat/glucose/Solver.h @@ -64,6 +64,12 @@ public: vec<int> user_vec; vec<Lit> user_lits; + // circuit-based solving + int jftr; + void sat_solver_set_var_fanin_lit(int, int, int); + void sat_solver_start_new_round(); + void sat_solver_mark_cone(int); + // Problem specification: // Var newVar (bool polarity = true, bool dvar = true); // Add a new variable with parameters specifying variable mode. @@ -116,6 +122,7 @@ public: int nLearnts () const; // The current number of learnt clauses. int nVars () const; // The current number of variables. int nFreeVars () const; + int * getCex () const; // Incremental mode void setIncrementalMode(); @@ -418,6 +425,7 @@ inline int Solver::nClauses () const { return clauses.size(); } inline int Solver::nLearnts () const { return learnts.size(); } inline int Solver::nVars () const { return vardata.size(); } inline int Solver::nFreeVars () const { return (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]); } +inline int * Solver::getCex () const { return NULL; } inline void Solver::setPolarity (Var v, bool b) { polarity[v] = b; } inline void Solver::setDecisionVar(Var v, bool b) { @@ -455,6 +463,10 @@ inline void Solver::toDimacs (const char* file, Lit p, Lit q, Lit r){ v inline void Solver::addVar(Var v) { while (v >= nVars()) newVar(); } +inline void Solver::sat_solver_set_var_fanin_lit(int var, int lit0, int lit1) {} +inline void Solver::sat_solver_start_new_round() {} +inline void Solver::sat_solver_mark_cone(int var) {} + //================================================================================================= // Debug etc: diff --git a/src/sat/glucose/SolverTypes.h b/src/sat/glucose/SolverTypes.h index 4f2670a7..b29699fa 100644 --- a/src/sat/glucose/SolverTypes.h +++ b/src/sat/glucose/SolverTypes.h @@ -306,9 +306,15 @@ class OccLists } void clear(bool free = true){ - occs .clear(free); - dirty .clear(free); - dirties.clear(free); + if(free){ + occs .clear(free); + dirty .clear(free); + dirties.clear(free); + } else { + occs .shrink_(occs .size()); + dirty .shrink_(dirty .size()); + dirties.shrink_(dirties.size()); + } } }; diff --git a/src/sat/glucose/Vec.h b/src/sat/glucose/Vec.h index da87af35..dd1bc20a 100644 --- a/src/sat/glucose/Vec.h +++ b/src/sat/glucose/Vec.h @@ -89,7 +89,8 @@ public: T& operator [] (int index) { return data[index]; } // Duplicatation (preferred instead): - void copyTo(vec<T>& copy) const { copy.clear(); copy.growTo(sz); for (int i = 0; i < sz; i++) copy[i] = data[i]; } + void copyTo (vec<T>& copy) const { copy.clear(); copy.growTo(sz); for (int i = 0; i < sz; i++) copy[i] = data[i]; } + void copyTo_(vec<T>& copy) const { copy.shrink_(copy.size()); copy.growTo(sz); for (int i = 0; i < sz; i++) copy[i] = data[i]; } void moveTo(vec<T>& dest) { dest.clear(true); dest.data = data; dest.sz = sz; dest.cap = cap; data = NULL; sz = 0; cap = 0; } }; diff --git a/src/sat/glucose/stdint.h b/src/sat/glucose/stdint.h deleted file mode 100644 index e36a136d..00000000 --- a/src/sat/glucose/stdint.h +++ /dev/null @@ -1,1628 +0,0 @@ - - - - - - -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <link rel="dns-prefetch" href="https://assets-cdn.github.com"> - <link rel="dns-prefetch" href="https://avatars0.githubusercontent.com"> - <link rel="dns-prefetch" href="https://avatars1.githubusercontent.com"> - <link rel="dns-prefetch" href="https://avatars2.githubusercontent.com"> - <link rel="dns-prefetch" href="https://avatars3.githubusercontent.com"> - <link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com"> - <link rel="dns-prefetch" href="https://user-images.githubusercontent.com/"> - - - - <link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/frameworks-7db951ed87f8f6cbd3a9e89c294e300cf23c1a83ad7ae64c70b8f99b21031340.css" integrity="sha256-fblR7Yf49svTqeicKU4wDPI8GoOteuZMcLj5myEDE0A=" media="all" rel="stylesheet" /> - <link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/github-4b2158409cc56f58dafd534ae676475b1bfe7cb057c415e2c5984e3c13b041e5.css" integrity="sha256-SyFYQJzFb1ja/VNK5nZHWxv+fLBXxBXixZhOPBOwQeU=" media="all" rel="stylesheet" /> - - - <link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/site-955690c4e09b2eeb3627ae6048471522eb98b42054150bd855ad4183db364816.css" integrity="sha256-lVaQxOCbLus2J65gSEcVIuuYtCBUFQvYVa1Bg9s2SBY=" media="all" rel="stylesheet" /> - - - <meta name="viewport" content="width=device-width"> - - <title>gntp-send/stdint.h at master · mattn/gntp-send · GitHub</title> - <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub"> - <link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub"> - <meta property="fb:app_id" content="1401488693436528"> - - - <meta content="https://avatars1.githubusercontent.com/u/10111?v=4&s=400" property="og:image" /><meta content="GitHub" property="og:site_name" /><meta content="object" property="og:type" /><meta content="mattn/gntp-send" property="og:title" /><meta content="https://github.com/mattn/gntp-send" property="og:url" /><meta content="gntp-send - command line program that send to growl using GNTP protocol." property="og:description" /> - - <link rel="assets" href="https://assets-cdn.github.com/"> - - <meta name="pjax-timeout" content="1000"> - - <meta name="request-id" content="C6BC:2817D:56F2228:8688546:59B04B65" data-pjax-transient> - - - <meta name="selected-link" value="repo_source" data-pjax-transient> - - <meta name="google-site-verification" content="KT5gs8h0wvaagLKAVWq8bbeNwnZZK1r1XQysX3xurLU"> -<meta name="google-site-verification" content="ZzhVyEFwb7w3e0-uOTltm8Jsck2F5StVihD0exw2fsA"> - <meta name="google-analytics" content="UA-3769691-2"> - -<meta content="collector.githubapp.com" name="octolytics-host" /><meta content="github" name="octolytics-app-id" /><meta content="https://collector.githubapp.com/github-external/browser_event" name="octolytics-event-url" /><meta content="C6BC:2817D:56F2228:8688546:59B04B65" name="octolytics-dimension-request_id" /><meta content="sea" name="octolytics-dimension-region_edge" /><meta content="iad" name="octolytics-dimension-region_render" /> -<meta content="/<user-name>/<repo-name>/blob/show" data-pjax-transient="true" name="analytics-location" /> - - - - - <meta class="js-ga-set" name="dimension1" content="Logged Out"> - - - - - <meta name="hostname" content="github.com"> - <meta name="user-login" content=""> - - <meta name="expected-hostname" content="github.com"> - <meta name="js-proxy-site-detection-payload" content="YmNhNTY5Y2Y4MjdmNjMyMzc4ODViZmFkM2JmYmE5MDA4YWFkMWRmZWU5YzNjMGZmMmU3M2U2YTc1YWE0ZTEzYXx7InJlbW90ZV9hZGRyZXNzIjoiNzMuMjUyLjEzOC45MyIsInJlcXVlc3RfaWQiOiJDNkJDOjI4MTdEOjU2RjIyMjg6ODY4ODU0Njo1OUIwNEI2NSIsInRpbWVzdGFtcCI6MTUwNDcyNTg2NiwiaG9zdCI6ImdpdGh1Yi5jb20ifQ=="> - - - <meta name="html-safe-nonce" content="c7ac7dad53ebbb213745963c771e009cd0ec2414"> - - <meta http-equiv="x-pjax-version" content="ef2b97c5ce9b111269ce538c13af797b"> - - - <link href="https://github.com/mattn/gntp-send/commits/master.atom" rel="alternate" title="Recent Commits to gntp-send:master" type="application/atom+xml"> - - <meta name="description" content="gntp-send - command line program that send to growl using GNTP protocol."> - <meta name="go-import" content="github.com/mattn/gntp-send git https://github.com/mattn/gntp-send.git"> - - <meta content="10111" name="octolytics-dimension-user_id" /><meta content="mattn" name="octolytics-dimension-user_login" /><meta content="160637" name="octolytics-dimension-repository_id" /><meta content="mattn/gntp-send" name="octolytics-dimension-repository_nwo" /><meta content="true" name="octolytics-dimension-repository_public" /><meta content="false" name="octolytics-dimension-repository_is_fork" /><meta content="160637" name="octolytics-dimension-repository_network_root_id" /><meta content="mattn/gntp-send" name="octolytics-dimension-repository_network_root_nwo" /><meta content="false" name="octolytics-dimension-repository_explore_github_marketplace_ci_cta_shown" /> - - - <link rel="canonical" href="https://github.com/mattn/gntp-send/blob/master/include/msinttypes/stdint.h" data-pjax-transient> - - - <meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats"> - - <meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors"> - - <link rel="mask-icon" href="https://assets-cdn.github.com/pinned-octocat.svg" color="#000000"> - <link rel="icon" type="image/x-icon" href="https://assets-cdn.github.com/favicon.ico"> - -<meta name="theme-color" content="#1e2327"> - - - - </head> - - <body class="logged-out env-production page-blob"> - - - <div class="position-relative js-header-wrapper "> - <a href="#start-of-content" tabindex="1" class="px-2 py-4 show-on-focus js-skip-to-content">Skip to content</a> - <div id="js-pjax-loader-bar" class="pjax-loader-bar"><div class="progress"></div></div> - - - - - - - - <header class="Header header-logged-out position-relative f4 py-3" role="banner"> - <div class="container-lg d-flex px-3"> - <div class="d-flex flex-justify-between flex-items-center"> - <a class="header-logo-invertocat my-0" href="https://github.com/" aria-label="Homepage" data-ga-click="(Logged out) Header, go to homepage, icon:logo-wordmark"> - <svg aria-hidden="true" class="octicon octicon-mark-github" height="32" version="1.1" viewBox="0 0 16 16" width="32"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg> - </a> - - </div> - - <div class="HeaderMenu HeaderMenu--bright d-flex flex-justify-between flex-auto"> - <nav class="mt-0"> - <ul class="d-flex list-style-none"> - <li class="ml-2"> - <a href="/features" class="js-selected-navigation-item HeaderNavlink px-0 py-2 m-0" data-ga-click="Header, click, Nav menu - item:features" data-selected-links="/features /features/project-management /features/code-review /features/project-management /features/integrations /features"> - Features -</a> </li> - <li class="ml-4"> - <a href="/business" class="js-selected-navigation-item HeaderNavlink px-0 py-2 m-0" data-ga-click="Header, click, Nav menu - item:business" data-selected-links="/business /business/security /business/customers /business"> - Business -</a> </li> - - <li class="ml-4"> - <a href="/explore" class="js-selected-navigation-item HeaderNavlink px-0 py-2 m-0" data-ga-click="Header, click, Nav menu - item:explore" data-selected-links="/explore /trending /trending/developers /integrations /integrations/feature/code /integrations/feature/collaborate /integrations/feature/ship showcases showcases_search showcases_landing /explore"> - Explore -</a> </li> - - <li class="ml-4"> - <a href="/marketplace" class="js-selected-navigation-item HeaderNavlink px-0 py-2 m-0" data-ga-click="Header, click, Nav menu - item:marketplace" data-selected-links=" /marketplace"> - Marketplace -</a> </li> - <li class="ml-4"> - <a href="/pricing" class="js-selected-navigation-item HeaderNavlink px-0 py-2 m-0" data-ga-click="Header, click, Nav menu - item:pricing" data-selected-links="/pricing /pricing/developer /pricing/team /pricing/business-hosted /pricing/business-enterprise /pricing"> - Pricing -</a> </li> - </ul> - </nav> - - <div class="d-flex"> - <div class="d-lg-flex flex-items-center mr-3"> - <div class="header-search scoped-search site-scoped-search js-site-search" role="search"> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form accept-charset="UTF-8" action="/mattn/gntp-send/search" class="js-site-search-form" data-scoped-search-url="/mattn/gntp-send/search" data-unscoped-search-url="/search" method="get"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /></div> - <label class="form-control header-search-wrapper js-chromeless-input-container"> - <a href="/mattn/gntp-send/blob/master/include/msinttypes/stdint.h" class="header-search-scope no-underline">This repository</a> - <input type="text" - class="form-control header-search-input js-site-search-focus js-site-search-field is-clearable" - data-hotkey="s" - name="q" - value="" - placeholder="Search" - aria-label="Search this repository" - data-unscoped-placeholder="Search GitHub" - data-scoped-placeholder="Search" - autocapitalize="off"> - <input type="hidden" class="js-site-search-type-field" name="type" > - </label> -</form></div> - - </div> - - <span class="d-inline-block"> - <div class="HeaderNavlink px-0 py-2 m-0"> - <a class="text-bold text-white no-underline" href="/login?return_to=%2Fmattn%2Fgntp-send%2Fblob%2Fmaster%2Finclude%2Fmsinttypes%2Fstdint.h" data-ga-click="(Logged out) Header, clicked Sign in, text:sign-in">Sign in</a> - <span class="text-gray">or</span> - <a class="text-bold text-white no-underline" href="/join?source=header-repo" data-ga-click="(Logged out) Header, clicked Sign up, text:sign-up">Sign up</a> - </div> - </span> - </div> - </div> - </div> -</header> - - - </div> - - <div id="start-of-content" class="show-on-focus"></div> - - <div id="js-flash-container"> -</div> - - - - <div role="main"> - <div itemscope itemtype="http://schema.org/SoftwareSourceCode"> - <div id="js-repo-pjax-container" data-pjax-container> - - - - - - - <div class="pagehead repohead instapaper_ignore readability-menu experiment-repo-nav"> - <div class="container repohead-details-container"> - - <ul class="pagehead-actions"> - <li> - <a href="/login?return_to=%2Fmattn%2Fgntp-send" - class="btn btn-sm btn-with-count tooltipped tooltipped-n" - aria-label="You must be signed in to watch a repository" rel="nofollow"> - <svg aria-hidden="true" class="octicon octicon-eye" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"/></svg> - Watch - </a> - <a class="social-count" href="/mattn/gntp-send/watchers" - aria-label="7 users are watching this repository"> - 7 - </a> - - </li> - - <li> - <a href="/login?return_to=%2Fmattn%2Fgntp-send" - class="btn btn-sm btn-with-count tooltipped tooltipped-n" - aria-label="You must be signed in to star a repository" rel="nofollow"> - <svg aria-hidden="true" class="octicon octicon-star" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path fill-rule="evenodd" d="M14 6l-4.9-.64L7 1 4.9 5.36 0 6l3.6 3.26L2.67 14 7 11.67 11.33 14l-.93-4.74z"/></svg> - Star - </a> - - <a class="social-count js-social-count" href="/mattn/gntp-send/stargazers" - aria-label="44 users starred this repository"> - 44 - </a> - - </li> - - <li> - <a href="/login?return_to=%2Fmattn%2Fgntp-send" - class="btn btn-sm btn-with-count tooltipped tooltipped-n" - aria-label="You must be signed in to fork a repository" rel="nofollow"> - <svg aria-hidden="true" class="octicon octicon-repo-forked" height="16" version="1.1" viewBox="0 0 10 16" width="10"><path fill-rule="evenodd" d="M8 1a1.993 1.993 0 0 0-1 3.72V6L5 8 3 6V4.72A1.993 1.993 0 0 0 2 1a1.993 1.993 0 0 0-1 3.72V6.5l3 3v1.78A1.993 1.993 0 0 0 5 15a1.993 1.993 0 0 0 1-3.72V9.5l3-3V4.72A1.993 1.993 0 0 0 8 1zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3 10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3-10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"/></svg> - Fork - </a> - - <a href="/mattn/gntp-send/network" class="social-count" - aria-label="45 users forked this repository"> - 45 - </a> - </li> -</ul> - - <h1 class="public "> - <svg aria-hidden="true" class="octicon octicon-repo" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"/></svg> - <span class="author" itemprop="author"><a href="/mattn" class="url fn" rel="author">mattn</a></span><!-- ---><span class="path-divider">/</span><!-- ---><strong itemprop="name"><a href="/mattn/gntp-send" data-pjax="#js-repo-pjax-container">gntp-send</a></strong> - -</h1> - - </div> - <div class="container"> - -<nav class="reponav js-repo-nav js-sidenav-container-pjax" - itemscope - itemtype="http://schema.org/BreadcrumbList" - role="navigation" - data-pjax="#js-repo-pjax-container"> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a href="/mattn/gntp-send" class="js-selected-navigation-item selected reponav-item" data-hotkey="g c" data-selected-links="repo_source repo_downloads repo_commits repo_releases repo_tags repo_branches /mattn/gntp-send" itemprop="url"> - <svg aria-hidden="true" class="octicon octicon-code" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path fill-rule="evenodd" d="M9.5 3L8 4.5 11.5 8 8 11.5 9.5 13 14 8 9.5 3zm-5 0L0 8l4.5 5L6 11.5 2.5 8 6 4.5 4.5 3z"/></svg> - <span itemprop="name">Code</span> - <meta itemprop="position" content="1"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a href="/mattn/gntp-send/issues" class="js-selected-navigation-item reponav-item" data-hotkey="g i" data-selected-links="repo_issues repo_labels repo_milestones /mattn/gntp-send/issues" itemprop="url"> - <svg aria-hidden="true" class="octicon octicon-issue-opened" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"/></svg> - <span itemprop="name">Issues</span> - <span class="Counter">1</span> - <meta itemprop="position" content="2"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a href="/mattn/gntp-send/pulls" class="js-selected-navigation-item reponav-item" data-hotkey="g p" data-selected-links="repo_pulls /mattn/gntp-send/pulls" itemprop="url"> - <svg aria-hidden="true" class="octicon octicon-git-pull-request" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M11 11.28V5c-.03-.78-.34-1.47-.94-2.06C9.46 2.35 8.78 2.03 8 2H7V0L4 3l3 3V4h1c.27.02.48.11.69.31.21.2.3.42.31.69v6.28A1.993 1.993 0 0 0 10 15a1.993 1.993 0 0 0 1-3.72zm-1 2.92c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zM4 3c0-1.11-.89-2-2-2a1.993 1.993 0 0 0-1 3.72v6.56A1.993 1.993 0 0 0 2 15a1.993 1.993 0 0 0 1-3.72V4.72c.59-.34 1-.98 1-1.72zm-.8 10c0 .66-.55 1.2-1.2 1.2-.65 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"/></svg> - <span itemprop="name">Pull requests</span> - <span class="Counter">0</span> - <meta itemprop="position" content="3"> -</a> </span> - - <a href="/mattn/gntp-send/projects" class="js-selected-navigation-item reponav-item" data-selected-links="repo_projects new_repo_project repo_project /mattn/gntp-send/projects"> - <svg aria-hidden="true" class="octicon octicon-project" height="16" version="1.1" viewBox="0 0 15 16" width="15"><path fill-rule="evenodd" d="M10 12h3V2h-3v10zm-4-2h3V2H6v8zm-4 4h3V2H2v12zm-1 1h13V1H1v14zM14 0H1a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h13a1 1 0 0 0 1-1V1a1 1 0 0 0-1-1z"/></svg> - Projects - <span class="Counter" >0</span> -</a> - <a href="/mattn/gntp-send/wiki" class="js-selected-navigation-item reponav-item" data-hotkey="g w" data-selected-links="repo_wiki /mattn/gntp-send/wiki"> - <svg aria-hidden="true" class="octicon octicon-book" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M3 5h4v1H3V5zm0 3h4V7H3v1zm0 2h4V9H3v1zm11-5h-4v1h4V5zm0 2h-4v1h4V7zm0 2h-4v1h4V9zm2-6v9c0 .55-.45 1-1 1H9.5l-1 1-1-1H2c-.55 0-1-.45-1-1V3c0-.55.45-1 1-1h5.5l1 1 1-1H15c.55 0 1 .45 1 1zm-8 .5L7.5 3H2v9h6V3.5zm7-.5H9.5l-.5.5V12h6V3z"/></svg> - Wiki -</a> - - <div class="reponav-dropdown js-menu-container"> - <button type="button" class="btn-link reponav-item reponav-dropdown js-menu-target " data-no-toggle aria-expanded="false" aria-haspopup="true"> - Insights - <svg aria-hidden="true" class="octicon octicon-triangle-down v-align-middle text-gray" height="11" version="1.1" viewBox="0 0 12 16" width="8"><path fill-rule="evenodd" d="M0 5l6 6 6-6z"/></svg> - </button> - <div class="dropdown-menu-content js-menu-content"> - <div class="dropdown-menu dropdown-menu-sw"> - <a class="dropdown-item" href="/mattn/gntp-send/pulse" data-skip-pjax> - <svg aria-hidden="true" class="octicon octicon-pulse" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path fill-rule="evenodd" d="M11.5 8L8.8 5.4 6.6 8.5 5.5 1.6 2.38 8H0v2h3.6l.9-1.8.9 5.4L9 8.5l1.6 1.5H14V8z"/></svg> - Pulse - </a> - <a class="dropdown-item" href="/mattn/gntp-send/graphs" data-skip-pjax> - <svg aria-hidden="true" class="octicon octicon-graph" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M16 14v1H0V0h1v14h15zM5 13H3V8h2v5zm4 0H7V3h2v10zm4 0h-2V6h2v7z"/></svg> - Graphs - </a> - </div> - </div> - </div> -</nav> - - </div> - </div> - -<div class="container new-discussion-timeline experiment-repo-nav"> - <div class="repository-content"> - - - <a href="/mattn/gntp-send/blob/090b1276fb4a30601113551bed88c58329646818/include/msinttypes/stdint.h" class="d-none js-permalink-shortcut" data-hotkey="y">Permalink</a> - - <!-- blob contrib key: blob_contributors:v21:1fdd18f08c206edbaba4a5b47a34cc57 --> - - <div class="file-navigation js-zeroclipboard-container"> - -<div class="select-menu branch-select-menu js-menu-container js-select-menu float-left"> - <button class=" btn btn-sm select-menu-button js-menu-target css-truncate" data-hotkey="w" - - type="button" aria-label="Switch branches or tags" aria-expanded="false" aria-haspopup="true"> - <i>Branch:</i> - <span class="js-select-button css-truncate-target">master</span> - </button> - - <div class="select-menu-modal-holder js-menu-content js-navigation-container" data-pjax> - - <div class="select-menu-modal"> - <div class="select-menu-header"> - <svg aria-label="Close" class="octicon octicon-x js-menu-close" height="16" role="img" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"/></svg> - <span class="select-menu-title">Switch branches/tags</span> - </div> - - <div class="select-menu-filters"> - <div class="select-menu-text-filter"> - <input type="text" aria-label="Filter branches/tags" id="context-commitish-filter-field" class="form-control js-filterable-field js-navigation-enable" placeholder="Filter branches/tags"> - </div> - <div class="select-menu-tabs"> - <ul> - <li class="select-menu-tab"> - <a href="#" data-tab-filter="branches" data-filter-placeholder="Filter branches/tags" class="js-select-menu-tab" role="tab">Branches</a> - </li> - <li class="select-menu-tab"> - <a href="#" data-tab-filter="tags" data-filter-placeholder="Find a tag…" class="js-select-menu-tab" role="tab">Tags</a> - </li> - </ul> - </div> - </div> - - <div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="branches" role="menu"> - - <div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring"> - - - <a class="select-menu-item js-navigation-item js-navigation-open selected" - href="/mattn/gntp-send/blob/master/include/msinttypes/stdint.h" - data-name="master" - data-skip-pjax="true" - rel="nofollow"> - <svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"/></svg> - <span class="select-menu-item-text css-truncate-target js-select-menu-filter-text"> - master - </span> - </a> - </div> - - <div class="select-menu-no-results">Nothing to show</div> - </div> - - <div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="tags"> - <div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring"> - - - <a class="select-menu-item js-navigation-item js-navigation-open " - href="/mattn/gntp-send/tree/0.3.4/include/msinttypes/stdint.h" - data-name="0.3.4" - data-skip-pjax="true" - rel="nofollow"> - <svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"/></svg> - <span class="select-menu-item-text css-truncate-target" title="0.3.4"> - 0.3.4 - </span> - </a> - </div> - - <div class="select-menu-no-results">Nothing to show</div> - </div> - - </div> - </div> -</div> - - <div class="BtnGroup float-right"> - <a href="/mattn/gntp-send/find/master" - class="js-pjax-capture-input btn btn-sm BtnGroup-item" - data-pjax - data-hotkey="t"> - Find file - </a> - <button aria-label="Copy file path to clipboard" class="js-zeroclipboard btn btn-sm BtnGroup-item tooltipped tooltipped-s" data-copied-hint="Copied!" type="button">Copy path</button> - </div> - <div class="breadcrumb js-zeroclipboard-target"> - <span class="repo-root js-repo-root"><span class="js-path-segment"><a href="/mattn/gntp-send"><span>gntp-send</span></a></span></span><span class="separator">/</span><span class="js-path-segment"><a href="/mattn/gntp-send/tree/master/include"><span>include</span></a></span><span class="separator">/</span><span class="js-path-segment"><a href="/mattn/gntp-send/tree/master/include/msinttypes"><span>msinttypes</span></a></span><span class="separator">/</span><strong class="final-path">stdint.h</strong> - </div> - </div> - - - - <div class="commit-tease"> - <span class="float-right"> - <a class="commit-tease-sha" href="/mattn/gntp-send/commit/700f4a2d844001a6197d68440a9123f197be6096" data-pjax> - 700f4a2 - </a> - <relative-time datetime="2011-10-06T00:28:08Z">Oct 6, 2011</relative-time> - </span> - <div> - <img alt="@mattn" class="avatar" height="20" src="https://avatars1.githubusercontent.com/u/10111?v=4&s=40" width="20" /> - <a href="/mattn" class="user-mention" rel="author">mattn</a> - <a href="/mattn/gntp-send/commit/700f4a2d844001a6197d68440a9123f197be6096" class="message" data-pjax="true" title="perfer include/src name.">perfer include/src name.</a> - </div> - - <div class="commit-tease-contributors"> - <button type="button" class="btn-link muted-link contributors-toggle" data-facebox="#blob_contributors_box"> - <strong>1</strong> - contributor - </button> - - </div> - - <div id="blob_contributors_box" style="display:none"> - <h2 class="facebox-header" data-facebox-id="facebox-header">Users who have contributed to this file</h2> - <ul class="facebox-user-list" data-facebox-id="facebox-description"> - <li class="facebox-user-list-item"> - <img alt="@mattn" height="24" src="https://avatars3.githubusercontent.com/u/10111?v=4&s=48" width="24" /> - <a href="/mattn">mattn</a> - </li> - </ul> - </div> - </div> - - - <div class="file"> - <div class="file-header"> - <div class="file-actions"> - - <div class="BtnGroup"> - <a href="/mattn/gntp-send/raw/master/include/msinttypes/stdint.h" class="btn btn-sm BtnGroup-item" id="raw-url">Raw</a> - <a href="/mattn/gntp-send/blame/master/include/msinttypes/stdint.h" class="btn btn-sm js-update-url-with-hash BtnGroup-item" data-hotkey="b">Blame</a> - <a href="/mattn/gntp-send/commits/master/include/msinttypes/stdint.h" class="btn btn-sm BtnGroup-item" rel="nofollow">History</a> - </div> - - <a class="btn-octicon tooltipped tooltipped-nw" - href="https://desktop.github.com" - aria-label="Open this file in GitHub Desktop" - data-ga-click="Repository, open with desktop, type:windows"> - <svg aria-hidden="true" class="octicon octicon-device-desktop" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M15 2H1c-.55 0-1 .45-1 1v9c0 .55.45 1 1 1h5.34c-.25.61-.86 1.39-2.34 2h8c-1.48-.61-2.09-1.39-2.34-2H15c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm0 9H1V3h14v8z"/></svg> - </a> - - <button type="button" class="btn-octicon disabled tooltipped tooltipped-nw" - aria-label="You must be signed in to make or propose changes"> - <svg aria-hidden="true" class="octicon octicon-pencil" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path fill-rule="evenodd" d="M0 12v3h3l8-8-3-3-8 8zm3 2H1v-2h1v1h1v1zm10.3-9.3L12 6 9 3l1.3-1.3a.996.996 0 0 1 1.41 0l1.59 1.59c.39.39.39 1.02 0 1.41z"/></svg> - </button> - <button type="button" class="btn-octicon btn-octicon-danger disabled tooltipped tooltipped-nw" - aria-label="You must be signed in to make or propose changes"> - <svg aria-hidden="true" class="octicon octicon-trashcan" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M11 2H9c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1H2c-.55 0-1 .45-1 1v1c0 .55.45 1 1 1v9c0 .55.45 1 1 1h7c.55 0 1-.45 1-1V5c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm-1 12H3V5h1v8h1V5h1v8h1V5h1v8h1V5h1v9zm1-10H2V3h9v1z"/></svg> - </button> - </div> - - <div class="file-info"> - 248 lines (207 sloc) - <span class="file-info-divider"></span> - 7.55 KB - </div> -</div> - - - - <div itemprop="text" class="blob-wrapper data type-c"> - <table class="highlight tab-size js-file-line-container" data-tab-size="8"> - <tr> - <td id="L1" class="blob-num js-line-number" data-line-number="1"></td> - <td id="LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> ISO C9x compliant stdint.h for Microsoft Visual Studio</span></td> - </tr> - <tr> - <td id="L2" class="blob-num js-line-number" data-line-number="2"></td> - <td id="LC2" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 </span></td> - </tr> - <tr> - <td id="L3" class="blob-num js-line-number" data-line-number="3"></td> - <td id="LC3" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> </span></td> - </tr> - <tr> - <td id="L4" class="blob-num js-line-number" data-line-number="4"></td> - <td id="LC4" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> Copyright (c) 2006-2008 Alexander Chemeris</span></td> - </tr> - <tr> - <td id="L5" class="blob-num js-line-number" data-line-number="5"></td> - <td id="LC5" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> </span></td> - </tr> - <tr> - <td id="L6" class="blob-num js-line-number" data-line-number="6"></td> - <td id="LC6" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> Redistribution and use in source and binary forms, with or without</span></td> - </tr> - <tr> - <td id="L7" class="blob-num js-line-number" data-line-number="7"></td> - <td id="LC7" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> modification, are permitted provided that the following conditions are met:</span></td> - </tr> - <tr> - <td id="L8" class="blob-num js-line-number" data-line-number="8"></td> - <td id="LC8" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> </span></td> - </tr> - <tr> - <td id="L9" class="blob-num js-line-number" data-line-number="9"></td> - <td id="LC9" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 1. Redistributions of source code must retain the above copyright notice,</span></td> - </tr> - <tr> - <td id="L10" class="blob-num js-line-number" data-line-number="10"></td> - <td id="LC10" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> this list of conditions and the following disclaimer.</span></td> - </tr> - <tr> - <td id="L11" class="blob-num js-line-number" data-line-number="11"></td> - <td id="LC11" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> </span></td> - </tr> - <tr> - <td id="L12" class="blob-num js-line-number" data-line-number="12"></td> - <td id="LC12" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 2. Redistributions in binary form must reproduce the above copyright</span></td> - </tr> - <tr> - <td id="L13" class="blob-num js-line-number" data-line-number="13"></td> - <td id="LC13" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> notice, this list of conditions and the following disclaimer in the</span></td> - </tr> - <tr> - <td id="L14" class="blob-num js-line-number" data-line-number="14"></td> - <td id="LC14" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> documentation and/or other materials provided with the distribution.</span></td> - </tr> - <tr> - <td id="L15" class="blob-num js-line-number" data-line-number="15"></td> - <td id="LC15" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> </span></td> - </tr> - <tr> - <td id="L16" class="blob-num js-line-number" data-line-number="16"></td> - <td id="LC16" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 3. The name of the author may be used to endorse or promote products</span></td> - </tr> - <tr> - <td id="L17" class="blob-num js-line-number" data-line-number="17"></td> - <td id="LC17" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> derived from this software without specific prior written permission.</span></td> - </tr> - <tr> - <td id="L18" class="blob-num js-line-number" data-line-number="18"></td> - <td id="LC18" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> </span></td> - </tr> - <tr> - <td id="L19" class="blob-num js-line-number" data-line-number="19"></td> - <td id="LC19" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED</span></td> - </tr> - <tr> - <td id="L20" class="blob-num js-line-number" data-line-number="20"></td> - <td id="LC20" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF</span></td> - </tr> - <tr> - <td id="L21" class="blob-num js-line-number" data-line-number="21"></td> - <td id="LC21" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO</span></td> - </tr> - <tr> - <td id="L22" class="blob-num js-line-number" data-line-number="22"></td> - <td id="LC22" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,</span></td> - </tr> - <tr> - <td id="L23" class="blob-num js-line-number" data-line-number="23"></td> - <td id="LC23" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,</span></td> - </tr> - <tr> - <td id="L24" class="blob-num js-line-number" data-line-number="24"></td> - <td id="LC24" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;</span></td> - </tr> - <tr> - <td id="L25" class="blob-num js-line-number" data-line-number="25"></td> - <td id="LC25" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, </span></td> - </tr> - <tr> - <td id="L26" class="blob-num js-line-number" data-line-number="26"></td> - <td id="LC26" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR</span></td> - </tr> - <tr> - <td id="L27" class="blob-num js-line-number" data-line-number="27"></td> - <td id="LC27" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF</span></td> - </tr> - <tr> - <td id="L28" class="blob-num js-line-number" data-line-number="28"></td> - <td id="LC28" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span></td> - </tr> - <tr> - <td id="L29" class="blob-num js-line-number" data-line-number="29"></td> - <td id="LC29" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> </span></td> - </tr> - <tr> - <td id="L30" class="blob-num js-line-number" data-line-number="30"></td> - <td id="LC30" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span>/////////////////////////////////////////////////////////////////////////////</span></td> - </tr> - <tr> - <td id="L31" class="blob-num js-line-number" data-line-number="31"></td> - <td id="LC31" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L32" class="blob-num js-line-number" data-line-number="32"></td> - <td id="LC32" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">ifndef</span> _MSC_VER <span class="pl-c"><span class="pl-c">//</span> [</span></td> - </tr> - <tr> - <td id="L33" class="blob-num js-line-number" data-line-number="33"></td> - <td id="LC33" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">error</span> "Use this header only with Microsoft Visual C++ compilers!"</td> - </tr> - <tr> - <td id="L34" class="blob-num js-line-number" data-line-number="34"></td> - <td id="LC34" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">endif</span> <span class="pl-c"><span class="pl-c">//</span> _MSC_VER ]</span></td> - </tr> - <tr> - <td id="L35" class="blob-num js-line-number" data-line-number="35"></td> - <td id="LC35" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L36" class="blob-num js-line-number" data-line-number="36"></td> - <td id="LC36" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">ifndef</span> _MSC_STDINT_H_ <span class="pl-c"><span class="pl-c">//</span> [</span></td> - </tr> - <tr> - <td id="L37" class="blob-num js-line-number" data-line-number="37"></td> - <td id="LC37" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">_MSC_STDINT_H_</span></td> - </tr> - <tr> - <td id="L38" class="blob-num js-line-number" data-line-number="38"></td> - <td id="LC38" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L39" class="blob-num js-line-number" data-line-number="39"></td> - <td id="LC39" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">if</span> _MSC_VER > 1000</td> - </tr> - <tr> - <td id="L40" class="blob-num js-line-number" data-line-number="40"></td> - <td id="LC40" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">pragma</span> once</td> - </tr> - <tr> - <td id="L41" class="blob-num js-line-number" data-line-number="41"></td> - <td id="LC41" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">endif</span></td> - </tr> - <tr> - <td id="L42" class="blob-num js-line-number" data-line-number="42"></td> - <td id="LC42" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L43" class="blob-num js-line-number" data-line-number="43"></td> - <td id="LC43" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">include</span> <span class="pl-s"><span class="pl-pds"><</span>limits.h<span class="pl-pds">></span></span></td> - </tr> - <tr> - <td id="L44" class="blob-num js-line-number" data-line-number="44"></td> - <td id="LC44" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L45" class="blob-num js-line-number" data-line-number="45"></td> - <td id="LC45" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> For Visual Studio 6 in C++ mode and for many Visual Studio versions when</span></td> - </tr> - <tr> - <td id="L46" class="blob-num js-line-number" data-line-number="46"></td> - <td id="LC46" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'</span></td> - </tr> - <tr> - <td id="L47" class="blob-num js-line-number" data-line-number="47"></td> - <td id="LC47" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> or compiler give many errors like this:</span></td> - </tr> - <tr> - <td id="L48" class="blob-num js-line-number" data-line-number="48"></td> - <td id="LC48" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> error C2733: second C linkage of overloaded function 'wmemchr' not allowed</span></td> - </tr> - <tr> - <td id="L49" class="blob-num js-line-number" data-line-number="49"></td> - <td id="LC49" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">ifdef</span> __cplusplus</td> - </tr> - <tr> - <td id="L50" class="blob-num js-line-number" data-line-number="50"></td> - <td id="LC50" class="blob-code blob-code-inner js-file-line"><span class="pl-k">extern</span> <span class="pl-s"><span class="pl-pds">"</span>C<span class="pl-pds">"</span></span> {</td> - </tr> - <tr> - <td id="L51" class="blob-num js-line-number" data-line-number="51"></td> - <td id="LC51" class="blob-code blob-code-inner js-file-line">#endif</td> - </tr> - <tr> - <td id="L52" class="blob-num js-line-number" data-line-number="52"></td> - <td id="LC52" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">include</span> <span class="pl-s"><span class="pl-pds"><</span>wchar.h<span class="pl-pds">></span></span></td> - </tr> - <tr> - <td id="L53" class="blob-num js-line-number" data-line-number="53"></td> - <td id="LC53" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">ifdef</span> __cplusplus</td> - </tr> - <tr> - <td id="L54" class="blob-num js-line-number" data-line-number="54"></td> - <td id="LC54" class="blob-code blob-code-inner js-file-line">}</td> - </tr> - <tr> - <td id="L55" class="blob-num js-line-number" data-line-number="55"></td> - <td id="LC55" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">endif</span></td> - </tr> - <tr> - <td id="L56" class="blob-num js-line-number" data-line-number="56"></td> - <td id="LC56" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L57" class="blob-num js-line-number" data-line-number="57"></td> - <td id="LC57" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> Define _W64 macros to mark types changing their size, like intptr_t.</span></td> - </tr> - <tr> - <td id="L58" class="blob-num js-line-number" data-line-number="58"></td> - <td id="LC58" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">ifndef</span> _W64</td> - </tr> - <tr> - <td id="L59" class="blob-num js-line-number" data-line-number="59"></td> - <td id="LC59" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">if</span> !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300</td> - </tr> - <tr> - <td id="L60" class="blob-num js-line-number" data-line-number="60"></td> - <td id="LC60" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">define</span> <span class="pl-en">_W64</span> __w64</td> - </tr> - <tr> - <td id="L61" class="blob-num js-line-number" data-line-number="61"></td> - <td id="LC61" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">else</span></td> - </tr> - <tr> - <td id="L62" class="blob-num js-line-number" data-line-number="62"></td> - <td id="LC62" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">define</span> <span class="pl-en">_W64</span></td> - </tr> - <tr> - <td id="L63" class="blob-num js-line-number" data-line-number="63"></td> - <td id="LC63" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">endif</span></td> - </tr> - <tr> - <td id="L64" class="blob-num js-line-number" data-line-number="64"></td> - <td id="LC64" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">endif</span></td> - </tr> - <tr> - <td id="L65" class="blob-num js-line-number" data-line-number="65"></td> - <td id="LC65" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L66" class="blob-num js-line-number" data-line-number="66"></td> - <td id="LC66" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L67" class="blob-num js-line-number" data-line-number="67"></td> - <td id="LC67" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 7.18.1 Integer types</span></td> - </tr> - <tr> - <td id="L68" class="blob-num js-line-number" data-line-number="68"></td> - <td id="LC68" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L69" class="blob-num js-line-number" data-line-number="69"></td> - <td id="LC69" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 7.18.1.1 Exact-width integer types</span></td> - </tr> - <tr> - <td id="L70" class="blob-num js-line-number" data-line-number="70"></td> - <td id="LC70" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L71" class="blob-num js-line-number" data-line-number="71"></td> - <td id="LC71" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> Visual Studio 6 and Embedded Visual C++ 4 doesn't</span></td> - </tr> - <tr> - <td id="L72" class="blob-num js-line-number" data-line-number="72"></td> - <td id="LC72" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> realize that, e.g. char has the same size as __int8</span></td> - </tr> - <tr> - <td id="L73" class="blob-num js-line-number" data-line-number="73"></td> - <td id="LC73" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> so we give up on __intX for them.</span></td> - </tr> - <tr> - <td id="L74" class="blob-num js-line-number" data-line-number="74"></td> - <td id="LC74" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">if</span> (_MSC_VER < 1300)</td> - </tr> - <tr> - <td id="L75" class="blob-num js-line-number" data-line-number="75"></td> - <td id="LC75" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">typedef</span> <span class="pl-k">signed</span> <span class="pl-k">char</span> <span class="pl-c1">int8_t</span>;</td> - </tr> - <tr> - <td id="L76" class="blob-num js-line-number" data-line-number="76"></td> - <td id="LC76" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">typedef</span> <span class="pl-k">signed</span> <span class="pl-k">short</span> <span class="pl-c1">int16_t</span>;</td> - </tr> - <tr> - <td id="L77" class="blob-num js-line-number" data-line-number="77"></td> - <td id="LC77" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">typedef</span> <span class="pl-k">signed</span> <span class="pl-k">int</span> <span class="pl-c1">int32_t</span>;</td> - </tr> - <tr> - <td id="L78" class="blob-num js-line-number" data-line-number="78"></td> - <td id="LC78" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">typedef</span> <span class="pl-k">unsigned</span> <span class="pl-k">char</span> <span class="pl-c1">uint8_t</span>;</td> - </tr> - <tr> - <td id="L79" class="blob-num js-line-number" data-line-number="79"></td> - <td id="LC79" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">typedef</span> <span class="pl-k">unsigned</span> <span class="pl-k">short</span> <span class="pl-c1">uint16_t</span>;</td> - </tr> - <tr> - <td id="L80" class="blob-num js-line-number" data-line-number="80"></td> - <td id="LC80" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">typedef</span> <span class="pl-k">unsigned</span> <span class="pl-k">int</span> <span class="pl-c1">uint32_t</span>;</td> - </tr> - <tr> - <td id="L81" class="blob-num js-line-number" data-line-number="81"></td> - <td id="LC81" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">else</span></td> - </tr> - <tr> - <td id="L82" class="blob-num js-line-number" data-line-number="82"></td> - <td id="LC82" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">typedef</span> <span class="pl-k">signed</span> __int8 <span class="pl-c1">int8_t</span>;</td> - </tr> - <tr> - <td id="L83" class="blob-num js-line-number" data-line-number="83"></td> - <td id="LC83" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">typedef</span> <span class="pl-k">signed</span> __int16 <span class="pl-c1">int16_t</span>;</td> - </tr> - <tr> - <td id="L84" class="blob-num js-line-number" data-line-number="84"></td> - <td id="LC84" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">typedef</span> <span class="pl-k">signed</span> __int32 <span class="pl-c1">int32_t</span>;</td> - </tr> - <tr> - <td id="L85" class="blob-num js-line-number" data-line-number="85"></td> - <td id="LC85" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">typedef</span> <span class="pl-k">unsigned</span> __int8 <span class="pl-c1">uint8_t</span>;</td> - </tr> - <tr> - <td id="L86" class="blob-num js-line-number" data-line-number="86"></td> - <td id="LC86" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">typedef</span> <span class="pl-k">unsigned</span> __int16 <span class="pl-c1">uint16_t</span>;</td> - </tr> - <tr> - <td id="L87" class="blob-num js-line-number" data-line-number="87"></td> - <td id="LC87" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">typedef</span> <span class="pl-k">unsigned</span> __int32 <span class="pl-c1">uint32_t</span>;</td> - </tr> - <tr> - <td id="L88" class="blob-num js-line-number" data-line-number="88"></td> - <td id="LC88" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">endif</span></td> - </tr> - <tr> - <td id="L89" class="blob-num js-line-number" data-line-number="89"></td> - <td id="LC89" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-k">signed</span> __int64 <span class="pl-c1">int64_t</span>;</td> - </tr> - <tr> - <td id="L90" class="blob-num js-line-number" data-line-number="90"></td> - <td id="LC90" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-k">unsigned</span> __int64 <span class="pl-c1">uint64_t</span>;</td> - </tr> - <tr> - <td id="L91" class="blob-num js-line-number" data-line-number="91"></td> - <td id="LC91" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L92" class="blob-num js-line-number" data-line-number="92"></td> - <td id="LC92" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L93" class="blob-num js-line-number" data-line-number="93"></td> - <td id="LC93" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 7.18.1.2 Minimum-width integer types</span></td> - </tr> - <tr> - <td id="L94" class="blob-num js-line-number" data-line-number="94"></td> - <td id="LC94" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-c1">int8_t</span> <span class="pl-c1">int_least8_t</span>;</td> - </tr> - <tr> - <td id="L95" class="blob-num js-line-number" data-line-number="95"></td> - <td id="LC95" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-c1">int16_t</span> <span class="pl-c1">int_least16_t</span>;</td> - </tr> - <tr> - <td id="L96" class="blob-num js-line-number" data-line-number="96"></td> - <td id="LC96" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-c1">int32_t</span> <span class="pl-c1">int_least32_t</span>;</td> - </tr> - <tr> - <td id="L97" class="blob-num js-line-number" data-line-number="97"></td> - <td id="LC97" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-c1">int64_t</span> <span class="pl-c1">int_least64_t</span>;</td> - </tr> - <tr> - <td id="L98" class="blob-num js-line-number" data-line-number="98"></td> - <td id="LC98" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-c1">uint8_t</span> <span class="pl-c1">uint_least8_t</span>;</td> - </tr> - <tr> - <td id="L99" class="blob-num js-line-number" data-line-number="99"></td> - <td id="LC99" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-c1">uint16_t</span> <span class="pl-c1">uint_least16_t</span>;</td> - </tr> - <tr> - <td id="L100" class="blob-num js-line-number" data-line-number="100"></td> - <td id="LC100" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-c1">uint32_t</span> <span class="pl-c1">uint_least32_t</span>;</td> - </tr> - <tr> - <td id="L101" class="blob-num js-line-number" data-line-number="101"></td> - <td id="LC101" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-c1">uint64_t</span> <span class="pl-c1">uint_least64_t</span>;</td> - </tr> - <tr> - <td id="L102" class="blob-num js-line-number" data-line-number="102"></td> - <td id="LC102" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L103" class="blob-num js-line-number" data-line-number="103"></td> - <td id="LC103" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 7.18.1.3 Fastest minimum-width integer types</span></td> - </tr> - <tr> - <td id="L104" class="blob-num js-line-number" data-line-number="104"></td> - <td id="LC104" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-c1">int8_t</span> <span class="pl-c1">int_fast8_t</span>;</td> - </tr> - <tr> - <td id="L105" class="blob-num js-line-number" data-line-number="105"></td> - <td id="LC105" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-c1">int16_t</span> <span class="pl-c1">int_fast16_t</span>;</td> - </tr> - <tr> - <td id="L106" class="blob-num js-line-number" data-line-number="106"></td> - <td id="LC106" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-c1">int32_t</span> <span class="pl-c1">int_fast32_t</span>;</td> - </tr> - <tr> - <td id="L107" class="blob-num js-line-number" data-line-number="107"></td> - <td id="LC107" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-c1">int64_t</span> <span class="pl-c1">int_fast64_t</span>;</td> - </tr> - <tr> - <td id="L108" class="blob-num js-line-number" data-line-number="108"></td> - <td id="LC108" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-c1">uint8_t</span> <span class="pl-c1">uint_fast8_t</span>;</td> - </tr> - <tr> - <td id="L109" class="blob-num js-line-number" data-line-number="109"></td> - <td id="LC109" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-c1">uint16_t</span> <span class="pl-c1">uint_fast16_t</span>;</td> - </tr> - <tr> - <td id="L110" class="blob-num js-line-number" data-line-number="110"></td> - <td id="LC110" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-c1">uint32_t</span> <span class="pl-c1">uint_fast32_t</span>;</td> - </tr> - <tr> - <td id="L111" class="blob-num js-line-number" data-line-number="111"></td> - <td id="LC111" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-c1">uint64_t</span> <span class="pl-c1">uint_fast64_t</span>;</td> - </tr> - <tr> - <td id="L112" class="blob-num js-line-number" data-line-number="112"></td> - <td id="LC112" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L113" class="blob-num js-line-number" data-line-number="113"></td> - <td id="LC113" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 7.18.1.4 Integer types capable of holding object pointers</span></td> - </tr> - <tr> - <td id="L114" class="blob-num js-line-number" data-line-number="114"></td> - <td id="LC114" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">ifdef</span> _WIN64 <span class="pl-c"><span class="pl-c">//</span> [</span></td> - </tr> - <tr> - <td id="L115" class="blob-num js-line-number" data-line-number="115"></td> - <td id="LC115" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">typedef</span> <span class="pl-k">signed</span> __int64 <span class="pl-c1">intptr_t</span>;</td> - </tr> - <tr> - <td id="L116" class="blob-num js-line-number" data-line-number="116"></td> - <td id="LC116" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">typedef</span> <span class="pl-k">unsigned</span> __int64 <span class="pl-c1">uintptr_t</span>;</td> - </tr> - <tr> - <td id="L117" class="blob-num js-line-number" data-line-number="117"></td> - <td id="LC117" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">else</span> <span class="pl-c"><span class="pl-c">//</span> _WIN64 ][</span></td> - </tr> - <tr> - <td id="L118" class="blob-num js-line-number" data-line-number="118"></td> - <td id="LC118" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">typedef</span> _W64 <span class="pl-k">signed</span> <span class="pl-k">int</span> <span class="pl-c1">intptr_t</span>;</td> - </tr> - <tr> - <td id="L119" class="blob-num js-line-number" data-line-number="119"></td> - <td id="LC119" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">typedef</span> _W64 <span class="pl-k">unsigned</span> <span class="pl-k">int</span> <span class="pl-c1">uintptr_t</span>;</td> - </tr> - <tr> - <td id="L120" class="blob-num js-line-number" data-line-number="120"></td> - <td id="LC120" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">endif</span> <span class="pl-c"><span class="pl-c">//</span> _WIN64 ]</span></td> - </tr> - <tr> - <td id="L121" class="blob-num js-line-number" data-line-number="121"></td> - <td id="LC121" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L122" class="blob-num js-line-number" data-line-number="122"></td> - <td id="LC122" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 7.18.1.5 Greatest-width integer types</span></td> - </tr> - <tr> - <td id="L123" class="blob-num js-line-number" data-line-number="123"></td> - <td id="LC123" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-c1">int64_t</span> <span class="pl-c1">intmax_t</span>;</td> - </tr> - <tr> - <td id="L124" class="blob-num js-line-number" data-line-number="124"></td> - <td id="LC124" class="blob-code blob-code-inner js-file-line"><span class="pl-k">typedef</span> <span class="pl-c1">uint64_t</span> <span class="pl-c1">uintmax_t</span>;</td> - </tr> - <tr> - <td id="L125" class="blob-num js-line-number" data-line-number="125"></td> - <td id="LC125" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L126" class="blob-num js-line-number" data-line-number="126"></td> - <td id="LC126" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L127" class="blob-num js-line-number" data-line-number="127"></td> - <td id="LC127" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 7.18.2 Limits of specified-width integer types</span></td> - </tr> - <tr> - <td id="L128" class="blob-num js-line-number" data-line-number="128"></td> - <td id="LC128" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L129" class="blob-num js-line-number" data-line-number="129"></td> - <td id="LC129" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">if</span> !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) <span class="pl-c"><span class="pl-c">//</span> [ See footnote 220 at page 257 and footnote 221 at page 259</span></td> - </tr> - <tr> - <td id="L130" class="blob-num js-line-number" data-line-number="130"></td> - <td id="LC130" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L131" class="blob-num js-line-number" data-line-number="131"></td> - <td id="LC131" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 7.18.2.1 Limits of exact-width integer types</span></td> - </tr> - <tr> - <td id="L132" class="blob-num js-line-number" data-line-number="132"></td> - <td id="LC132" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT8_MIN</span> ((<span class="pl-c1">int8_t</span>)_I8_MIN)</td> - </tr> - <tr> - <td id="L133" class="blob-num js-line-number" data-line-number="133"></td> - <td id="LC133" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT8_MAX</span> _I8_MAX</td> - </tr> - <tr> - <td id="L134" class="blob-num js-line-number" data-line-number="134"></td> - <td id="LC134" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT16_MIN</span> ((<span class="pl-c1">int16_t</span>)_I16_MIN)</td> - </tr> - <tr> - <td id="L135" class="blob-num js-line-number" data-line-number="135"></td> - <td id="LC135" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT16_MAX</span> _I16_MAX</td> - </tr> - <tr> - <td id="L136" class="blob-num js-line-number" data-line-number="136"></td> - <td id="LC136" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT32_MIN</span> ((<span class="pl-c1">int32_t</span>)_I32_MIN)</td> - </tr> - <tr> - <td id="L137" class="blob-num js-line-number" data-line-number="137"></td> - <td id="LC137" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT32_MAX</span> _I32_MAX</td> - </tr> - <tr> - <td id="L138" class="blob-num js-line-number" data-line-number="138"></td> - <td id="LC138" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT64_MIN</span> ((<span class="pl-c1">int64_t</span>)_I64_MIN)</td> - </tr> - <tr> - <td id="L139" class="blob-num js-line-number" data-line-number="139"></td> - <td id="LC139" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT64_MAX</span> _I64_MAX</td> - </tr> - <tr> - <td id="L140" class="blob-num js-line-number" data-line-number="140"></td> - <td id="LC140" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">UINT8_MAX</span> _UI8_MAX</td> - </tr> - <tr> - <td id="L141" class="blob-num js-line-number" data-line-number="141"></td> - <td id="LC141" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">UINT16_MAX</span> _UI16_MAX</td> - </tr> - <tr> - <td id="L142" class="blob-num js-line-number" data-line-number="142"></td> - <td id="LC142" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">UINT32_MAX</span> _UI32_MAX</td> - </tr> - <tr> - <td id="L143" class="blob-num js-line-number" data-line-number="143"></td> - <td id="LC143" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">UINT64_MAX</span> _UI64_MAX</td> - </tr> - <tr> - <td id="L144" class="blob-num js-line-number" data-line-number="144"></td> - <td id="LC144" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L145" class="blob-num js-line-number" data-line-number="145"></td> - <td id="LC145" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 7.18.2.2 Limits of minimum-width integer types</span></td> - </tr> - <tr> - <td id="L146" class="blob-num js-line-number" data-line-number="146"></td> - <td id="LC146" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT_LEAST8_MIN</span> INT8_MIN</td> - </tr> - <tr> - <td id="L147" class="blob-num js-line-number" data-line-number="147"></td> - <td id="LC147" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT_LEAST8_MAX</span> INT8_MAX</td> - </tr> - <tr> - <td id="L148" class="blob-num js-line-number" data-line-number="148"></td> - <td id="LC148" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT_LEAST16_MIN</span> INT16_MIN</td> - </tr> - <tr> - <td id="L149" class="blob-num js-line-number" data-line-number="149"></td> - <td id="LC149" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT_LEAST16_MAX</span> INT16_MAX</td> - </tr> - <tr> - <td id="L150" class="blob-num js-line-number" data-line-number="150"></td> - <td id="LC150" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT_LEAST32_MIN</span> INT32_MIN</td> - </tr> - <tr> - <td id="L151" class="blob-num js-line-number" data-line-number="151"></td> - <td id="LC151" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT_LEAST32_MAX</span> INT32_MAX</td> - </tr> - <tr> - <td id="L152" class="blob-num js-line-number" data-line-number="152"></td> - <td id="LC152" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT_LEAST64_MIN</span> INT64_MIN</td> - </tr> - <tr> - <td id="L153" class="blob-num js-line-number" data-line-number="153"></td> - <td id="LC153" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT_LEAST64_MAX</span> INT64_MAX</td> - </tr> - <tr> - <td id="L154" class="blob-num js-line-number" data-line-number="154"></td> - <td id="LC154" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">UINT_LEAST8_MAX</span> UINT8_MAX</td> - </tr> - <tr> - <td id="L155" class="blob-num js-line-number" data-line-number="155"></td> - <td id="LC155" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">UINT_LEAST16_MAX</span> UINT16_MAX</td> - </tr> - <tr> - <td id="L156" class="blob-num js-line-number" data-line-number="156"></td> - <td id="LC156" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">UINT_LEAST32_MAX</span> UINT32_MAX</td> - </tr> - <tr> - <td id="L157" class="blob-num js-line-number" data-line-number="157"></td> - <td id="LC157" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">UINT_LEAST64_MAX</span> UINT64_MAX</td> - </tr> - <tr> - <td id="L158" class="blob-num js-line-number" data-line-number="158"></td> - <td id="LC158" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L159" class="blob-num js-line-number" data-line-number="159"></td> - <td id="LC159" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 7.18.2.3 Limits of fastest minimum-width integer types</span></td> - </tr> - <tr> - <td id="L160" class="blob-num js-line-number" data-line-number="160"></td> - <td id="LC160" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT_FAST8_MIN</span> INT8_MIN</td> - </tr> - <tr> - <td id="L161" class="blob-num js-line-number" data-line-number="161"></td> - <td id="LC161" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT_FAST8_MAX</span> INT8_MAX</td> - </tr> - <tr> - <td id="L162" class="blob-num js-line-number" data-line-number="162"></td> - <td id="LC162" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT_FAST16_MIN</span> INT16_MIN</td> - </tr> - <tr> - <td id="L163" class="blob-num js-line-number" data-line-number="163"></td> - <td id="LC163" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT_FAST16_MAX</span> INT16_MAX</td> - </tr> - <tr> - <td id="L164" class="blob-num js-line-number" data-line-number="164"></td> - <td id="LC164" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT_FAST32_MIN</span> INT32_MIN</td> - </tr> - <tr> - <td id="L165" class="blob-num js-line-number" data-line-number="165"></td> - <td id="LC165" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT_FAST32_MAX</span> INT32_MAX</td> - </tr> - <tr> - <td id="L166" class="blob-num js-line-number" data-line-number="166"></td> - <td id="LC166" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT_FAST64_MIN</span> INT64_MIN</td> - </tr> - <tr> - <td id="L167" class="blob-num js-line-number" data-line-number="167"></td> - <td id="LC167" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT_FAST64_MAX</span> INT64_MAX</td> - </tr> - <tr> - <td id="L168" class="blob-num js-line-number" data-line-number="168"></td> - <td id="LC168" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">UINT_FAST8_MAX</span> UINT8_MAX</td> - </tr> - <tr> - <td id="L169" class="blob-num js-line-number" data-line-number="169"></td> - <td id="LC169" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">UINT_FAST16_MAX</span> UINT16_MAX</td> - </tr> - <tr> - <td id="L170" class="blob-num js-line-number" data-line-number="170"></td> - <td id="LC170" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">UINT_FAST32_MAX</span> UINT32_MAX</td> - </tr> - <tr> - <td id="L171" class="blob-num js-line-number" data-line-number="171"></td> - <td id="LC171" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">UINT_FAST64_MAX</span> UINT64_MAX</td> - </tr> - <tr> - <td id="L172" class="blob-num js-line-number" data-line-number="172"></td> - <td id="LC172" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L173" class="blob-num js-line-number" data-line-number="173"></td> - <td id="LC173" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 7.18.2.4 Limits of integer types capable of holding object pointers</span></td> - </tr> - <tr> - <td id="L174" class="blob-num js-line-number" data-line-number="174"></td> - <td id="LC174" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">ifdef</span> _WIN64 <span class="pl-c"><span class="pl-c">//</span> [</span></td> - </tr> - <tr> - <td id="L175" class="blob-num js-line-number" data-line-number="175"></td> - <td id="LC175" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">define</span> <span class="pl-en">INTPTR_MIN</span> INT64_MIN</td> - </tr> - <tr> - <td id="L176" class="blob-num js-line-number" data-line-number="176"></td> - <td id="LC176" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">define</span> <span class="pl-en">INTPTR_MAX</span> INT64_MAX</td> - </tr> - <tr> - <td id="L177" class="blob-num js-line-number" data-line-number="177"></td> - <td id="LC177" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">define</span> <span class="pl-en">UINTPTR_MAX</span> UINT64_MAX</td> - </tr> - <tr> - <td id="L178" class="blob-num js-line-number" data-line-number="178"></td> - <td id="LC178" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">else</span> <span class="pl-c"><span class="pl-c">//</span> _WIN64 ][</span></td> - </tr> - <tr> - <td id="L179" class="blob-num js-line-number" data-line-number="179"></td> - <td id="LC179" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">define</span> <span class="pl-en">INTPTR_MIN</span> INT32_MIN</td> - </tr> - <tr> - <td id="L180" class="blob-num js-line-number" data-line-number="180"></td> - <td id="LC180" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">define</span> <span class="pl-en">INTPTR_MAX</span> INT32_MAX</td> - </tr> - <tr> - <td id="L181" class="blob-num js-line-number" data-line-number="181"></td> - <td id="LC181" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">define</span> <span class="pl-en">UINTPTR_MAX</span> UINT32_MAX</td> - </tr> - <tr> - <td id="L182" class="blob-num js-line-number" data-line-number="182"></td> - <td id="LC182" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">endif</span> <span class="pl-c"><span class="pl-c">//</span> _WIN64 ]</span></td> - </tr> - <tr> - <td id="L183" class="blob-num js-line-number" data-line-number="183"></td> - <td id="LC183" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L184" class="blob-num js-line-number" data-line-number="184"></td> - <td id="LC184" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 7.18.2.5 Limits of greatest-width integer types</span></td> - </tr> - <tr> - <td id="L185" class="blob-num js-line-number" data-line-number="185"></td> - <td id="LC185" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INTMAX_MIN</span> INT64_MIN</td> - </tr> - <tr> - <td id="L186" class="blob-num js-line-number" data-line-number="186"></td> - <td id="LC186" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INTMAX_MAX</span> INT64_MAX</td> - </tr> - <tr> - <td id="L187" class="blob-num js-line-number" data-line-number="187"></td> - <td id="LC187" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">UINTMAX_MAX</span> UINT64_MAX</td> - </tr> - <tr> - <td id="L188" class="blob-num js-line-number" data-line-number="188"></td> - <td id="LC188" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L189" class="blob-num js-line-number" data-line-number="189"></td> - <td id="LC189" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 7.18.3 Limits of other integer types</span></td> - </tr> - <tr> - <td id="L190" class="blob-num js-line-number" data-line-number="190"></td> - <td id="LC190" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L191" class="blob-num js-line-number" data-line-number="191"></td> - <td id="LC191" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">ifdef</span> _WIN64 <span class="pl-c"><span class="pl-c">//</span> [</span></td> - </tr> - <tr> - <td id="L192" class="blob-num js-line-number" data-line-number="192"></td> - <td id="LC192" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">define</span> <span class="pl-en">PTRDIFF_MIN</span> _I64_MIN</td> - </tr> - <tr> - <td id="L193" class="blob-num js-line-number" data-line-number="193"></td> - <td id="LC193" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">define</span> <span class="pl-en">PTRDIFF_MAX</span> _I64_MAX</td> - </tr> - <tr> - <td id="L194" class="blob-num js-line-number" data-line-number="194"></td> - <td id="LC194" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">else</span> <span class="pl-c"><span class="pl-c">//</span> _WIN64 ][</span></td> - </tr> - <tr> - <td id="L195" class="blob-num js-line-number" data-line-number="195"></td> - <td id="LC195" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">define</span> <span class="pl-en">PTRDIFF_MIN</span> _I32_MIN</td> - </tr> - <tr> - <td id="L196" class="blob-num js-line-number" data-line-number="196"></td> - <td id="LC196" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">define</span> <span class="pl-en">PTRDIFF_MAX</span> _I32_MAX</td> - </tr> - <tr> - <td id="L197" class="blob-num js-line-number" data-line-number="197"></td> - <td id="LC197" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">endif</span> <span class="pl-c"><span class="pl-c">//</span> _WIN64 ]</span></td> - </tr> - <tr> - <td id="L198" class="blob-num js-line-number" data-line-number="198"></td> - <td id="LC198" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L199" class="blob-num js-line-number" data-line-number="199"></td> - <td id="LC199" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">SIG_ATOMIC_MIN</span> INT_MIN</td> - </tr> - <tr> - <td id="L200" class="blob-num js-line-number" data-line-number="200"></td> - <td id="LC200" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">SIG_ATOMIC_MAX</span> INT_MAX</td> - </tr> - <tr> - <td id="L201" class="blob-num js-line-number" data-line-number="201"></td> - <td id="LC201" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L202" class="blob-num js-line-number" data-line-number="202"></td> - <td id="LC202" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">ifndef</span> SIZE_MAX <span class="pl-c"><span class="pl-c">//</span> [</span></td> - </tr> - <tr> - <td id="L203" class="blob-num js-line-number" data-line-number="203"></td> - <td id="LC203" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">ifdef</span> _WIN64 <span class="pl-c"><span class="pl-c">//</span> [</span></td> - </tr> - <tr> - <td id="L204" class="blob-num js-line-number" data-line-number="204"></td> - <td id="LC204" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">define</span> <span class="pl-en">SIZE_MAX</span> _UI64_MAX</td> - </tr> - <tr> - <td id="L205" class="blob-num js-line-number" data-line-number="205"></td> - <td id="LC205" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">else</span> <span class="pl-c"><span class="pl-c">//</span> _WIN64 ][</span></td> - </tr> - <tr> - <td id="L206" class="blob-num js-line-number" data-line-number="206"></td> - <td id="LC206" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">define</span> <span class="pl-en">SIZE_MAX</span> _UI32_MAX</td> - </tr> - <tr> - <td id="L207" class="blob-num js-line-number" data-line-number="207"></td> - <td id="LC207" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">endif</span> <span class="pl-c"><span class="pl-c">//</span> _WIN64 ]</span></td> - </tr> - <tr> - <td id="L208" class="blob-num js-line-number" data-line-number="208"></td> - <td id="LC208" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">endif</span> <span class="pl-c"><span class="pl-c">//</span> SIZE_MAX ]</span></td> - </tr> - <tr> - <td id="L209" class="blob-num js-line-number" data-line-number="209"></td> - <td id="LC209" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L210" class="blob-num js-line-number" data-line-number="210"></td> - <td id="LC210" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h></span></td> - </tr> - <tr> - <td id="L211" class="blob-num js-line-number" data-line-number="211"></td> - <td id="LC211" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">ifndef</span> WCHAR_MIN <span class="pl-c"><span class="pl-c">//</span> [</span></td> - </tr> - <tr> - <td id="L212" class="blob-num js-line-number" data-line-number="212"></td> - <td id="LC212" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">define</span> <span class="pl-en">WCHAR_MIN</span> <span class="pl-c1">0</span></td> - </tr> - <tr> - <td id="L213" class="blob-num js-line-number" data-line-number="213"></td> - <td id="LC213" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">endif</span> <span class="pl-c"><span class="pl-c">//</span> WCHAR_MIN ]</span></td> - </tr> - <tr> - <td id="L214" class="blob-num js-line-number" data-line-number="214"></td> - <td id="LC214" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">ifndef</span> WCHAR_MAX <span class="pl-c"><span class="pl-c">//</span> [</span></td> - </tr> - <tr> - <td id="L215" class="blob-num js-line-number" data-line-number="215"></td> - <td id="LC215" class="blob-code blob-code-inner js-file-line"># <span class="pl-k">define</span> <span class="pl-en">WCHAR_MAX</span> _UI16_MAX</td> - </tr> - <tr> - <td id="L216" class="blob-num js-line-number" data-line-number="216"></td> - <td id="LC216" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">endif</span> <span class="pl-c"><span class="pl-c">//</span> WCHAR_MAX ]</span></td> - </tr> - <tr> - <td id="L217" class="blob-num js-line-number" data-line-number="217"></td> - <td id="LC217" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L218" class="blob-num js-line-number" data-line-number="218"></td> - <td id="LC218" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">WINT_MIN</span> <span class="pl-c1">0</span></td> - </tr> - <tr> - <td id="L219" class="blob-num js-line-number" data-line-number="219"></td> - <td id="LC219" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">WINT_MAX</span> _UI16_MAX</td> - </tr> - <tr> - <td id="L220" class="blob-num js-line-number" data-line-number="220"></td> - <td id="LC220" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L221" class="blob-num js-line-number" data-line-number="221"></td> - <td id="LC221" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">endif</span> <span class="pl-c"><span class="pl-c">//</span> __STDC_LIMIT_MACROS ]</span></td> - </tr> - <tr> - <td id="L222" class="blob-num js-line-number" data-line-number="222"></td> - <td id="LC222" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L223" class="blob-num js-line-number" data-line-number="223"></td> - <td id="LC223" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L224" class="blob-num js-line-number" data-line-number="224"></td> - <td id="LC224" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 7.18.4 Limits of other integer types</span></td> - </tr> - <tr> - <td id="L225" class="blob-num js-line-number" data-line-number="225"></td> - <td id="LC225" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L226" class="blob-num js-line-number" data-line-number="226"></td> - <td id="LC226" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">if</span> !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) <span class="pl-c"><span class="pl-c">//</span> [ See footnote 224 at page 260</span></td> - </tr> - <tr> - <td id="L227" class="blob-num js-line-number" data-line-number="227"></td> - <td id="LC227" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L228" class="blob-num js-line-number" data-line-number="228"></td> - <td id="LC228" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 7.18.4.1 Macros for minimum-width integer constants</span></td> - </tr> - <tr> - <td id="L229" class="blob-num js-line-number" data-line-number="229"></td> - <td id="LC229" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L230" class="blob-num js-line-number" data-line-number="230"></td> - <td id="LC230" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT8_C</span>(<span class="pl-v">val</span>) val##i8</td> - </tr> - <tr> - <td id="L231" class="blob-num js-line-number" data-line-number="231"></td> - <td id="LC231" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT16_C</span>(<span class="pl-v">val</span>) val##i16</td> - </tr> - <tr> - <td id="L232" class="blob-num js-line-number" data-line-number="232"></td> - <td id="LC232" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT32_C</span>(<span class="pl-v">val</span>) val##i32</td> - </tr> - <tr> - <td id="L233" class="blob-num js-line-number" data-line-number="233"></td> - <td id="LC233" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INT64_C</span>(<span class="pl-v">val</span>) val##i64</td> - </tr> - <tr> - <td id="L234" class="blob-num js-line-number" data-line-number="234"></td> - <td id="LC234" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L235" class="blob-num js-line-number" data-line-number="235"></td> - <td id="LC235" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">UINT8_C</span>(<span class="pl-v">val</span>) val##ui8</td> - </tr> - <tr> - <td id="L236" class="blob-num js-line-number" data-line-number="236"></td> - <td id="LC236" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">UINT16_C</span>(<span class="pl-v">val</span>) val##ui16</td> - </tr> - <tr> - <td id="L237" class="blob-num js-line-number" data-line-number="237"></td> - <td id="LC237" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">UINT32_C</span>(<span class="pl-v">val</span>) val##ui32</td> - </tr> - <tr> - <td id="L238" class="blob-num js-line-number" data-line-number="238"></td> - <td id="LC238" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">UINT64_C</span>(<span class="pl-v">val</span>) val##ui64</td> - </tr> - <tr> - <td id="L239" class="blob-num js-line-number" data-line-number="239"></td> - <td id="LC239" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L240" class="blob-num js-line-number" data-line-number="240"></td> - <td id="LC240" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">//</span> 7.18.4.2 Macros for greatest-width integer constants</span></td> - </tr> - <tr> - <td id="L241" class="blob-num js-line-number" data-line-number="241"></td> - <td id="LC241" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">INTMAX_C</span> INT64_C</td> - </tr> - <tr> - <td id="L242" class="blob-num js-line-number" data-line-number="242"></td> - <td id="LC242" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">define</span> <span class="pl-en">UINTMAX_C</span> UINT64_C</td> - </tr> - <tr> - <td id="L243" class="blob-num js-line-number" data-line-number="243"></td> - <td id="LC243" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L244" class="blob-num js-line-number" data-line-number="244"></td> - <td id="LC244" class="blob-code blob-code-inner js-file-line">#<span class="pl-k">endif</span> <span class="pl-c"><span class="pl-c">//</span> __STDC_CONSTANT_MACROS ]</span></td> - </tr> - <tr> - <td id="L245" class="blob-num js-line-number" data-line-number="245"></td> - <td id="LC245" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L246" class="blob-num js-line-number" data-line-number="246"></td> - <td id="LC246" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L247" class="blob-num js-line-number" data-line-number="247"></td> - <td id="LC247" class="blob-code blob-code-inner js-file-line">#endif <span class="pl-c"><span class="pl-c">//</span> _MSC_STDINT_H_ ]</span></td> - </tr> -</table> - - <div class="BlobToolbar position-absolute js-file-line-actions dropdown js-menu-container js-select-menu d-none" aria-hidden="true"> - <button class="btn-octicon ml-0 px-2 p-0 bg-white border border-gray-dark rounded-1 dropdown-toggle js-menu-target" id="js-file-line-action-button" type="button" aria-expanded="false" aria-haspopup="true" aria-label="Inline file action toolbar" aria-controls="inline-file-actions"> - <svg aria-hidden="true" class="octicon" height="16" version="1.1" viewBox="0 0 13 4" width="14"> - <g stroke="none" stroke-width="1" fill-rule="evenodd"> - <g transform="translate(-1.000000, -6.000000)"> - <path d="M2.5,9.5 C1.67157288,9.5 1,8.82842712 1,8 C1,7.17157288 1.67157288,6.5 2.5,6.5 C3.32842712,6.5 4,7.17157288 4,8 C4,8.82842712 3.32842712,9.5 2.5,9.5 Z M7.5,9.5 C6.67157288,9.5 6,8.82842712 6,8 C6,7.17157288 6.67157288,6.5 7.5,6.5 C8.32842712,6.5 9,7.17157288 9,8 C9,8.82842712 8.32842712,9.5 7.5,9.5 Z M12.5,9.5 C11.6715729,9.5 11,8.82842712 11,8 C11,7.17157288 11.6715729,6.5 12.5,6.5 C13.3284271,6.5 14,7.17157288 14,8 C14,8.82842712 13.3284271,9.5 12.5,9.5 Z"></path> - </g> - </g> - </svg> - </button> - <div class="dropdown-menu-content js-menu-content" id="inline-file-actions"> - <ul class="BlobToolbar-dropdown dropdown-menu dropdown-menu-se mt-2"> - <li><a class="js-zeroclipboard dropdown-item" style="cursor:pointer;" id="js-copy-lines" data-original-text="Copy lines">Copy lines</a></li> - <li><a class="js-zeroclipboard dropdown-item" id= "js-copy-permalink" style="cursor:pointer;" data-original-text="Copy permalink">Copy permalink</a></li> - <li><a href="/mattn/gntp-send/blame/090b1276fb4a30601113551bed88c58329646818/include/msinttypes/stdint.h" class="dropdown-item js-update-url-with-hash" id="js-view-git-blame">View git blame</a></li> - <li><a href="/mattn/gntp-send/issues/new" class="dropdown-item" id="js-new-issue">Open new issue</a></li> - </ul> - </div> - </div> - - </div> - - </div> - - <button type="button" data-facebox="#jump-to-line" data-facebox-class="linejump" data-hotkey="l" class="d-none">Jump to Line</button> - <div id="jump-to-line" style="display:none"> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form accept-charset="UTF-8" action="" class="js-jump-to-line-form" method="get"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /></div> - <input class="form-control linejump-input js-jump-to-line-field" type="text" placeholder="Jump to line…" aria-label="Jump to line" autofocus> - <button type="submit" class="btn">Go</button> -</form> </div> - - </div> - <div class="modal-backdrop js-touch-events"></div> -</div> - - </div> - </div> - - </div> - - -<div class="footer container-lg px-3" role="contentinfo"> - <div class="position-relative d-flex flex-justify-between py-6 mt-6 f6 text-gray border-top border-gray-light "> - <ul class="list-style-none d-flex flex-wrap "> - <li class="mr-3">© 2017 <span title="0.12140s from unicorn-1420858540-p0bxs">GitHub</span>, Inc.</li> - <li class="mr-3"><a href="https://github.com/site/terms" data-ga-click="Footer, go to terms, text:terms">Terms</a></li> - <li class="mr-3"><a href="https://github.com/site/privacy" data-ga-click="Footer, go to privacy, text:privacy">Privacy</a></li> - <li class="mr-3"><a href="https://github.com/security" data-ga-click="Footer, go to security, text:security">Security</a></li> - <li class="mr-3"><a href="https://status.github.com/" data-ga-click="Footer, go to status, text:status">Status</a></li> - <li><a href="https://help.github.com" data-ga-click="Footer, go to help, text:help">Help</a></li> - </ul> - - <a href="https://github.com" aria-label="Homepage" class="footer-octicon" title="GitHub"> - <svg aria-hidden="true" class="octicon octicon-mark-github" height="24" version="1.1" viewBox="0 0 16 16" width="24"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg> -</a> - <ul class="list-style-none d-flex flex-wrap "> - <li class="mr-3"><a href="https://github.com/contact" data-ga-click="Footer, go to contact, text:contact">Contact GitHub</a></li> - <li class="mr-3"><a href="https://developer.github.com" data-ga-click="Footer, go to api, text:api">API</a></li> - <li class="mr-3"><a href="https://training.github.com" data-ga-click="Footer, go to training, text:training">Training</a></li> - <li class="mr-3"><a href="https://shop.github.com" data-ga-click="Footer, go to shop, text:shop">Shop</a></li> - <li class="mr-3"><a href="https://github.com/blog" data-ga-click="Footer, go to blog, text:blog">Blog</a></li> - <li><a href="https://github.com/about" data-ga-click="Footer, go to about, text:about">About</a></li> - - </ul> - </div> -</div> - - - - <div id="ajax-error-message" class="ajax-error-message flash flash-error"> - <svg aria-hidden="true" class="octicon octicon-alert" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M8.865 1.52c-.18-.31-.51-.5-.87-.5s-.69.19-.87.5L.275 13.5c-.18.31-.18.69 0 1 .19.31.52.5.87.5h13.7c.36 0 .69-.19.86-.5.17-.31.18-.69.01-1L8.865 1.52zM8.995 13h-2v-2h2v2zm0-3h-2V6h2v4z"/></svg> - <button type="button" class="flash-close js-flash-close js-ajax-error-dismiss" aria-label="Dismiss error"> - <svg aria-hidden="true" class="octicon octicon-x" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"/></svg> - </button> - You can't perform that action at this time. - </div> - - - - <script crossorigin="anonymous" integrity="sha256-Sxs+Reu4luxVVaYLalcHLGmPG0uGt2qgtP4QZ/RAsfM=" src="https://assets-cdn.github.com/assets/frameworks-4b1b3e45ebb896ec5555a60b6a57072c698f1b4b86b76aa0b4fe1067f440b1f3.js"></script> - - <script async="async" crossorigin="anonymous" integrity="sha256-rhTSU9vJG0Aq7OSJ05kyOeUQ/RwV/IBUApQ7VS8xXXM=" src="https://assets-cdn.github.com/assets/github-ae14d253dbc91b402aece489d3993239e510fd1c15fc805402943b552f315d73.js"></script> - - - - - <div class="js-stale-session-flash stale-session-flash flash flash-warn flash-banner d-none"> - <svg aria-hidden="true" class="octicon octicon-alert" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M8.865 1.52c-.18-.31-.51-.5-.87-.5s-.69.19-.87.5L.275 13.5c-.18.31-.18.69 0 1 .19.31.52.5.87.5h13.7c.36 0 .69-.19.86-.5.17-.31.18-.69.01-1L8.865 1.52zM8.995 13h-2v-2h2v2zm0-3h-2V6h2v4z"/></svg> - <span class="signed-in-tab-flash">You signed in with another tab or window. <a href="">Reload</a> to refresh your session.</span> - <span class="signed-out-tab-flash">You signed out in another tab or window. <a href="">Reload</a> to refresh your session.</span> - </div> - <div class="facebox" id="facebox" style="display:none;"> - <div class="facebox-popup"> - <div class="facebox-content" role="dialog" aria-labelledby="facebox-header" aria-describedby="facebox-description"> - </div> - <button type="button" class="facebox-close js-facebox-close" aria-label="Close modal"> - <svg aria-hidden="true" class="octicon octicon-x" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"/></svg> - </button> - </div> -</div> - - - </body> -</html> - diff --git a/src/sat/glucose2/AbcGlucose2.cpp b/src/sat/glucose2/AbcGlucose2.cpp new file mode 100644 index 00000000..9a8b97eb --- /dev/null +++ b/src/sat/glucose2/AbcGlucose2.cpp @@ -0,0 +1,1543 @@ +/**CFile**************************************************************** + + FileName [AbcGlucose.cpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [SAT solver Glucose 3.0 by Gilles Audemard and Laurent Simon.] + + Synopsis [Interface to Glucose.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 6, 2017.] + + Revision [$Id: AbcGlucose.cpp,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sat/glucose2/System.h" +#include "sat/glucose2/ParseUtils.h" +#include "sat/glucose2/Options.h" +#include "sat/glucose2/Dimacs.h" +#include "sat/glucose2/SimpSolver.h" + +#include "sat/glucose2/AbcGlucose2.h" + +#include "base/abc/abc.h" +#include "aig/gia/gia.h" +#include "sat/cnf/cnf.h" +#include "misc/extra/extra.h" + +ABC_NAMESPACE_IMPL_START + +using namespace Gluco2; + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define USE_SIMP_SOLVER 1 + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifdef USE_SIMP_SOLVER + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +SimpSolver * glucose2_solver_start() +{ + SimpSolver * S = new SimpSolver; + S->setIncrementalMode(); + return S; +} + +void glucose2_solver_stop(Gluco2::SimpSolver* S) +{ + delete S; +} + +void glucose2_solver_reset(Gluco2::SimpSolver* S) +{ + S->reset(); +} + +int glucose2_solver_addclause(Gluco2::SimpSolver* S, int * plits, int nlits) +{ + vec<Lit> lits; + for ( int i = 0; i < nlits; i++,plits++) + { + // note: Glucose uses the same var->lit conventiaon as ABC + while ((*plits)/2 >= S->nVars()) S->newVar(); + assert((*plits)/2 < S->nVars()); // NOTE: since we explicitely use new function bmc_add_var + Lit p; + p.x = *plits; + lits.push(p); + } + return S->addClause(lits); // returns 0 if the problem is UNSAT +} + +void glucose2_solver_setcallback(Gluco2::SimpSolver* S, void * pman, int(*pfunc)(void*, int, int*)) +{ + S->pCnfMan = pman; + S->pCnfFunc = pfunc; + S->nCallConfl = 1000; +} + +int glucose2_solver_solve(Gluco2::SimpSolver* S, int * plits, int nlits) +{ +// vec<Lit> lits; +// for (int i=0;i<nlits;i++,plits++) +// { +// Lit p; +// p.x = *plits; +// lits.push(p); +// } +// Gluco2::lbool res = S->solveLimited(lits, 0); +// return (res == l_True ? 1 : res == l_False ? -1 : 0); + return S->solveLimited(plits, nlits, 0); +} + +int glucose2_solver_addvar(Gluco2::SimpSolver* S) +{ + S->newVar(); + return S->nVars() - 1; +} + +int * glucose2_solver_read_cex(Gluco2::SimpSolver* S ) +{ + return S->getCex(); +} + +int glucose2_solver_read_cex_varvalue(Gluco2::SimpSolver* S, int ivar) +{ + return S->model[ivar] == l_True; +} + +void glucose2_solver_setstop(Gluco2::SimpSolver* S, int * pstop) +{ + S->pstop = pstop; +} + + +/**Function************************************************************* + + Synopsis [Wrapper APIs to calling from ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bmcg2_sat_solver * bmcg2_sat_solver_start() +{ + return (bmcg2_sat_solver *)glucose2_solver_start(); +} +void bmcg2_sat_solver_stop(bmcg2_sat_solver* s) +{ + glucose2_solver_stop((Gluco2::SimpSolver*)s); +} +void bmcg2_sat_solver_reset(bmcg2_sat_solver* s) +{ + glucose2_solver_reset((Gluco2::SimpSolver*)s); +} + + +int bmcg2_sat_solver_addclause(bmcg2_sat_solver* s, int * plits, int nlits) +{ + return glucose2_solver_addclause((Gluco2::SimpSolver*)s,plits,nlits); +} + +void bmcg2_sat_solver_setcallback(bmcg2_sat_solver* s, void * pman, int(*pfunc)(void*, int, int*)) +{ + glucose2_solver_setcallback((Gluco2::SimpSolver*)s,pman,pfunc); +} + +int bmcg2_sat_solver_solve(bmcg2_sat_solver* s, int * plits, int nlits) +{ + return glucose2_solver_solve((Gluco2::SimpSolver*)s,plits,nlits); +} + +int bmcg2_sat_solver_final(bmcg2_sat_solver* s, int ** ppArray) +{ + *ppArray = (int *)(Lit *)((Gluco2::SimpSolver*)s)->conflict; + return ((Gluco2::SimpSolver*)s)->conflict.size(); +} + +int bmcg2_sat_solver_addvar(bmcg2_sat_solver* s) +{ + return glucose2_solver_addvar((Gluco2::SimpSolver*)s); +} + +void bmcg2_sat_solver_set_nvars( bmcg2_sat_solver* s, int nvars ) +{ + int i; + for ( i = bmcg2_sat_solver_varnum(s); i < nvars; i++ ) + bmcg2_sat_solver_addvar(s); +} + +int bmcg2_sat_solver_eliminate( bmcg2_sat_solver* s, int turn_off_elim ) +{ +// return 1; + return ((Gluco2::SimpSolver*)s)->eliminate(turn_off_elim != 0); +} + +int bmcg2_sat_solver_var_is_elim( bmcg2_sat_solver* s, int v ) +{ +// return 0; + return ((Gluco2::SimpSolver*)s)->isEliminated(v); +} + +void bmcg2_sat_solver_var_set_frozen( bmcg2_sat_solver* s, int v, int freeze ) +{ + ((Gluco2::SimpSolver*)s)->setFrozen(v, freeze != 0); +} + +int bmcg2_sat_solver_elim_varnum(bmcg2_sat_solver* s) +{ +// return 0; + return ((Gluco2::SimpSolver*)s)->eliminated_vars; +} + +int * bmcg2_sat_solver_read_cex(bmcg2_sat_solver* s) +{ + return glucose2_solver_read_cex((Gluco2::SimpSolver*)s); +} +int bmcg2_sat_solver_read_cex_varvalue(bmcg2_sat_solver* s, int ivar) +{ + return glucose2_solver_read_cex_varvalue((Gluco2::SimpSolver*)s, ivar); +} + +void bmcg2_sat_solver_set_stop(bmcg2_sat_solver* s, int * pstop) +{ + glucose2_solver_setstop((Gluco2::SimpSolver*)s, pstop); +} + +abctime bmcg2_sat_solver_set_runtime_limit(bmcg2_sat_solver* s, abctime Limit) +{ + abctime nRuntimeLimit = ((Gluco2::SimpSolver*)s)->nRuntimeLimit; + ((Gluco2::SimpSolver*)s)->nRuntimeLimit = Limit; + return nRuntimeLimit; +} + +void bmcg2_sat_solver_set_conflict_budget(bmcg2_sat_solver* s, int Limit) +{ + if ( Limit > 0 ) + ((Gluco2::SimpSolver*)s)->setConfBudget( (int64_t)Limit ); + else + ((Gluco2::SimpSolver*)s)->budgetOff(); +} + +int bmcg2_sat_solver_varnum(bmcg2_sat_solver* s) +{ + return ((Gluco2::SimpSolver*)s)->nVars(); +} +int bmcg2_sat_solver_clausenum(bmcg2_sat_solver* s) +{ + return ((Gluco2::SimpSolver*)s)->nClauses(); +} +int bmcg2_sat_solver_learntnum(bmcg2_sat_solver* s) +{ + return ((Gluco2::SimpSolver*)s)->nLearnts(); +} +int bmcg2_sat_solver_conflictnum(bmcg2_sat_solver* s) +{ + return ((Gluco2::SimpSolver*)s)->conflicts; +} + +int bmcg2_sat_solver_minimize_assumptions( bmcg2_sat_solver * s, int * plits, int nlits, int pivot ) +{ + vec<int>*array = &((Gluco2::SimpSolver*)s)->user_vec; + int i, nlitsL, nlitsR, nresL, nresR, status; + assert( pivot >= 0 ); +// assert( nlits - pivot >= 2 ); + assert( nlits - pivot >= 1 ); + if ( nlits - pivot == 1 ) + { + // since the problem is UNSAT, we try to solve it without assuming the last literal + // if the result is UNSAT, the last literal can be dropped; otherwise, it is needed + status = bmcg2_sat_solver_solve( s, plits, pivot ); + return status != GLUCOSE_UNSAT; // return 1 if the problem is not UNSAT + } + assert( nlits - pivot >= 2 ); + nlitsL = (nlits - pivot) / 2; + nlitsR = (nlits - pivot) - nlitsL; + assert( nlitsL + nlitsR == nlits - pivot ); + // solve with these assumptions + status = bmcg2_sat_solver_solve( s, plits, pivot + nlitsL ); + if ( status == GLUCOSE_UNSAT ) // these are enough + return bmcg2_sat_solver_minimize_assumptions( s, plits, pivot + nlitsL, pivot ); + // these are not enough + // solve for the right lits +// nResL = nLitsR == 1 ? 1 : sat_solver_minimize_assumptions( s, pLits + nLitsL, nLitsR, nConfLimit ); + nresL = nlitsR == 1 ? 1 : bmcg2_sat_solver_minimize_assumptions( s, plits, nlits, pivot + nlitsL ); + // swap literals + array->clear(); + for ( i = 0; i < nlitsL; i++ ) + array->push(plits[pivot + i]); + for ( i = 0; i < nresL; i++ ) + plits[pivot + i] = plits[pivot + nlitsL + i]; + for ( i = 0; i < nlitsL; i++ ) + plits[pivot + nresL + i] = (*array)[i]; + // solve with these assumptions + status = bmcg2_sat_solver_solve( s, plits, pivot + nresL ); + if ( status == GLUCOSE_UNSAT ) // these are enough + return nresL; + // solve for the left lits +// nResR = nLitsL == 1 ? 1 : sat_solver_minimize_assumptions( s, pLits + nResL, nLitsL, nConfLimit ); + nresR = nlitsL == 1 ? 1 : bmcg2_sat_solver_minimize_assumptions( s, plits, pivot + nresL + nlitsL, pivot + nresL ); + return nresL + nresR; +} + +int bmcg2_sat_solver_add_and( bmcg2_sat_solver * s, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1, int fCompl ) +{ + int Lits[3]; + + Lits[0] = Abc_Var2Lit( iVar, !fCompl ); + Lits[1] = Abc_Var2Lit( iVar0, fCompl0 ); + if ( !bmcg2_sat_solver_addclause( s, Lits, 2 ) ) + return 0; + + Lits[0] = Abc_Var2Lit( iVar, !fCompl ); + Lits[1] = Abc_Var2Lit( iVar1, fCompl1 ); + if ( !bmcg2_sat_solver_addclause( s, Lits, 2 ) ) + return 0; + + Lits[0] = Abc_Var2Lit( iVar, fCompl ); + Lits[1] = Abc_Var2Lit( iVar0, !fCompl0 ); + Lits[2] = Abc_Var2Lit( iVar1, !fCompl1 ); + if ( !bmcg2_sat_solver_addclause( s, Lits, 3 ) ) + return 0; + + return 1; +} + +int bmcg2_sat_solver_add_xor( bmcg2_sat_solver * pSat, int iVarA, int iVarB, int iVarC, int fCompl ) +{ + int Lits[3]; + int Cid; + assert( iVarA >= 0 && iVarB >= 0 && iVarC >= 0 ); + + Lits[0] = Abc_Var2Lit( iVarA, !fCompl ); + Lits[1] = Abc_Var2Lit( iVarB, 1 ); + Lits[2] = Abc_Var2Lit( iVarC, 1 ); + Cid = bmcg2_sat_solver_addclause( pSat, Lits, 3 ); + assert( Cid ); + + Lits[0] = Abc_Var2Lit( iVarA, !fCompl ); + Lits[1] = Abc_Var2Lit( iVarB, 0 ); + Lits[2] = Abc_Var2Lit( iVarC, 0 ); + Cid = bmcg2_sat_solver_addclause( pSat, Lits, 3 ); + assert( Cid ); + + Lits[0] = Abc_Var2Lit( iVarA, fCompl ); + Lits[1] = Abc_Var2Lit( iVarB, 1 ); + Lits[2] = Abc_Var2Lit( iVarC, 0 ); + Cid = bmcg2_sat_solver_addclause( pSat, Lits, 3 ); + assert( Cid ); + + Lits[0] = Abc_Var2Lit( iVarA, fCompl ); + Lits[1] = Abc_Var2Lit( iVarB, 0 ); + Lits[2] = Abc_Var2Lit( iVarC, 1 ); + Cid = bmcg2_sat_solver_addclause( pSat, Lits, 3 ); + assert( Cid ); + return 4; +} + +int bmcg2_sat_solver_jftr(bmcg2_sat_solver* s) +{ + return ((Gluco2::SimpSolver*)s)->jftr; +} + +void bmcg2_sat_solver_set_jftr(bmcg2_sat_solver* s, int jftr) +{ + ((Gluco2::SimpSolver*)s)->jftr = jftr; +} + +void bmcg2_sat_solver_set_var_fanin_lit(bmcg2_sat_solver* s, int var, int lit0, int lit1) +{ + ((Gluco2::SimpSolver*)s)->sat_solver_set_var_fanin_lit(var, lit0, lit1); +} + +void bmcg2_sat_solver_start_new_round(bmcg2_sat_solver* s) +{ + ((Gluco2::SimpSolver*)s)->sat_solver_start_new_round(); +} + +void bmcg2_sat_solver_mark_cone(bmcg2_sat_solver* s, int var) +{ + ((Gluco2::SimpSolver*)s)->sat_solver_mark_cone(var); +} + +void bmcg2_sat_solver_prelocate( bmcg2_sat_solver * s, int var_num ){ + ((Gluco2::SimpSolver*)s)->prelocate(var_num); +} + +#else + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Solver * glucose2_solver_start() +{ + Solver * S = new Solver; + S->setIncrementalMode(); + return S; +} + +void glucose2_solver_stop(Gluco2::Solver* S) +{ + delete S; +} + +void glucose2_solver_reset(Gluco2::Solver* S) +{ + S->reset(); +} + +int glucose2_solver_addclause(Gluco2::Solver* S, int * plits, int nlits) +{ + vec<Lit> lits; + for ( int i = 0; i < nlits; i++,plits++) + { + // note: Glucose uses the same var->lit conventiaon as ABC + while ((*plits)/2 >= S->nVars()) S->newVar(); + assert((*plits)/2 < S->nVars()); // NOTE: since we explicitely use new function bmc_add_var + Lit p; + p.x = *plits; + lits.push(p); + } + return S->addClause(lits); // returns 0 if the problem is UNSAT +} + +void glucose2_solver_setcallback(Gluco2::Solver* S, void * pman, int(*pfunc)(void*, int, int*)) +{ + S->pCnfMan = pman; + S->pCnfFunc = pfunc; + S->nCallConfl = 1000; +} + +int glucose2_solver_solve(Gluco2::Solver* S, int * plits, int nlits) +{ + vec<Lit> lits; + for (int i=0;i<nlits;i++,plits++) + { + Lit p; + p.x = *plits; + lits.push(p); + } + Gluco2::lbool res = S->solveLimited(lits); + return (res == l_True ? 1 : res == l_False ? -1 : 0); +} + +int glucose2_solver_addvar(Gluco2::Solver* S) +{ + S->newVar(); + return S->nVars() - 1; +} + +int * glucose2_solver_read_cex(Gluco2::Solver* S ) +{ + return S->getCex(); +} + +int glucose2_solver_read_cex_varvalue(Gluco2::Solver* S, int ivar) +{ + return S->model[ivar] == l_True; +} + +void glucose2_solver_setstop(Gluco2::Solver* S, int * pstop) +{ + S->pstop = pstop; +} + + +/**Function************************************************************* + + Synopsis [Wrapper APIs to calling from ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bmcg2_sat_solver * bmcg2_sat_solver_start() +{ + return (bmcg2_sat_solver *)glucose2_solver_start(); +} +void bmcg2_sat_solver_stop(bmcg2_sat_solver* s) +{ + glucose2_solver_stop((Gluco2::Solver*)s); +} +void bmcg2_sat_solver_reset(bmcg2_sat_solver* s) +{ + glucose2_solver_reset((Gluco2::Solver*)s); +} + +int bmcg2_sat_solver_addclause(bmcg2_sat_solver* s, int * plits, int nlits) +{ + return glucose2_solver_addclause((Gluco2::Solver*)s,plits,nlits); +} + +void bmcg2_sat_solver_setcallback(bmcg2_sat_solver* s, void * pman, int(*pfunc)(void*, int, int*)) +{ + glucose2_solver_setcallback((Gluco2::Solver*)s,pman,pfunc); +} + +int bmcg2_sat_solver_solve(bmcg2_sat_solver* s, int * plits, int nlits) +{ + return glucose2_solver_solve((Gluco2::Solver*)s,plits,nlits); +} + +int bmcg2_sat_solver_final(bmcg2_sat_solver* s, int ** ppArray) +{ + *ppArray = (int *)(Lit *)((Gluco2::Solver*)s)->conflict; + return ((Gluco2::Solver*)s)->conflict.size(); +} + +int bmcg2_sat_solver_addvar(bmcg2_sat_solver* s) +{ + return glucose2_solver_addvar((Gluco2::Solver*)s); +} + +void bmcg2_sat_solver_set_nvars( bmcg2_sat_solver* s, int nvars ) +{ + int i; + for ( i = bmcg2_sat_solver_varnum(s); i < nvars; i++ ) + bmcg2_sat_solver_addvar(s); +} + +int bmcg2_sat_solver_eliminate( bmcg2_sat_solver* s, int turn_off_elim ) +{ + return 1; +// return ((Gluco2::SimpSolver*)s)->eliminate(turn_off_elim != 0); +} + +int bmcg2_sat_solver_var_is_elim( bmcg2_sat_solver* s, int v ) +{ + return 0; +// return ((Gluco2::SimpSolver*)s)->isEliminated(v); +} + +void bmcg2_sat_solver_var_set_frozen( bmcg2_sat_solver* s, int v, int freeze ) +{ +// ((Gluco2::SimpSolver*)s)->setFrozen(v, freeze); +} + +int bmcg2_sat_solver_elim_varnum(bmcg2_sat_solver* s) +{ + return 0; +// return ((Gluco2::SimpSolver*)s)->eliminated_vars; +} + +int * bmcg2_sat_solver_read_cex(bmcg2_sat_solver* s) +{ + return glucose2_solver_read_cex((Gluco2::Solver*)s); +} + +int bmcg2_sat_solver_read_cex_varvalue(bmcg2_sat_solver* s, int ivar) +{ + return glucose2_solver_read_cex_varvalue((Gluco2::Solver*)s, ivar); +} + +void bmcg2_sat_solver_set_stop(bmcg2_sat_solver* s, int * pstop) +{ + glucose2_solver_setstop((Gluco2::Solver*)s, pstop); +} + +abctime bmcg2_sat_solver_set_runtime_limit(bmcg2_sat_solver* s, abctime Limit) +{ + abctime nRuntimeLimit = ((Gluco2::Solver*)s)->nRuntimeLimit; + ((Gluco2::Solver*)s)->nRuntimeLimit = Limit; + return nRuntimeLimit; +} + +void bmcg2_sat_solver_set_conflict_budget(bmcg2_sat_solver* s, int Limit) +{ + if ( Limit > 0 ) + ((Gluco2::Solver*)s)->setConfBudget( (int64_t)Limit ); + else + ((Gluco2::Solver*)s)->budgetOff(); +} + +int bmcg2_sat_solver_varnum(bmcg2_sat_solver* s) +{ + return ((Gluco2::Solver*)s)->nVars(); +} +int bmcg2_sat_solver_clausenum(bmcg2_sat_solver* s) +{ + return ((Gluco2::Solver*)s)->nClauses(); +} +int bmcg2_sat_solver_learntnum(bmcg2_sat_solver* s) +{ + return ((Gluco2::Solver*)s)->nLearnts(); +} +int bmcg2_sat_solver_conflictnum(bmcg2_sat_solver* s) +{ + return ((Gluco2::Solver*)s)->conflicts; +} + +int bmcg2_sat_solver_minimize_assumptions( bmcg2_sat_solver * s, int * plits, int nlits, int pivot ) +{ + vec<int>*array = &((Gluco2::Solver*)s)->user_vec; + int i, nlitsL, nlitsR, nresL, nresR, status; + assert( pivot >= 0 ); +// assert( nlits - pivot >= 2 ); + assert( nlits - pivot >= 1 ); + if ( nlits - pivot == 1 ) + { + // since the problem is UNSAT, we try to solve it without assuming the last literal + // if the result is UNSAT, the last literal can be dropped; otherwise, it is needed + status = bmcg2_sat_solver_solve( s, plits, pivot ); + return status != GLUCOSE_UNSAT; // return 1 if the problem is not UNSAT + } + assert( nlits - pivot >= 2 ); + nlitsL = (nlits - pivot) / 2; + nlitsR = (nlits - pivot) - nlitsL; + assert( nlitsL + nlitsR == nlits - pivot ); + // solve with these assumptions + status = bmcg2_sat_solver_solve( s, plits, pivot + nlitsL ); + if ( status == GLUCOSE_UNSAT ) // these are enough + return bmcg2_sat_solver_minimize_assumptions( s, plits, pivot + nlitsL, pivot ); + // these are not enough + // solve for the right lits +// nResL = nLitsR == 1 ? 1 : sat_solver_minimize_assumptions( s, pLits + nLitsL, nLitsR, nConfLimit ); + nresL = nlitsR == 1 ? 1 : bmcg2_sat_solver_minimize_assumptions( s, plits, nlits, pivot + nlitsL ); + // swap literals + array->clear(); + for ( i = 0; i < nlitsL; i++ ) + array->push(plits[pivot + i]); + for ( i = 0; i < nresL; i++ ) + plits[pivot + i] = plits[pivot + nlitsL + i]; + for ( i = 0; i < nlitsL; i++ ) + plits[pivot + nresL + i] = (*array)[i]; + // solve with these assumptions + status = bmcg2_sat_solver_solve( s, plits, pivot + nresL ); + if ( status == GLUCOSE_UNSAT ) // these are enough + return nresL; + // solve for the left lits +// nResR = nLitsL == 1 ? 1 : sat_solver_minimize_assumptions( s, pLits + nResL, nLitsL, nConfLimit ); + nresR = nlitsL == 1 ? 1 : bmcg2_sat_solver_minimize_assumptions( s, plits, pivot + nresL + nlitsL, pivot + nresL ); + return nresL + nresR; +} + +int bmcg2_sat_solver_add_and( bmcg2_sat_solver * s, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1, int fCompl ) +{ + int Lits[3]; + + Lits[0] = Abc_Var2Lit( iVar, !fCompl ); + Lits[1] = Abc_Var2Lit( iVar0, fCompl0 ); + if ( !bmcg2_sat_solver_addclause( s, Lits, 2 ) ) + return 0; + + Lits[0] = Abc_Var2Lit( iVar, !fCompl ); + Lits[1] = Abc_Var2Lit( iVar1, fCompl1 ); + if ( !bmcg2_sat_solver_addclause( s, Lits, 2 ) ) + return 0; + + Lits[0] = Abc_Var2Lit( iVar, fCompl ); + Lits[1] = Abc_Var2Lit( iVar0, !fCompl0 ); + Lits[2] = Abc_Var2Lit( iVar1, !fCompl1 ); + if ( !bmcg2_sat_solver_addclause( s, Lits, 3 ) ) + return 0; + + return 1; +} + +int bmcg2_solver_add_xor( bmcg2_sat_solver * pSat, int iVarA, int iVarB, int iVarC, int fCompl ) +{ + int Lits[3]; + int Cid; + assert( iVarA >= 0 && iVarB >= 0 && iVarC >= 0 ); + + Lits[0] = Abc_Var2Lit( iVarA, !fCompl ); + Lits[1] = Abc_Var2Lit( iVarB, 1 ); + Lits[2] = Abc_Var2Lit( iVarC, 1 ); + Cid = bmcg2_sat_solver_addclause( pSat, Lits, 3 ); + assert( Cid ); + + Lits[0] = Abc_Var2Lit( iVarA, !fCompl ); + Lits[1] = Abc_Var2Lit( iVarB, 0 ); + Lits[2] = Abc_Var2Lit( iVarC, 0 ); + Cid = bmcg2_sat_solver_addclause( pSat, Lits, 3 ); + assert( Cid ); + + Lits[0] = Abc_Var2Lit( iVarA, fCompl ); + Lits[1] = Abc_Var2Lit( iVarB, 1 ); + Lits[2] = Abc_Var2Lit( iVarC, 0 ); + Cid = bmcg2_sat_solver_addclause( pSat, Lits, 3 ); + assert( Cid ); + + Lits[0] = Abc_Var2Lit( iVarA, fCompl ); + Lits[1] = Abc_Var2Lit( iVarB, 0 ); + Lits[2] = Abc_Var2Lit( iVarC, 1 ); + Cid = bmcg2_sat_solver_addclause( pSat, Lits, 3 ); + assert( Cid ); + return 4; +} + +int bmcg2_sat_solver_jftr(bmcg2_sat_solver* s) +{ + return ((Gluco2::Solver*)s)->jftr; +} + +void bmcg2_sat_solver_set_jftr(bmcg2_sat_solver* s, int jftr) +{ + ((Gluco2::Solver*)s)->jftr = jftr; +} + +void bmcg2_sat_solver_set_var_fanin_lit(bmcg2_sat_solver* s, int var, int lit0, int lit1) +{ + ((Gluco2::Solver*)s)->sat_solver_set_var_fanin_lit(var, lit0, lit1); +} + +void bmcg2_sat_solver_start_new_round(bmcg2_sat_solver* s) +{ + ((Gluco2::Solver*)s)->sat_solver_start_new_round(); +} + +void bmcg2_sat_solver_mark_cone(bmcg2_sat_solver* s, int var) +{ + ((Gluco2::Solver*)s)->sat_solver_mark_cone(var); +} + +void bmcg2_sat_solver_prelocate( bmcg2_sat_solver * s, int var_num ){ + ((Gluco2::Solver*)s)->prelocate(var_num); +} + +#endif + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void glucose2_print_stats(SimpSolver& s, abctime clk) +{ + double cpu_time = (double)(unsigned)clk / CLOCKS_PER_SEC; + double mem_used = memUsed(); + printf("c restarts : %d (%d conflicts on average)\n", (int)s.starts, s.starts > 0 ? (int)(s.conflicts/s.starts) : 0); + printf("c blocked restarts : %d (multiple: %d) \n", (int)s.nbstopsrestarts, (int)s.nbstopsrestartssame); + printf("c last block at restart : %d\n", (int)s.lastblockatrestart); + printf("c nb ReduceDB : %-12d\n", (int)s.nbReduceDB); + printf("c nb removed Clauses : %-12d\n", (int)s.nbRemovedClauses); + printf("c nb learnts DL2 : %-12d\n", (int)s.nbDL2); + printf("c nb learnts size 2 : %-12d\n", (int)s.nbBin); + printf("c nb learnts size 1 : %-12d\n", (int)s.nbUn); + printf("c conflicts : %-12d (%.0f /sec)\n", (int)s.conflicts, s.conflicts /cpu_time); + printf("c decisions : %-12d (%4.2f %% random) (%.0f /sec)\n", (int)s.decisions, (float)s.rnd_decisions*100 / (float)s.decisions, s.decisions /cpu_time); + printf("c propagations : %-12d (%.0f /sec)\n", (int)s.propagations, s.propagations/cpu_time); + printf("c conflict literals : %-12d (%4.2f %% deleted)\n", (int)s.tot_literals, (s.max_literals - s.tot_literals)*100 / (double)s.max_literals); + printf("c nb reduced Clauses : %-12d\n", (int)s.nbReducedClauses); + if (mem_used != 0) printf("Memory used : %.2f MB\n", mem_used); + //printf("c CPU time : %.2f sec\n", cpu_time); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Glucose_ReadDimacs( char * pFileName, SimpSolver& s ) +{ + vec<Lit> * lits = &s.user_lits; + char * pBuffer = Extra_FileReadContents( pFileName ); + char * pTemp; int fComp, Var, VarMax = 0; + lits->clear(); + for ( pTemp = pBuffer; *pTemp; pTemp++ ) + { + if ( *pTemp == 'c' || *pTemp == 'p' ) { + while ( *pTemp != '\n' ) + pTemp++; + continue; + } + while ( *pTemp == ' ' || *pTemp == '\t' || *pTemp == '\r' || *pTemp == '\n' ) + pTemp++; + fComp = 0; + if ( *pTemp == '-' ) + fComp = 1, pTemp++; + if ( *pTemp == '+' ) + pTemp++; + Var = atoi( pTemp ); + if ( Var == 0 ) { + if ( lits->size() > 0 ) { + s.addVar( VarMax ); + s.addClause(*lits); + lits->clear(); + } + } + else { + Var--; + VarMax = Abc_MaxInt( VarMax, Var ); + lits->push( toLit(Abc_Var2Lit(Var, fComp)) ); + } + while ( *pTemp >= '0' && *pTemp <= '9' ) + pTemp++; + } + ABC_FREE( pBuffer ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Glucose2_SolveCnf( char * pFileName, Glucose2_Pars * pPars ) +{ + abctime clk = Abc_Clock(); + + SimpSolver S; + S.verbosity = pPars->verb; + S.setConfBudget( pPars->nConfls > 0 ? (int64_t)pPars->nConfls : -1 ); + +// gzFile in = gzopen(pFilename, "rb"); +// parse_DIMACS(in, S); +// gzclose(in); + Glucose_ReadDimacs( pFileName, S ); + + if ( pPars->verb ) + { + printf("c ============================[ Problem Statistics ]=============================\n"); + printf("c | |\n"); + printf("c | Number of variables: %12d |\n", S.nVars()); + printf("c | Number of clauses: %12d |\n", S.nClauses()); + } + + if ( pPars->pre ) + { + S.eliminate(true); + printf( "c Simplication removed %d variables and %d clauses. ", S.eliminated_vars, S.eliminated_clauses ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + + vec<Lit> dummy; + lbool ret = S.solveLimited(dummy, 0); + if ( pPars->verb ) glucose2_print_stats(S, Abc_Clock() - clk); + printf(ret == l_True ? "SATISFIABLE" : ret == l_False ? "UNSATISFIABLE" : "INDETERMINATE"); + Abc_PrintTime( 1, " Time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Glucose_SolverFromAig( Gia_Man_t * p, SimpSolver& s ) +{ + abctime clk = Abc_Clock(); + vec<Lit> * lits = &s.user_lits; + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8 /*nLutSize*/, 0 /*fCnfObjIds*/, 1/*fAddOrCla*/, 0, 0/*verbose*/ ); + for ( int i = 0; i < pCnf->nClauses; i++ ) + { + lits->clear(); + for ( int * pLit = pCnf->pClauses[i]; pLit < pCnf->pClauses[i+1]; pLit++ ) + lits->push( toLit(*pLit) ), s.addVar( *pLit >> 1 ); + s.addClause(*lits); + } + Vec_Int_t * vCnfIds = Vec_IntAllocArrayCopy(pCnf->pVarNums,pCnf->nVars); + printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Cnf_DataFree(pCnf); + return vCnfIds; +} + +// procedure below does not work because glucose2_solver_addclause() expects Solver +Vec_Int_t * Glucose_SolverFromAig2( Gia_Man_t * p, SimpSolver& S ) +{ + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8 /*nLutSize*/, 0 /*fCnfObjIds*/, 1/*fAddOrCla*/, 0, 0/*verbose*/ ); + for ( int i = 0; i < pCnf->nClauses; i++ ) + if ( !glucose2_solver_addclause( &S, pCnf->pClauses[i], pCnf->pClauses[i+1]-pCnf->pClauses[i] ) ) + assert( 0 ); + Vec_Int_t * vCnfIds = Vec_IntAllocArrayCopy(pCnf->pVarNums,pCnf->nVars); + //printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); + //Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Cnf_DataFree(pCnf); + return vCnfIds; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Glucose2_GenerateCubes( bmcg2_sat_solver * pSat[2], Vec_Int_t * vCiSatVars, Vec_Int_t * vVar2Index, int CubeLimit ) +{ + int fCreatePrime = 1; + int nCubes, nSupp = Vec_IntSize(vCiSatVars); + Vec_Str_t * vSop = Vec_StrAlloc( 1000 ); + Vec_Int_t * vLits = Vec_IntAlloc( nSupp ); + Vec_Str_t * vCube = Vec_StrAlloc( nSupp + 4 ); + Vec_StrFill( vCube, nSupp, '-' ); + Vec_StrPrintF( vCube, " 1\n\0" ); + for ( nCubes = 0; !CubeLimit || nCubes < CubeLimit; nCubes++ ) + { + int * pFinal, nFinal, iVar, i, k = 0; + // generate onset minterm + int status = bmcg2_sat_solver_solve( pSat[1], NULL, 0 ); + if ( status == GLUCOSE_UNSAT ) + break; + assert( status == GLUCOSE_SAT ); + Vec_IntClear( vLits ); + Vec_IntForEachEntry( vCiSatVars, iVar, i ) + Vec_IntPush( vLits, Abc_Var2Lit(iVar, !bmcg2_sat_solver_read_cex_varvalue(pSat[1], iVar)) ); + // expand against offset + if ( fCreatePrime ) + { + nFinal = bmcg2_sat_solver_minimize_assumptions( pSat[0], Vec_IntArray(vLits), Vec_IntSize(vLits), 0 ); + Vec_IntShrink( vLits, nFinal ); + pFinal = Vec_IntArray( vLits ); + for ( i = 0; i < nFinal; i++ ) + pFinal[i] = Abc_LitNot(pFinal[i]); + } + else + { + status = bmcg2_sat_solver_solve( pSat[0], Vec_IntArray(vLits), Vec_IntSize(vLits) ); + assert( status == GLUCOSE_UNSAT ); + nFinal = bmcg2_sat_solver_final( pSat[0], &pFinal ); + } + // print cube + Vec_StrFill( vCube, nSupp, '-' ); + for ( i = 0; i < nFinal; i++ ) + { + int Index = Vec_IntEntry(vVar2Index, Abc_Lit2Var(pFinal[i])); + if ( Index == -1 ) + continue; + pFinal[k++] = pFinal[i]; + assert( Index >= 0 && Index < nSupp ); + Vec_StrWriteEntry( vCube, Index, (char)('0' + Abc_LitIsCompl(pFinal[i])) ); + } + nFinal = k; + Vec_StrAppend( vSop, Vec_StrArray(vCube) ); + //printf( "%s\n", Vec_StrArray(vCube) ); + // add blocking clause + if ( !bmcg2_sat_solver_addclause( pSat[1], pFinal, nFinal ) ) + break; + } + Vec_IntFree( vLits ); + Vec_StrFree( vCube ); + Vec_StrPush( vSop, '\0' ); + return vSop; +} +Vec_Str_t * bmcg2_sat_solver_sop( Gia_Man_t * p, int CubeLimit ) +{ + bmcg2_sat_solver * pSat[2] = { bmcg2_sat_solver_start(), bmcg2_sat_solver_start() }; + + // generate CNF for the on-set and off-set + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8 /*nLutSize*/, 0 /*fCnfObjIds*/, 0/*fAddOrCla*/, 0, 0/*verbose*/ ); + int i, n, nVars = Gia_ManCiNum(p), Lit;//, Count = 0; + int iFirstVar = pCnf->nVars - nVars; + assert( Gia_ManCoNum(p) == 1 ); + for ( n = 0; n < 2; n++ ) + { + bmcg2_sat_solver_set_nvars( pSat[n], pCnf->nVars ); + Lit = Abc_Var2Lit( 1, !n ); // output variable is 1 + for ( i = 0; i < pCnf->nClauses; i++ ) + if ( !bmcg2_sat_solver_addclause( pSat[n], pCnf->pClauses[i], pCnf->pClauses[i+1]-pCnf->pClauses[i] ) ) + assert( 0 ); + if ( !bmcg2_sat_solver_addclause( pSat[n], &Lit, 1 ) ) + { + Vec_Str_t * vSop = Vec_StrAlloc( 10 ); + Vec_StrPrintF( vSop, " %d\n\0", !n ); + Cnf_DataFree( pCnf ); + return vSop; + } + } + Cnf_DataFree( pCnf ); + + // collect cube vars and map SAT vars into them + Vec_Int_t * vVars = Vec_IntAlloc( 100 ); + Vec_Int_t * vVarMap = Vec_IntStartFull( iFirstVar + nVars ); + for ( i = 0; i < nVars; i++ ) + { + Vec_IntPush( vVars, iFirstVar+i ); + Vec_IntWriteEntry( vVarMap, iFirstVar+i, i ); + } + + Vec_Str_t * vSop = Glucose2_GenerateCubes( pSat, vVars, vVarMap, CubeLimit ); + Vec_IntFree( vVarMap ); + Vec_IntFree( vVars ); + + bmcg2_sat_solver_stop( pSat[0] ); + bmcg2_sat_solver_stop( pSat[1] ); + return vSop; +} +void bmcg2_sat_solver_print_sop( Gia_Man_t * p ) +{ + Vec_Str_t * vSop = bmcg2_sat_solver_sop( p, 0 ); + printf( "%s", Vec_StrArray(vSop) ); + Vec_StrFree( vSop ); +} +void bmcg2_sat_solver_print_sop_lit( Gia_Man_t * p, int Lit ) +{ + Vec_Int_t * vCisUsed = Vec_IntAlloc( 100 ); + int i, ObjId, iNode = Abc_Lit2Var( Lit ); + Gia_ManCollectCis( p, &iNode, 1, vCisUsed ); + Vec_IntSort( vCisUsed, 0 ); + Vec_IntForEachEntry( vCisUsed, ObjId, i ) + Vec_IntWriteEntry( vCisUsed, i, Gia_ManIdToCioId(p, ObjId) ); + Vec_IntPrint( vCisUsed ); + Gia_Man_t * pNew = Gia_ManDupConeSupp( p, Lit, vCisUsed ); + Vec_IntFree( vCisUsed ); + bmcg2_sat_solver_print_sop( pNew ); + Gia_ManStop( pNew ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Computing d-literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +#define Gia_CubeForEachVar( pCube, Value, i ) \ + for ( i = 0; (pCube[i] != ' ') && (Value = pCube[i]); i++ ) +#define Gia_SopForEachCube( pSop, nFanins, pCube ) \ + for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 ) + +void bmcg2_sat_generate_dvars( Vec_Int_t * vCiVars, Vec_Str_t * vSop, Vec_Int_t * vDLits ) +{ + int i, Lit, Counter, nCubes = 0; + char Value, * pCube, * pSop = Vec_StrArray( vSop ); + Vec_Int_t * vCounts = Vec_IntStart( 2*Vec_IntSize(vCiVars) ); + Vec_IntClear( vDLits ); + Gia_SopForEachCube( pSop, Vec_IntSize(vCiVars), pCube ) + { + nCubes++; + Gia_CubeForEachVar( pCube, Value, i ) + { + if ( Value == '1' ) + Vec_IntAddToEntry( vCounts, 2*i, 1 ); + else if ( Value == '0' ) + Vec_IntAddToEntry( vCounts, 2*i+1, 1 ); + } + } + Vec_IntForEachEntry( vCounts, Counter, Lit ) + if ( Counter == nCubes ) + Vec_IntPush( vDLits, Abc_Var2Lit(Vec_IntEntry(vCiVars, Abc_Lit2Var(Lit)), Abc_LitIsCompl(Lit)) ); + Vec_IntSort( vDLits, 0 ); + Vec_IntFree( vCounts ); +} + +/**Function************************************************************* + + Synopsis [Performs SAT-based quantification.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int bmcg2_sat_solver_quantify2( Gia_Man_t * p, int iLit, int fHash, int(*pFuncCiToKeep)(void *, int), void * pData, Vec_Int_t * vDLits ) +{ + int fSynthesize = 0; + extern Gia_Man_t * Abc_SopSynthesizeOne( char * pSop, int fClp ); + Gia_Man_t * pMan, * pNew, * pTemp; Vec_Str_t * vSop; + int i, CiId, ObjId, Res, nCubes = 0, nNodes, Count = 0, iNode = Abc_Lit2Var(iLit); + Vec_Int_t * vCisUsed = Vec_IntAlloc( 100 ); + Gia_ManCollectCis( p, &iNode, 1, vCisUsed ); + Vec_IntSort( vCisUsed, 0 ); + if ( vDLits ) Vec_IntClear( vDLits ); + if ( iLit < 2 ) + return iLit; + // remap into CI Ids + Vec_IntForEachEntry( vCisUsed, ObjId, i ) + Vec_IntWriteEntry( vCisUsed, i, Gia_ManIdToCioId(p, ObjId) ); + // duplicate cone + pNew = Gia_ManDupConeSupp( p, iLit, vCisUsed ); + assert( Gia_ManCiNum(pNew) == Vec_IntSize(vCisUsed) ); + nNodes = Gia_ManAndNum(pNew); + + // perform quantification one CI at a time + assert( pFuncCiToKeep ); + Vec_IntForEachEntry( vCisUsed, CiId, i ) + if ( !pFuncCiToKeep( pData, CiId ) ) + { + //printf( "Quantifying %d.\n", CiId ); + pNew = Gia_ManDupExist( pTemp = pNew, i ); + Gia_ManStop( pTemp ); + Count++; + } + if ( Gia_ManPoIsConst(pNew, 0) ) + { + int RetValue = Gia_ManPoIsConst1(pNew, 0); + Vec_IntFree( vCisUsed ); + Gia_ManStop( pNew ); + return RetValue; + } + + if ( fSynthesize ) + { + vSop = bmcg2_sat_solver_sop( pNew, 0 ); + Gia_ManStop( pNew ); + pMan = Abc_SopSynthesizeOne( Vec_StrArray(vSop), 1 ); + nCubes = Vec_StrCountEntry(vSop, '\n'); + if ( vDLits ) + { + // convert into object IDs + Vec_Int_t * vCisObjs = Vec_IntAlloc( Vec_IntSize(vCisUsed) ); + Vec_IntForEachEntry( vCisUsed, CiId, i ) + Vec_IntPush( vCisObjs, CiId + 1 ); + bmcg2_sat_generate_dvars( vCisObjs, vSop, vDLits ); + Vec_IntFree( vCisObjs ); + } + Vec_StrFree( vSop ); + + if ( Gia_ManPoIsConst(pMan, 0) ) + { + int RetValue = Gia_ManPoIsConst1(pMan, 0); + Vec_IntFree( vCisUsed ); + Gia_ManStop( pMan ); + return RetValue; + } + } + else + { + pMan = pNew; + } + + Res = Gia_ManDupConeBack( p, pMan, vCisUsed ); + + // report the result + //printf( "Performed quantification with %5d nodes, %3d keep-vars, %3d quant-vars, resulting in %5d cubes and %5d nodes. ", + // nNodes, Vec_IntSize(vCisUsed) - Count, Count, nCubes, Gia_ManAndNum(pMan) ); + //Abc_PrintTime( 1, "Time", Abc_Clock() - clkAll ); + + Vec_IntFree( vCisUsed ); + Gia_ManStop( pMan ); + return Res; +} + + +/**Function************************************************************* + + Synopsis [Performs SAT-based quantification.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSatAndCollect2_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vObjsUsed, Vec_Int_t * vCiVars ) +{ + Gia_Obj_t * pObj; int iVar; + if ( (iVar = Gia_ObjCopyArray(p, iObj)) >= 0 ) + return iVar; + pObj = Gia_ManObj( p, iObj ); + assert( Gia_ObjIsCand(pObj) ); + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ManSatAndCollect2_rec( p, Gia_ObjFaninId0(pObj, iObj), vObjsUsed, vCiVars ); + Gia_ManSatAndCollect2_rec( p, Gia_ObjFaninId1(pObj, iObj), vObjsUsed, vCiVars ); + } + iVar = Vec_IntSize( vObjsUsed ); + Vec_IntPush( vObjsUsed, iObj ); + Gia_ObjSetCopyArray( p, iObj, iVar ); + if ( vCiVars && Gia_ObjIsCi(pObj) ) + Vec_IntPush( vCiVars, iVar ); + return iVar; +} +void Gia_ManQuantLoadCnf2( Gia_Man_t * p, Vec_Int_t * vObjsUsed, bmcg2_sat_solver * pSats[] ) +{ + Gia_Obj_t * pObj; int i; + bmcg2_sat_solver_reset( pSats[0] ); + if ( pSats[1] ) + bmcg2_sat_solver_reset( pSats[1] ); + bmcg2_sat_solver_set_nvars( pSats[0], Vec_IntSize(vObjsUsed) ); + if ( pSats[1] ) + bmcg2_sat_solver_set_nvars( pSats[1], Vec_IntSize(vObjsUsed) ); + Gia_ManForEachObjVec( vObjsUsed, p, pObj, i ) + if ( Gia_ObjIsAnd(pObj) ) + { + int iObj = Gia_ObjId( p, pObj ); + int iVar = Gia_ObjCopyArray(p, iObj); + int iVar0 = Gia_ObjCopyArray(p, Gia_ObjFaninId0(pObj, iObj)); + int iVar1 = Gia_ObjCopyArray(p, Gia_ObjFaninId1(pObj, iObj)); + bmcg2_sat_solver_add_and( pSats[0], iVar, iVar0, iVar1, Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + if ( pSats[1] ) + bmcg2_sat_solver_add_and( pSats[1], iVar, iVar0, iVar1, Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + } + else if ( Gia_ObjIsConst0(pObj) ) + { + int Lit = Abc_Var2Lit( Gia_ObjCopyArray(p, 0), 1 ); + int RetValue = bmcg2_sat_solver_addclause( pSats[0], &Lit, 1 ); + assert( RetValue ); + if ( pSats[1] ) + bmcg2_sat_solver_addclause( pSats[1], &Lit, 1 ); + assert( Lit == 1 ); + } +} +int Gia_ManFactorSop2( Gia_Man_t * p, Vec_Int_t * vCiObjIds, Vec_Str_t * vSop, int fHash ) +{ + extern Gia_Man_t * Abc_SopSynthesizeOne( char * pSop, int fClp ); + Gia_Man_t * pMan = Abc_SopSynthesizeOne( Vec_StrArray(vSop), 1 ); + Gia_Obj_t * pObj; int i, Result; + assert( Gia_ManPiNum(pMan) == Vec_IntSize(vCiObjIds) ); + Gia_ManConst0(pMan)->Value = 0; + Gia_ManForEachPi( pMan, pObj, i ) + pObj->Value = Abc_Var2Lit( Vec_IntEntry(vCiObjIds, i), 0 ); + Gia_ManForEachAnd( pMan, pObj, i ) + if ( fHash ) + pObj->Value = Gia_ManHashAnd( p, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + pObj->Value = Gia_ManAppendAnd( p, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + pObj = Gia_ManPo(pMan, 0); + Result = Gia_ObjFanin0Copy(pObj); + Gia_ManStop( pMan ); + return Result; +} +int bmcg2_sat_solver_quantify( bmcg2_sat_solver * pSats[], Gia_Man_t * p, int iLit, int fHash, int(*pFuncCiToKeep)(void *, int), void * pData, Vec_Int_t * vDLits ) +{ + Vec_Int_t * vObjsUsed = Vec_IntAlloc( 100 ); // GIA objs + Vec_Int_t * vCiVars = Vec_IntAlloc( 100 ); // CI SAT vars + Vec_Int_t * vVarMap = NULL; Vec_Str_t * vSop = NULL; + int i, iVar, iVarLast, Lit, RetValue, Count = 0, Result = -1; + if ( vDLits ) Vec_IntClear( vDLits ); + if ( iLit < 2 ) + return iLit; + if ( Vec_IntSize(&p->vCopies) < Gia_ManObjNum(p) ) + Vec_IntFillExtra( &p->vCopies, Gia_ManObjNum(p), -1 ); + // assign variable number 0 to const0 node + iVar = Vec_IntSize(vObjsUsed); + Vec_IntPush( vObjsUsed, 0 ); + Gia_ObjSetCopyArray( p, 0, iVar ); + assert( iVar == 0 ); + + // collect other variables + iVarLast = Gia_ManSatAndCollect2_rec( p, Abc_Lit2Var(iLit), vObjsUsed, vCiVars ); + Gia_ManQuantLoadCnf2( p, vObjsUsed, pSats ); + + // check constants + Lit = Abc_Var2Lit( iVarLast, !Abc_LitIsCompl(iLit) ); + RetValue = bmcg2_sat_solver_addclause( pSats[0], &Lit, 1 ); // offset + if ( !RetValue || bmcg2_sat_solver_solve(pSats[0], NULL, 0) == GLUCOSE_UNSAT ) + { + Result = 1; + goto cleanup; + } + Lit = Abc_Var2Lit( iVarLast, Abc_LitIsCompl(iLit) ); + RetValue = bmcg2_sat_solver_addclause( pSats[1], &Lit, 1 ); // onset + if ( !RetValue || bmcg2_sat_solver_solve(pSats[1], NULL, 0) == GLUCOSE_UNSAT ) + { + Result = 0; + goto cleanup; + } +/* + // reorder CI SAT variables to have keep-vars first + Vec_Int_t * vCiVars2 = Vec_IntAlloc( 100 ); // CI SAT vars + Vec_IntForEachEntry( vCiVars, iVar, i ) + { + Gia_Obj_t * pObj = Gia_ManObj( p, Vec_IntEntry(vObjsUsed, iVar) ); + assert( Gia_ObjIsCi(pObj) ); + if ( pFuncCiToKeep(pData, Gia_ObjCioId(pObj)) ) + Vec_IntPush( vCiVars2, iVar ); + } + Vec_IntForEachEntry( vCiVars, iVar, i ) + { + Gia_Obj_t * pObj = Gia_ManObj( p, Vec_IntEntry(vObjsUsed, iVar) ); + assert( Gia_ObjIsCi(pObj) ); + if ( !pFuncCiToKeep(pData, Gia_ObjCioId(pObj)) ) + Vec_IntPush( vCiVars2, iVar ); + } + ABC_SWAP( Vec_Int_t *, vCiVars2, vCiVars ); + Vec_IntFree( vCiVars2 ); +*/ + // map CI SAT variables into their indexes used in the cubes + vVarMap = Vec_IntStartFull( Vec_IntSize(vObjsUsed) ); + Vec_IntForEachEntry( vCiVars, iVar, i ) + { + Gia_Obj_t * pObj = Gia_ManObj( p, Vec_IntEntry(vObjsUsed, iVar) ); + assert( Gia_ObjIsCi(pObj) ); + if ( pFuncCiToKeep(pData, Gia_ObjCioId(pObj)) ) + Vec_IntWriteEntry( vVarMap, iVar, i ), Count++; + } + if ( Count == 0 || Count == Vec_IntSize(vCiVars) ) + { + Result = Count == 0 ? 1 : iLit; + goto cleanup; + } + // generate cubes + vSop = Glucose2_GenerateCubes( pSats, vCiVars, vVarMap, 0 ); + //printf( "%s", Vec_StrArray(vSop) ); + // convert into object IDs + Vec_IntForEachEntry( vCiVars, iVar, i ) + Vec_IntWriteEntry( vCiVars, i, Vec_IntEntry(vObjsUsed, iVar) ); + // generate unate variables + if ( vDLits ) + bmcg2_sat_generate_dvars( vCiVars, vSop, vDLits ); + // convert into an AIG + RetValue = Gia_ManAndNum(p); + Result = Gia_ManFactorSop2( p, vCiVars, vSop, fHash ); + + // report the result +// printf( "Performed quantification with %5d nodes, %3d keep-vars, %3d quant-vars, resulting in %5d cubes and %5d nodes. ", +// Vec_IntSize(vObjsUsed), Count, Vec_IntSize(vCiVars) - Count, Vec_StrCountEntry(vSop, '\n'), Gia_ManAndNum(p)-RetValue ); +// Abc_PrintTime( 1, "Time", Abc_Clock() - clkAll ); + +cleanup: + Vec_IntForEachEntry( vObjsUsed, iVar, i ) + Gia_ObjSetCopyArray( p, iVar, -1 ); + Vec_IntFree( vObjsUsed ); + Vec_IntFree( vCiVars ); + Vec_IntFreeP( &vVarMap ); + Vec_StrFreeP( &vSop ); + return Result; +} +int Gia_ManCiIsToKeep2( void * pData, int i ) +{ + return i % 5 != 0; +} +void Glucose2_QuantifyAigTest( Gia_Man_t * p ) +{ + bmcg2_sat_solver * pSats[3] = { bmcg2_sat_solver_start(), bmcg2_sat_solver_start(), bmcg2_sat_solver_start() }; + + abctime clk1 = Abc_Clock(); + int iRes1 = bmcg2_sat_solver_quantify( pSats, p, Gia_ObjFaninLit0p(p, Gia_ManPo(p, 0)), 0, Gia_ManCiIsToKeep2, NULL, NULL ); + abctime clk1d = Abc_Clock()-clk1; + + abctime clk2 = Abc_Clock(); + int iRes2 = bmcg2_sat_solver_quantify2( p, Gia_ObjFaninLit0p(p, Gia_ManPo(p, 0)), 0, Gia_ManCiIsToKeep2, NULL, NULL ); + abctime clk2d = Abc_Clock()-clk2; + + Abc_PrintTime( 1, "Time1", clk1d ); + Abc_PrintTime( 1, "Time2", clk2d ); + + if ( bmcg2_sat_solver_equiv_overlap_check( pSats[2], p, iRes1, iRes2, 1 ) ) + printf( "Verification passed.\n" ); + else + printf( "Verification FAILED.\n" ); + + Gia_ManAppendCo( p, iRes1 ); + Gia_ManAppendCo( p, iRes2 ); + + bmcg2_sat_solver_stop( pSats[0] ); + bmcg2_sat_solver_stop( pSats[1] ); + bmcg2_sat_solver_stop( pSats[2] ); +} +int bmcg2_sat_solver_quantify_test( bmcg2_sat_solver * pSats[], Gia_Man_t * p, int iLit, int fHash, int(*pFuncCiToKeep)(void *, int), void * pData, Vec_Int_t * vDLits ) +{ + extern int Gia_ManQuantExist( Gia_Man_t * p, int iLit, int(*pFuncCiToKeep)(void *, int), void * pData ); + int Res1 = Gia_ManQuantExist( p, iLit, pFuncCiToKeep, pData ); + int Res2 = bmcg2_sat_solver_quantify2( p, iLit, 1, pFuncCiToKeep, pData, NULL ); + + bmcg2_sat_solver * pSat = bmcg2_sat_solver_start(); + if ( bmcg2_sat_solver_equiv_overlap_check( pSat, p, Res1, Res2, 1 ) ) + printf( "Verification passed.\n" ); + else + { + printf( "Verification FAILED.\n" ); + bmcg2_sat_solver_print_sop_lit( p, Res1 ); + bmcg2_sat_solver_print_sop_lit( p, Res2 ); + printf( "\n" ); + } + return Res1; +} + +/**Function************************************************************* + + Synopsis [Checks equivalence or intersection of two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int bmcg2_sat_solver_equiv_overlap_check( bmcg2_sat_solver * pSat, Gia_Man_t * p, int iLit0, int iLit1, int fEquiv ) +{ + bmcg2_sat_solver * pSats[2] = { pSat, NULL }; + Vec_Int_t * vObjsUsed = Vec_IntAlloc( 100 ); + int i, iVar, iSatVar[2], iSatLit[2], Lits[2], status; + if ( Vec_IntSize(&p->vCopies) < Gia_ManObjNum(p) ) + Vec_IntFillExtra( &p->vCopies, Gia_ManObjNum(p), -1 ); + + // assign const0 variable number 0 + iVar = Vec_IntSize(vObjsUsed); + Vec_IntPush( vObjsUsed, 0 ); + Gia_ObjSetCopyArray( p, 0, iVar ); + assert( iVar == 0 ); + + iSatVar[0] = Gia_ManSatAndCollect2_rec( p, Abc_Lit2Var(iLit0), vObjsUsed, NULL ); + iSatVar[1] = Gia_ManSatAndCollect2_rec( p, Abc_Lit2Var(iLit1), vObjsUsed, NULL ); + + iSatLit[0] = Abc_Var2Lit( iSatVar[0], Abc_LitIsCompl(iLit0) ); + iSatLit[1] = Abc_Var2Lit( iSatVar[1], Abc_LitIsCompl(iLit1) ); + Gia_ManQuantLoadCnf2( p, vObjsUsed, pSats ); + Vec_IntForEachEntry( vObjsUsed, iVar, i ) + Gia_ObjSetCopyArray( p, iVar, -1 ); + Vec_IntFree( vObjsUsed ); + + if ( fEquiv ) + { + Lits[0] = iSatLit[0]; + Lits[1] = Abc_LitNot(iSatLit[1]); + status = bmcg2_sat_solver_solve( pSats[0], Lits, 2 ); + if ( status == GLUCOSE_UNSAT ) + { + Lits[0] = Abc_LitNot(iSatLit[0]); + Lits[1] = iSatLit[1]; + status = bmcg2_sat_solver_solve( pSats[0], Lits, 2 ); + } + return status == GLUCOSE_UNSAT; + } + else + { + Lits[0] = iSatLit[0]; + Lits[1] = iSatLit[1]; + status = bmcg2_sat_solver_solve( pSats[0], Lits, 2 ); + return status == GLUCOSE_SAT; + } +} +void Glucose2_CheckTwoNodesTest( Gia_Man_t * p ) +{ + int n, Res; + bmcg2_sat_solver * pSat = bmcg2_sat_solver_start(); + for ( n = 0; n < 2; n++ ) + { + Res = bmcg2_sat_solver_equiv_overlap_check( + pSat, p, + Gia_ObjFaninLit0p(p, Gia_ManPo(p, 0)), + Gia_ObjFaninLit0p(p, Gia_ManPo(p, 1)), + n ); + bmcg2_sat_solver_reset( pSat ); + printf( "%s %s.\n", n ? "Equivalence" : "Overlap", Res ? "holds" : "fails" ); + } + bmcg2_sat_solver_stop( pSat ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Glucose2_SolveAig(Gia_Man_t * p, Glucose2_Pars * pPars) +{ + abctime clk = Abc_Clock(); + + SimpSolver S; + S.verbosity = pPars->verb; + S.verbEveryConflicts = 50000; + S.showModel = false; + //S.verbosity = 2; + S.setConfBudget( pPars->nConfls > 0 ? (int64_t)pPars->nConfls : -1 ); + + S.parsing = 1; + Vec_Int_t * vCnfIds = Glucose_SolverFromAig(p,S); + S.parsing = 0; + + if (pPars->verb) + { + printf("c ============================[ Problem Statistics ]=============================\n"); + printf("c | |\n"); + printf("c | Number of variables: %12d |\n", S.nVars()); + printf("c | Number of clauses: %12d |\n", S.nClauses()); + } + + if (pPars->pre) + { + S.eliminate(true); + printf( "c Simplication removed %d variables and %d clauses. ", S.eliminated_vars, S.eliminated_clauses ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + + vec<Lit> dummy; + lbool ret = S.solveLimited(dummy, 0); + + if ( pPars->verb ) glucose2_print_stats(S, Abc_Clock() - clk); + printf(ret == l_True ? "SATISFIABLE" : ret == l_False ? "UNSATISFIABLE" : "INDETERMINATE"); + Abc_PrintTime( 1, " Time", Abc_Clock() - clk ); + + // port counterexample + if (ret == l_True) + { + Gia_Obj_t * pObj; int i; + p->pCexComb = Abc_CexAlloc(0,Gia_ManCiNum(p),1); + Gia_ManForEachCi( p, pObj, i ) + { + assert(Vec_IntEntry(vCnfIds,Gia_ObjId(p, pObj))!=-1); + if (S.model[Vec_IntEntry(vCnfIds,Gia_ObjId(p, pObj))] == l_True) + Abc_InfoSetBit( p->pCexComb->pData, i); + } + } + Vec_IntFree(vCnfIds); + return (ret == l_True ? 10 : ret == l_False ? 20 : 0); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END diff --git a/src/sat/glucose2/AbcGlucose2.h b/src/sat/glucose2/AbcGlucose2.h new file mode 100644 index 00000000..9299d290 --- /dev/null +++ b/src/sat/glucose2/AbcGlucose2.h @@ -0,0 +1,118 @@ +/**CFile**************************************************************** + + FileName [AbcGlucose.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [SAT solver Glucose 3.0 by Gilles Audemard and Laurent Simon.] + + Synopsis [Interface to Glucose.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 6, 2017.] + + Revision [$Id: AbcGlucose.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC_SAT_GLUCOSE_H_ +#define ABC_SAT_GLUCOSE_H_ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "aig/gia/gia.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +#define GLUCOSE_UNSAT -1 +#define GLUCOSE_SAT 1 +#define GLUCOSE_UNDEC 0 + + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Glucose2_Pars_ Glucose2_Pars; +struct Glucose2_Pars_ { + int pre; // preprocessing + int verb; // verbosity + int cust; // customizable + int nConfls; // conflict limit (0 = no limit) +}; + +static inline Glucose2_Pars Glucose_CreatePars(int p, int v, int c, int nConfls) +{ + Glucose2_Pars pars; + pars.pre = p; + pars.verb = v; + pars.cust = c; + pars.nConfls = nConfls; + return pars; +} + +typedef void bmcg2_sat_solver; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern bmcg2_sat_solver * bmcg2_sat_solver_start(); +extern void bmcg2_sat_solver_stop( bmcg2_sat_solver* s ); +extern void bmcg2_sat_solver_reset( bmcg2_sat_solver* s ); +extern int bmcg2_sat_solver_addclause( bmcg2_sat_solver* s, int * plits, int nlits ); +extern void bmcg2_sat_solver_setcallback( bmcg2_sat_solver* s, void * pman, int(*pfunc)(void*, int, int*) ); +extern int bmcg2_sat_solver_solve( bmcg2_sat_solver* s, int * plits, int nlits ); +extern int bmcg2_sat_solver_final( bmcg2_sat_solver* s, int ** ppArray ); +extern int bmcg2_sat_solver_addvar( bmcg2_sat_solver* s ); +extern void bmcg2_sat_solver_set_nvars( bmcg2_sat_solver* s, int nvars ); +extern int bmcg2_sat_solver_eliminate( bmcg2_sat_solver* s, int turn_off_elim ); +extern int bmcg2_sat_solver_var_is_elim( bmcg2_sat_solver* s, int v ); +extern void bmcg2_sat_solver_var_set_frozen( bmcg2_sat_solver* s, int v, int freeze ); +extern int bmcg2_sat_solver_elim_varnum(bmcg2_sat_solver* s); +extern int * bmcg2_sat_solver_read_cex( bmcg2_sat_solver* s ); +extern int bmcg2_sat_solver_read_cex_varvalue( bmcg2_sat_solver* s, int ); +extern void bmcg2_sat_solver_set_stop( bmcg2_sat_solver* s, int * pstop ); +extern abctime bmcg2_sat_solver_set_runtime_limit( bmcg2_sat_solver* s, abctime Limit ); +extern void bmcg2_sat_solver_set_conflict_budget( bmcg2_sat_solver* s, int Limit ); +extern int bmcg2_sat_solver_varnum( bmcg2_sat_solver* s ); +extern int bmcg2_sat_solver_clausenum( bmcg2_sat_solver* s ); +extern int bmcg2_sat_solver_learntnum( bmcg2_sat_solver* s ); +extern int bmcg2_sat_solver_conflictnum( bmcg2_sat_solver* s ); +extern int bmcg2_sat_solver_minimize_assumptions( bmcg2_sat_solver * s, int * plits, int nlits, int pivot ); +extern int bmcg2_sat_solver_add_and( bmcg2_sat_solver * s, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1, int fCompl ); +extern int bmcg2_sat_solver_add_xor( bmcg2_sat_solver * s, int iVarA, int iVarB, int iVarC, int fCompl ); +extern int bmcg2_sat_solver_quantify( bmcg2_sat_solver * s[], Gia_Man_t * p, int iLit, int fHash, int(*pFuncCiToKeep)(void *, int), void * pData, Vec_Int_t * vDLits ); +extern int bmcg2_sat_solver_equiv_overlap_check( bmcg2_sat_solver * s, Gia_Man_t * p, int iLit0, int iLit1, int fEquiv ); +extern Vec_Str_t * bmcg2_sat_solver_sop( Gia_Man_t * p, int CubeLimit ); +extern int bmcg2_sat_solver_jftr( bmcg2_sat_solver * s ); +extern void bmcg2_sat_solver_set_jftr( bmcg2_sat_solver * s, int jftr ); +extern void bmcg2_sat_solver_set_var_fanin_lit( bmcg2_sat_solver * s, int var, int lit0, int lit1 ); +extern void bmcg2_sat_solver_start_new_round( bmcg2_sat_solver * s ); +extern void bmcg2_sat_solver_mark_cone( bmcg2_sat_solver * s, int var ); +extern void bmcg2_sat_solver_prelocate( bmcg2_sat_solver * s, int var_num ); + +extern void Glucose2_SolveCnf( char * pFilename, Glucose2_Pars * pPars ); +extern int Glucose2_SolveAig( Gia_Man_t * p, Glucose2_Pars * pPars ); + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/sat/glucose2/AbcGlucoseCmd2.cpp b/src/sat/glucose2/AbcGlucoseCmd2.cpp new file mode 100644 index 00000000..54bae608 --- /dev/null +++ b/src/sat/glucose2/AbcGlucoseCmd2.cpp @@ -0,0 +1,149 @@ +/**CFile**************************************************************** + + FileName [AbcGlucoseCmd.cpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [SAT solver Glucose 3.0 by Gilles Audemard and Laurent Simon.] + + Synopsis [Interface to Glucose.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 6, 2017.] + + Revision [$Id: AbcGlucoseCmd.cpp,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig/gia/gia.h" +#include "base/main/mainInt.h" + +#include "sat/glucose2/AbcGlucose2.h" + + +ABC_NAMESPACE_HEADER_START + +extern void Glucose2_Init( Abc_Frame_t *pAbc ); +extern void Glucose2_End( Abc_Frame_t * pAbc ); + +ABC_NAMESPACE_HEADER_END + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Abc_CommandGlucose( Abc_Frame_t * pAbc, int argc, char ** argv ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +void Glucose2_Init(Abc_Frame_t *pAbc) +{ + Cmd_CommandAdd( pAbc, "ABC9", "&glucose2", Abc_CommandGlucose, 0 ); +} + +void Glucose2_End( Abc_Frame_t * pAbc ) +{ +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandGlucose( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + int c = 0; + int pre = 1; + int verb = 0; + int nConfls = 0; + + Glucose2_Pars pPars; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Cpvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfls = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfls < 0 ) + goto usage; + break; + case 'p': + pre ^= 1; + break; + case 'v': + verb ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + pPars = Glucose_CreatePars(pre,verb,0,nConfls); + + if ( argc == globalUtilOptind + 1 ) + { + Glucose2_SolveCnf( argv[globalUtilOptind], &pPars ); + return 0; + } + + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandGlucose(): There is no AIG.\n" ); + return 1; + } + + if ( Glucose2_SolveAig( pAbc->pGia, &pPars ) == 10 ) + Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb ); + + return 0; + +usage: + Abc_Print( -2, "usage: &glucose2 [-C num] [-pvh] <file.cnf>\n" ); + Abc_Print( -2, "\t run Glucose 3.0 by Gilles Audemard and Laurent Simon\n" ); + Abc_Print( -2, "\t-C num : conflict limit [default = %d]\n", nConfls ); + Abc_Print( -2, "\t-p : enable preprocessing [default = %d]\n",pre); + Abc_Print( -2, "\t-v : verbosity [default = %d]\n",verb); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t<file.cnf> : (optional) CNF file to solve\n"); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END diff --git a/src/sat/glucose2/Alg.h b/src/sat/glucose2/Alg.h new file mode 100644 index 00000000..96f6ab70 --- /dev/null +++ b/src/sat/glucose2/Alg.h @@ -0,0 +1,88 @@ +/*******************************************************************************************[Alg.h] +Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson +Copyright (c) 2007-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#ifndef Glucose_Alg_h +#define Glucose_Alg_h + +#include "sat/glucose2/Vec.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace Gluco2 { + +//================================================================================================= +// Useful functions on vector-like types: + +//================================================================================================= +// Removing and searching for elements: +// + +template<class V, class T> +static inline void remove(V& ts, const T& t) +{ + int j = 0; + for (; j < ts.size() && ts[j] != t; j++); + assert(j < ts.size()); + for (; j < ts.size()-1; j++) ts[j] = ts[j+1]; + ts.pop(); +} + + +template<class V, class T> +static inline bool find(V& ts, const T& t) +{ + int j = 0; + for (; j < ts.size() && ts[j] != t; j++); + return j < ts.size(); +} + + +//================================================================================================= +// Copying vectors with support for nested vector types: +// + +// Base case: +template<class T> +static inline void copy(const T& from, T& to) +{ + to = from; +} + +// Recursive case: +template<class T> +static inline void copy(const vec<T>& from, vec<T>& to, bool append = false) +{ + if (!append) + to.clear(); + for (int i = 0; i < from.size(); i++){ + to.push(); + copy(from[i], to.last()); + } +} + +template<class T> +static inline void append(const vec<T>& from, vec<T>& to){ copy(from, to, true); } + +//================================================================================================= +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/src/sat/glucose2/Alloc.h b/src/sat/glucose2/Alloc.h new file mode 100644 index 00000000..b7bebaca --- /dev/null +++ b/src/sat/glucose2/Alloc.h @@ -0,0 +1,136 @@ +/*****************************************************************************************[Alloc.h] +Copyright (c) 2008-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + + +#ifndef Glucose_Alloc_h +#define Glucose_Alloc_h + +#include "sat/glucose2/XAlloc.h" +#include "sat/glucose2/Vec.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace Gluco2 { + +//================================================================================================= +// Simple Region-based memory allocator: + +template<class T> +class RegionAllocator +{ + T* memory; + uint32_t sz; + uint32_t cap; + uint32_t wasted_; + + void capacity(uint32_t min_cap); + + public: + // TODO: make this a class for better type-checking? + typedef uint32_t Ref; + enum { Ref_Undef = UINT32_MAX }; + enum { Unit_Size = sizeof(uint32_t) }; + + explicit RegionAllocator(uint32_t start_cap = 1024*1024) : memory(NULL), sz(0), cap(0), wasted_(0){ capacity(start_cap); } + ~RegionAllocator() + { + if (memory != NULL) + ::free(memory); + } + + + uint32_t size () const { return sz; } + uint32_t wasted () const { return wasted_; } + + Ref alloc (int size); + void free_ (int size) { wasted_ += size; } + void clear () { sz = 0; wasted_=0; } + + // Deref, Load Effective Address (LEA), Inverse of LEA (AEL): + T& operator[](Ref r) { assert(r >= 0 && r < sz); return memory[r]; } + const T& operator[](Ref r) const { assert(r >= 0 && r < sz); return memory[r]; } + + T* lea (Ref r) { assert(r >= 0 && r < sz); return &memory[r]; } + const T* lea (Ref r) const { assert(r >= 0 && r < sz); return &memory[r]; } + Ref ael (const T* t) { assert((void*)t >= (void*)&memory[0] && (void*)t < (void*)&memory[sz-1]); + return (Ref)(t - &memory[0]); } + + void moveTo(RegionAllocator& to) { + if (to.memory != NULL) ::free(to.memory); + to.memory = memory; + to.sz = sz; + to.cap = cap; + to.wasted_ = wasted_; + + memory = NULL; + sz = cap = wasted_ = 0; + } + + +}; + +template<class T> +void RegionAllocator<T>::capacity(uint32_t min_cap) +{ + if (cap >= min_cap) return; + + uint32_t prev_cap = cap; + while (cap < min_cap){ + // NOTE: Multiply by a factor (13/8) without causing overflow, then add 2 and make the + // result even by clearing the least significant bit. The resulting sequence of capacities + // is carefully chosen to hit a maximum capacity that is close to the '2^32-1' limit when + // using 'uint32_t' as indices so that as much as possible of this space can be used. + uint32_t delta = ((cap >> 1) + (cap >> 3) + 2) & ~1; + cap += delta; + + if (cap <= prev_cap) + throw OutOfMemoryException(); + } + //printf(" .. (%p) cap = %u\n", this, cap); + + assert(cap > 0); + memory = (T*)xrealloc(memory, sizeof(T)*cap); +} + + +template<class T> +typename RegionAllocator<T>::Ref +RegionAllocator<T>::alloc(int size) +{ + //printf("ALLOC called (this = %p, size = %d)\n", this, size); fflush(stdout); + assert(size > 0); + capacity(sz + size); + + uint32_t prev_sz = sz; + sz += size; + + // Handle overflow: + if (sz < prev_sz) + throw OutOfMemoryException(); + + return prev_sz; +} + + +//================================================================================================= +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/src/sat/glucose2/BoundedQueue.h b/src/sat/glucose2/BoundedQueue.h new file mode 100644 index 00000000..1a0d2148 --- /dev/null +++ b/src/sat/glucose2/BoundedQueue.h @@ -0,0 +1,114 @@ +/***********************************************************************************[BoundedQueue.h] + Glucose -- Copyright (c) 2009, Gilles Audemard, Laurent Simon + CRIL - Univ. Artois, France + LRI - Univ. Paris Sud, France + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + + +#ifndef BoundedQueue_h +#define BoundedQueue_h + +#include "sat/glucose2/Vec.h" + +ABC_NAMESPACE_CXX_HEADER_START + +//================================================================================================= + +namespace Gluco2 { + +template <class T> +class bqueue { + vec<T> elems; + int first; + int last; + uint64_t sumofqueue; + int maxsize; + int queuesize; // Number of current elements (must be < maxsize !) + bool expComputed; + double exp,value; +public: + bqueue(void) : first(0), last(0), sumofqueue(0), maxsize(0), queuesize(0),expComputed(false) { } + + void initSize(int size) {growTo(size);exp = 2.0/(size+1);} // Init size of bounded size queue + + void push(T x) { + expComputed = false; + if (queuesize==maxsize) { + assert(last==first); // The queue is full, next value to enter will replace oldest one + sumofqueue -= elems[last]; + if ((++last) == maxsize) last = 0; + } else + queuesize++; + sumofqueue += x; + elems[first] = x; + if ((++first) == maxsize) {first = 0;last = 0;} + } + + T peek() { assert(queuesize>0); return elems[last]; } + void pop() {sumofqueue-=elems[last]; queuesize--; if ((++last) == maxsize) last = 0;} + + uint64_t getsum() const {return sumofqueue;} + unsigned int getavg() const {return (unsigned int)(sumofqueue/((uint64_t)queuesize));} + int maxSize() const {return maxsize;} + double getavgDouble() const { + double tmp = 0; + for(int i=0;i<elems.size();i++) { + tmp+=elems[i]; + } + return tmp/elems.size(); + } + int isvalid() const {return (queuesize==maxsize);} + + void growTo(int size) { + elems.growTo(size); + first=0; maxsize=size; queuesize = 0;last = 0; + for(int i=0;i<size;i++) elems[i]=0; + } + + double getAvgExp() { + if(expComputed) return value; + double a=exp; + value = elems[first]; + for(int i = first;i<maxsize;i++) { + value+=a*((double)elems[i]); + a=a*exp; + } + for(int i = 0;i<last;i++) { + value+=a*((double)elems[i]); + a=a*exp; + } + value = value*(1-exp)/(1-a); + expComputed = true; + return value; + + + } + void fastclear() {first = 0; last = 0; queuesize=0; sumofqueue=0;} // to be called after restarts... Discard the queue + + int size(void) { return queuesize; } + + void clear(bool dealloc = false) { elems.clear(dealloc); first = 0; maxsize=0; queuesize=0;sumofqueue=0;} + + +}; +} +//================================================================================================= + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/src/sat/glucose2/CGlucose.h b/src/sat/glucose2/CGlucose.h new file mode 100644 index 00000000..7fbf8f83 --- /dev/null +++ b/src/sat/glucose2/CGlucose.h @@ -0,0 +1,7 @@ +#ifndef Glucose_CGlucose_h +#define Glucose_CGlucose_h + +#define CGLUCOSE_EXP 1 +#include "sat/glucose2/Heap2.h" + +#endif
\ No newline at end of file diff --git a/src/sat/glucose2/CGlucoseCore.h b/src/sat/glucose2/CGlucoseCore.h new file mode 100644 index 00000000..c0f96fc4 --- /dev/null +++ b/src/sat/glucose2/CGlucoseCore.h @@ -0,0 +1,620 @@ +// The code in this file was developed by He-Teng Zhang (National Taiwan University) + +#ifndef Glucose_CGlucoseCore_h +#define Glucose_CGlucoseCore_h + +/* + * justification for glucose + */ + +#include "sat/glucose2/Options.h" +#include "sat/glucose2/Solver.h" + +ABC_NAMESPACE_IMPL_START + +namespace Gluco2 { +inline int Solver::justUsage() const { return jftr; } + +inline Lit Solver::gateJustFanin(Var v) const { + assert(v < nVars()); + assert(isJReason(v)); + + + lbool val0, val1; + val0 = value(getFaninLit0(v)); + val1 = value(getFaninLit1(v)); + + if(isAND(v)){ + // should be handled by conflict analysis before entering here + assert( value(v) != l_False || l_True != val0 || l_True != val1 ); + + if(val0 == l_False || val1 == l_False) + return lit_Undef; + + // branch + if(val0 == l_True) + return ~getFaninLit1(v); + if(val1 == l_True) + return ~getFaninLit0(v); + + //assert( jdata[v].act_fanin == activity[getFaninVar0(v)] || jdata[v].act_fanin == activity[getFaninVar1(v)] ); + //assert( jdata[v].act_fanin == (jdata[v].adir? activity[getFaninVar1(v)]: activity[getFaninVar0(v)]) ); + return maxActiveLit( ~getFaninLit0(v), ~getFaninLit1(v) ); + //return jdata[v].adir? ~getFaninLit1(v): ~getFaninLit0(v); + } else { // xor scope + // should be handled by conflict analysis before entering here + assert( value(v) == l_Undef || value(v) != l_False || val0 == val1 ); + + // both are assigned + if( l_Undef != val0 && l_Undef != val1 ) + return lit_Undef; + + // should be handled by propagation before entering here + assert( l_Undef == val0 && l_Undef == val1 ); + return maxActiveLit( getFaninPlt0(v), getFaninPlt1(v) ); + } +} + + +// a var should at most be enqueued one time +inline void Solver::pushJustQueue(Var v, int index){ + assert(v < nVars()); + assert(isJReason(v)); + + if( ! isRoundWatch(v) )\ + return; + + var2NodeData[v].now = true; + + + if( activity[getFaninVar1(v)] > activity[getFaninVar0(v)] ) + jheap.update( JustKey( activity[getFaninVar1(v)], v, index ) ); + else + jheap.update( JustKey( activity[getFaninVar0(v)], v, index ) ); +} + +inline void Solver::uncheckedEnqueue2(Lit p, CRef from) +{ + //assert( isRoundWatch(var(p)) ); // inplace sorting guarantee this + assert(value(p) == l_Undef); + assigns[var(p)] = lbool(!sign(p)); + vardata[var(p)] = mkVarData(from, decisionLevel()); + trail.push_(p); +} + +inline void Solver::ResetJustData(bool fCleanMemory){ + jhead = 0; + jheap .clear_( fCleanMemory ); +} + +inline Lit Solver::pickJustLit( int& index ){ + Var next = var_Undef; + Lit jlit = lit_Undef; + + for( ; jhead < trail.size() ; jhead++ ){ + Var x = var(trail[jhead]); + if( !decisionLevel() && !isRoundWatch(x) ) continue; + if( isJReason(x) && l_Undef == value( getFaninVar0(x) ) && l_Undef == value( getFaninVar1(x) ) ) + pushJustQueue(x,jhead); + } + + while( ! jheap.empty() ){ + next = jheap.removeMin(index); + if( ! var2NodeData[next].now ) + continue; + + assert(isJReason(next)); + if( lit_Undef != (jlit = gateJustFanin(next)) ){ + //assert( jheap.prev.key() == activity[getFaninVar0(next)] || jheap.prev.key() == activity[getFaninVar1(next)] ); + break; + } + gateAddJwatch(next,index); + } + + return jlit; +} + + +inline void Solver::gateAddJwatch(Var v,int index){ + assert(v < nVars()); + assert(isJReason(v)); + + lbool val0, val1; + Var var0, var1; + var0 = getFaninVar0(v); + var1 = getFaninVar1(v); + val0 = value(getFaninLit0(v)); + val1 = value(getFaninLit1(v)); + + assert( !isAND(v) || l_False == val0 || l_False == val1 ); + assert( isAND(v) || (l_Undef != val0 && l_Undef != val1) ); + + if( (val0 == l_False && val1 == l_False) || !isAND(v) ){ + addJwatch(vardata[var0].level < vardata[var1].level? var0: var1, v, index); + return; + } + + addJwatch(l_False == val0? var0: var1, v, index); + + return; +} + +inline void Solver::updateJustActivity( Var v ){ + if( ! var2NodeData[v].sort ) + inplace_sort(v); + + int nFanout = 0; + for(Lit lfo = var2Fanout0[ v ]; nFanout < var2NodeData[v].sort; lfo = var2FanoutN[ toInt(lfo) ], nFanout ++ ){ + Var x = var(lfo); + if( var2NodeData[x].now && jheap.inHeap(x) ){ + if( activity[getFaninVar1(x)] > activity[getFaninVar0(x)] ) + jheap.update( JustKey( activity[getFaninVar1(x)], x, jheap.data_attr(x) ) ); + else + jheap.update( JustKey( activity[getFaninVar0(x)], x, jheap.data_attr(x) ) ); + } + } +} + + +inline void Solver::addJwatch( Var host, Var member, int index ){ + assert(level(host) >= level(member)); + jnext[index] = jlevel[level(host)]; + jlevel[level(host)] = index; +} + +/* + * circuit propagation + */ + +inline void Solver::justCheck(){ + Lit lit; + int i, nJustFail = 0; + for(i=0; i<trail.size(); i++){ + Var x = var(trail[i]); + if( ! isRoundWatch(x) ) + continue; + if( !isJReason(x) ) + continue; + if( lit_Undef != (lit = gateJustFanin(x)) ){ + printf("\t%8d is not justified (value=%d, level=%3d)\n", x, l_True == value(x)? 1: 0, vardata[x].level), nJustFail ++ ; + + assert(false); + } + } + if( nJustFail ) + printf("%d just-fails\n", nJustFail); +} +/** +inline void Solver::delVarFaninLits( Var v ){ + if( toLit(~0) != getFaninLit0(v) ){ + if( toLit(~0) == var2FanoutP[ (v<<1) + 0 ] ){ + // head of linked-list + Lit root = mkLit(getFaninVar0(v)); + Lit next = var2FanoutN[ (v<<1) + 0 ]; + if( toLit(~0) != next ){ + assert( var2Fanout0[ toInt(root) ] == toLit((v<<1) + 0) ); + assert( var2FanoutP[ toInt(next) ] == toLit((v<<1) + 0) ); + var2Fanout0[ getFaninVar0(v) ] = next; + var2FanoutP[ toInt(next) ] = toLit(~0); + } + } else { + Lit prev = var2FanoutP[ (v<<1) + 0 ]; + Lit next = var2FanoutN[ (v<<1) + 0 ]; + if( toLit(~0) != next ){ + assert( var2FanoutN[ toInt(prev) ] == toLit((v<<1) + 0) ); + assert( var2FanoutP[ toInt(next) ] == toLit((v<<1) + 0) ); + var2FanoutN[ toInt(prev) ] = next; + var2FanoutP[ toInt(next) ] = prev; + } + } + } + + + if( toLit(~0) != getFaninLit1(v) ){ + if( toLit(~0) == var2FanoutP[ (v<<1) + 1 ] ){ + // head of linked-list + Lit root = mkLit(getFaninVar1(v)); + Lit next = var2FanoutN[ (v<<1) + 1 ]; + if( toLit(~0) != next ){ + assert( var2Fanout0[ toInt(root) ] == toLit((v<<1) + 1) ); + assert( var2FanoutP[ toInt(next) ] == toLit((v<<1) + 1) ); + var2Fanout0[ getFaninVar1(v) ] = next; + var2FanoutP[ toInt(next) ] = toLit(~0); + } + } else { + Lit prev = var2FanoutP[ (v<<1) + 1 ]; + Lit next = var2FanoutN[ (v<<1) + 1 ]; + if( toLit(~0) != next ){ + assert( var2FanoutN[ toInt(prev) ] == toLit((v<<1) + 1) ); + assert( var2FanoutP[ toInt(next) ] == toLit((v<<1) + 1) ); + var2FanoutN[ toInt(prev) ] = next; + var2FanoutP[ toInt(next) ] = prev; + } + } + } + + var2FanoutP [ (v<<1) + 0 ] = toLit(~0); + var2FanoutP [ (v<<1) + 1 ] = toLit(~0); + var2FanoutN [ (v<<1) + 0 ] = toLit(~0); + var2FanoutN [ (v<<1) + 1 ] = toLit(~0); + var2FaninLits[ (v<<1) + 0 ] = toLit(~0); + var2FaninLits[ (v<<1) + 1 ] = toLit(~0); +} +**/ +inline void Solver::setVarFaninLits( Var v, Lit lit1, Lit lit2 ){ + assert( var(lit1) != var(lit2) ); + int mincap = var(lit1) < var(lit2)? var(lit2): var(lit1); + mincap = (v < mincap? mincap: v) + 1; + + var2NodeData[ v ].lit0 = lit1; + var2NodeData[ v ].lit1 = lit2; + + + assert( toLit(~0) != lit1 && toLit(~0) != lit2 ); + + var2FanoutN[ (v<<1) + 0 ] = var2Fanout0[ var(lit1) ]; + var2FanoutN[ (v<<1) + 1 ] = var2Fanout0[ var(lit2) ]; + var2Fanout0[ var(lit1) ] = toLit( (v<<1) + 0 ); + var2Fanout0[ var(lit2) ] = toLit( (v<<1) + 1 ); + + //if( toLit(~0) != var2FanoutN[ (v<<1) + 0 ] ) + // var2FanoutP[ toInt(var2FanoutN[ (v<<1) + 0 ]) ] = toLit((v<<1) + 0); + + //if( toLit(~0) != var2FanoutN[ (v<<1) + 1 ] ) + // var2FanoutP[ toInt(var2FanoutN[ (v<<1) + 1 ]) ] = toLit((v<<1) + 1); +} + + +inline bool Solver::isTwoFanin( Var v ) const { + Lit lit0 = var2NodeData[ v ].lit0; + Lit lit1 = var2NodeData[ v ].lit1; + assert( toLit(~0) == lit0 || var(lit0) < nVars() ); + assert( toLit(~0) == lit1 || var(lit1) < nVars() ); + lit0.x = lit1.x = 0; // suppress the warning - alanmi + return toLit(~0) != var2NodeData[ v ].lit0 && toLit(~0) != var2NodeData[ v ].lit1; +} + +// this implementation return the last conflict encountered +// which follows minisat concept +inline CRef Solver::gatePropagate( Lit p ){ + CRef confl = CRef_Undef, stats; + if( justUsage() < 2 ) + return CRef_Undef; + + if( ! isRoundWatch(var(p)) ) + return CRef_Undef; + + if( ! isTwoFanin( var(p) ) ) + goto check_fanout; + + + // check fanin consistency + if( CRef_Undef != (stats = gatePropagateCheckThis( var(p) )) ){ + confl = stats; + if( l_True == value(var(p)) ) + return confl; + } + + // check fanout consistency +check_fanout: + assert( var(p) < var2Fanout0.size() ); + + if( ! var2NodeData[var(p)].sort ) + inplace_sort(var(p)); + + int nFanout = 0; + for( Lit lfo = var2Fanout0[ var(p) ]; nFanout < var2NodeData[var(p)].sort; lfo = var2FanoutN[ toInt(lfo) ], nFanout ++ ) + { + if( CRef_Undef != (stats = gatePropagateCheckFanout( var(p), lfo )) ){ + confl = stats; + if( l_True == value(var(lfo)) ) + return confl; + } + } + + return confl; +} + +inline CRef Solver::gatePropagateCheckFanout( Var v, Lit lfo ){ + Lit faninLit = sign(lfo)? getFaninLit1(var(lfo)): getFaninLit0(var(lfo)); + assert( var(faninLit) == v ); + if( isAND(var(lfo)) ){ + if( l_False == value(faninLit) ) + { + if( l_False == value(var(lfo)) ) + return CRef_Undef; + + if( l_True == value(var(lfo)) ) + return Var2CRef(var(lfo)); + + var2NodeData[var(lfo)].dir = sign(lfo); + uncheckedEnqueue2(~mkLit(var(lfo)), Var2CRef( var(lfo) ) ); + } else { + assert( l_True == value(faninLit) ); + + if( l_True == value(var(lfo)) ) + return CRef_Undef; + + // check value of the other fanin + Lit faninLitP = sign(lfo)? getFaninLit0(var(lfo)): getFaninLit1(var(lfo)); + if( l_False == value(var(lfo)) ){ + + if( l_False == value(faninLitP) ) + return CRef_Undef; + + if( l_True == value(faninLitP) ) + return Var2CRef(var(lfo)); + + uncheckedEnqueue2( ~faninLitP, Var2CRef( var(lfo) ) ); + } + else + if( l_True == value(faninLitP) ) + uncheckedEnqueue2( mkLit(var(lfo)), Var2CRef( var(lfo) ) ); + } + } else { // xor scope + // check value of the other fanin + Lit faninLitP = sign(lfo)? getFaninLit0(var(lfo)): getFaninLit1(var(lfo)); + + lbool val0, val1, valo; + val0 = value(faninLit ); + val1 = value(faninLitP); + valo = value(var(lfo)); + + if( l_Undef == val1 && l_Undef == valo ) + return CRef_Undef; + else + if( l_Undef == val1 ) + uncheckedEnqueue2( ~faninLitP ^ ( (l_True == val0) ^ (l_True == valo) ), Var2CRef( var(lfo) ) ); + else + if( l_Undef == valo ) + uncheckedEnqueue2( ~mkLit( var(lfo), (l_True == val0) ^ (l_True == val1) ), Var2CRef( var(lfo) ) ); + else + if( l_False == (valo ^ (val0 == val1)) ) + return Var2CRef(var(lfo)); + + } + + return CRef_Undef; +} + +inline CRef Solver::gatePropagateCheckThis( Var v ){ + CRef confl = CRef_Undef; + if( isAND(v) ){ + if( l_False == value(v) ){ + if( l_True == value(getFaninLit0(v)) && l_True == value(getFaninLit1(v)) ) + return Var2CRef(v); + + if( l_False == value(getFaninLit0(v)) || l_False == value(getFaninLit1(v)) ) + return CRef_Undef; + + if( l_True == value(getFaninLit0(v)) ) + uncheckedEnqueue2(~getFaninLit1( v ), Var2CRef( v ) ); + if( l_True == value(getFaninLit1(v)) ) + uncheckedEnqueue2(~getFaninLit0( v ), Var2CRef( v ) ); + } else { + assert( l_True == value(v) ); + if( l_False == value(getFaninLit0(v)) || l_False == value(getFaninLit1(v)) ) + confl = Var2CRef(v); + + if( l_Undef == value( getFaninLit0( v )) ) + uncheckedEnqueue2( getFaninLit0( v ), Var2CRef( v ) ); + + if( l_Undef == value( getFaninLit1( v )) ) + uncheckedEnqueue2( getFaninLit1( v ), Var2CRef( v ) ); + + } + } else { // xor scope + lbool val0, val1, valo; + val0 = value(getFaninLit0(v)); + val1 = value(getFaninLit1(v)); + valo = value(v); + if( l_Undef == val0 && l_Undef == val1 ) + return CRef_Undef; + if( l_Undef == val0 ) + uncheckedEnqueue2(~getFaninLit0( v ) ^ ( (l_True == val1) ^ (l_True == valo) ), Var2CRef( v ) ); + else + if( l_Undef == val1 ) + uncheckedEnqueue2(~getFaninLit1( v ) ^ ( (l_True == val0) ^ (l_True == valo) ), Var2CRef( v ) ); + else + if( l_False == (valo ^ (val0 == val1)) ) + return Var2CRef(v); + } + + return confl; +} + +inline CRef Solver::getConfClause( CRef r ){ + if( !isGateCRef(r) ) + return r; + Var v = CRef2Var(r); + assert( isTwoFanin(v) ); + + if(isAND(v)){ + if( l_False == value(v) ){ + setItpcSize(3); + Clause& c = ca[itpc]; + c[0] = mkLit(v); + c[1] = ~getFaninLit0( v ); + c[2] = ~getFaninLit1( v ); + } else { + setItpcSize(2); + Clause& c = ca[itpc]; + c[0] = ~mkLit(v); + + lbool val0 = value(getFaninLit0(v)); + lbool val1 = value(getFaninLit1(v)); + + if( l_False == val0 && l_False == val1 ) + c[1] = level(getFaninVar0(v)) < level(getFaninVar1(v))? getFaninLit0( v ): getFaninLit1( v ); + else + if( l_False == val0 ) + c[1] = getFaninLit0( v ); + else + c[1] = getFaninLit1( v ); + } + } else { // xor scope + setItpcSize(3); + Clause& c = ca[itpc]; + c[0] = mkLit(v, l_True == value(v)); + c[1] = mkLit(getFaninVar0(v), l_True == value(getFaninVar0(v))); + c[2] = mkLit(getFaninVar1(v), l_True == value(getFaninVar1(v))); + } + + + return itpc; +} + +inline void Solver::setItpcSize( int sz ){ + assert( 3 >= sz ); + assert( CRef_Undef != itpc ); + ca[itpc].header.size = sz; +} + +inline CRef Solver::interpret( Var v, Var t ) +{ // get gate-clause on implication graph + assert( isTwoFanin(v) ); + + lbool val0, val1, valo; + Var var0, var1; + var0 = getFaninVar0( v ); + var1 = getFaninVar1( v ); + val0 = value(var0); + val1 = value(var1); + valo = value( v ); + + // phased values + if(l_Undef != val0) val0 = val0 ^ getFaninC0( v ); + if(l_Undef != val1) val1 = val1 ^ getFaninC1( v ); + + + if( isAND(v) ){ + if( v == t ){ // tracing output + if( l_False == valo ){ + setItpcSize(2); + Clause& c = ca[itpc]; + c[0] = ~mkLit(v); + + c[1] = var2NodeData[v].dir ? getFaninLit1( v ): getFaninLit0( v ); + } else { + setItpcSize(3); + Clause& c = ca[itpc]; + c[0] = mkLit(v); + c[1] = ~getFaninLit0( v ); + c[2] = ~getFaninLit1( v ); + } + } else { + assert( t == var0 || t == var1 ); + if( l_False == valo ){ + setItpcSize(3); + Clause& c = ca[itpc]; + c[0] = ~getFaninLit0( v ); + c[1] = ~getFaninLit1( v ); + c[2] = mkLit(v); + if( t == var1 ) + c[1].x ^= c[0].x, c[0].x ^= c[1].x, c[1].x ^= c[0].x; + } else { + setItpcSize(2); + Clause& c = ca[itpc]; + c[0] = t == var0? getFaninLit0( v ): getFaninLit1( v ); + c[1] = ~mkLit(v); + } + } + } else { // xor scope + setItpcSize(3); + Clause& c = ca[itpc]; + if( v == t ){ + c[0] = mkLit(v, l_False == value(v)); + c[1] = mkLit(var0, l_True == value(var0)); + c[2] = mkLit(var1, l_True == value(var1)); + } else { + if( t == var0) + c[0] = mkLit(var0, l_False == value(var0)), c[1] = mkLit(var1, l_True == value(var1)); + else + c[1] = mkLit(var0, l_True == value(var0)), c[0] = mkLit(var1, l_False == value(var1)); + c[2] = mkLit(v, l_True == value(v)); + } + } + + return itpc; +} + +inline CRef Solver::castCRef( Lit p ){ + CRef cr = reason( var(p) ); + if( CRef_Undef == cr ) + return cr; + if( ! isGateCRef(cr) ) + return cr; + Var v = CRef2Var(cr); + return interpret(v,var(p)); +} + +inline void Solver::markCone( Var v ){ + if( var2TravId[v] >= travId ) + return; + var2TravId[v] = travId; + var2NodeData[v].sort = 0; + Var var0, var1; + var0 = getFaninVar0(v); + var1 = getFaninVar1(v); + if( !isTwoFanin(v) ) + return; + markCone( var0 ); + markCone( var1 ); +} + +inline void Solver::inplace_sort( Var v ){ + Lit w, next, prev; + prev= var2Fanout0[v]; + + if( toLit(~0) == prev ) return; + + if( isRoundWatch(var(prev)) ) + var2NodeData[v].sort ++ ; + + if( toLit(~0) == (w = var2FanoutN[toInt(prev)]) ) + return; + + while( toLit(~0) != w ){ + next = var2FanoutN[toInt(w)]; + if( isRoundWatch(var(w)) ) + var2NodeData[v].sort ++ ; + if( isRoundWatch(var(w)) && !isRoundWatch(var(prev)) ){ + var2FanoutN[toInt(w)] = var2Fanout0[v]; + var2Fanout0[v] = w; + var2FanoutN[toInt(prev)] = next; + } else + prev = w; + w = next; + } +} + +inline void Solver::prelocate( int base_var_num ){ + if( justUsage() ){ + var2FanoutN .prelocate( base_var_num << 1 ); + var2Fanout0 .prelocate( base_var_num ); + var2NodeData.prelocate( base_var_num ); + var2TravId .prelocate( base_var_num ); + jheap .prelocate( base_var_num ); + jlevel .prelocate( base_var_num ); + jnext .prelocate( base_var_num ); + } + watches .prelocate( base_var_num << 1 ); + watchesBin .prelocate( base_var_num << 1 ); + + decision .prelocate( base_var_num ); + trail .prelocate( base_var_num ); + assigns .prelocate( base_var_num ); + vardata .prelocate( base_var_num ); + activity .prelocate( base_var_num ); + + + seen .prelocate( base_var_num ); + permDiff .prelocate( base_var_num ); + polarity .prelocate( base_var_num ); +} + +}; + +ABC_NAMESPACE_IMPL_END + +#endif diff --git a/src/sat/glucose2/Constants.h b/src/sat/glucose2/Constants.h new file mode 100644 index 00000000..4cccad24 --- /dev/null +++ b/src/sat/glucose2/Constants.h @@ -0,0 +1,33 @@ +/************************************************************************************[Constants.h] + Glucose -- Copyright (c) 2009, Gilles Audemard, Laurent Simon + CRIL - Univ. Artois, France + LRI - Univ. Paris Sud, France + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#define DYNAMICNBLEVEL +#define CONSTANTREMOVECLAUSE +#define UPDATEVARACTIVITY + +// Constants for clauses reductions +#define RATIOREMOVECLAUSES 2 + + + +// Constants for restarts +#define LOWER_BOUND_FOR_BLOCKING_RESTART 10000 + diff --git a/src/sat/glucose2/Dimacs.h b/src/sat/glucose2/Dimacs.h new file mode 100644 index 00000000..1d6a0bed --- /dev/null +++ b/src/sat/glucose2/Dimacs.h @@ -0,0 +1,93 @@ +/****************************************************************************************[Dimacs.h] +Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson +Copyright (c) 2007-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#ifndef Glucose_Dimacs_h +#define Glucose_Dimacs_h + +#include <stdio.h> + +#include "sat/glucose2/ParseUtils.h" +#include "sat/glucose2/SolverTypes.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace Gluco2 { + +//================================================================================================= +// DIMACS Parser: + +template<class B, class Solver> +static void readClause(B& in, Solver& S, vec<Lit>& lits) { + int parsed_lit, var; + lits.clear(); + for (;;){ + parsed_lit = parseInt(in); + if (parsed_lit == 0) break; + var = abs(parsed_lit)-1; + while (var >= S.nVars()) S.newVar(); + lits.push( (parsed_lit > 0) ? mkLit(var) : ~mkLit(var) ); + } +} + +template<class B, class Solver> +static void parse_DIMACS_main(B& in, Solver& S) { + vec<Lit> lits; + int vars = 0; + int clauses = 0; + int cnt = 0; + for (;;){ + skipWhitespace(in); + if (*in == EOF) break; + else if (*in == 'p'){ + if (eagerMatch(in, "p cnf")){ + vars = parseInt(in); + clauses = parseInt(in); + // SATRACE'06 hack + // if (clauses > 4000000) + // S.eliminate(true); + }else{ + printf("PARSE ERROR! Unexpected char: %c\n", *in), exit(3); + } + } else if (*in == 'c' || *in == 'p') + skipLine(in); + else{ + cnt++; + readClause(in, S, lits); + S.addClause_(lits); } + } + if (vars != S.nVars()) + fprintf(stderr, "WARNING! DIMACS header mismatch: wrong number of variables.\n"); + if (cnt != clauses) + fprintf(stderr, "WARNING! DIMACS header mismatch: wrong number of clauses.\n"); +} + +// Inserts problem into solver. +// +template<class Solver> +static void parse_DIMACS(gzFile input_stream, Solver& S) { + StreamBuffer in(input_stream); + parse_DIMACS_main(in, S); } + +//================================================================================================= +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/src/sat/glucose2/Glucose2.cpp b/src/sat/glucose2/Glucose2.cpp new file mode 100644 index 00000000..7a8b265b --- /dev/null +++ b/src/sat/glucose2/Glucose2.cpp @@ -0,0 +1,1749 @@ +/***************************************************************************************[Solver.cc] + Glucose -- Copyright (c) 2013, Gilles Audemard, Laurent Simon + CRIL - Univ. Artois, France + LRI - Univ. Paris Sud, France + +Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of +Glucose are exactly the same as Minisat on which it is based on. (see below). + +--------------- + +Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson +Copyright (c) 2007-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ +#include <math.h> + +#include "sat/glucose2/Sort.h" +#include "sat/glucose2/Constants.h" +#include "sat/glucose2/System.h" +#include "sat/glucose2/Solver.h" + +#include "sat/glucose2/CGlucose.h" + +ABC_NAMESPACE_IMPL_START + +using namespace Gluco2; + +//================================================================================================= +// Options: +namespace Gluco2 { +static const char* _cat = "CORE"; +static const char* _cr = "CORE -- RESTART"; +static const char* _cred = "CORE -- REDUCE"; +static const char* _cm = "CORE -- MINIMIZE"; +static const char* _certified = "CORE -- CERTIFIED UNSAT"; + + + + +static BoolOption opt_incremental (_cat,"incremental", "Use incremental SAT solving", false); +static DoubleOption opt_K (_cr, "K", "The constant used to force restart", 0.8, DoubleRange(0, false, 1, false)); +static DoubleOption opt_R (_cr, "R", "The constant used to block restart", 1.4, DoubleRange(1, false, 5, false)); +static IntOption opt_size_lbd_queue (_cr, "szLBDQueue", "The size of moving average for LBD (restarts)", 50, IntRange(10, INT32_MAX)); +static IntOption opt_size_trail_queue (_cr, "szTrailQueue", "The size of moving average for trail (block restarts)", 5000, IntRange(10, INT32_MAX)); + +static IntOption opt_first_reduce_db (_cred, "firstReduceDB", "The number of conflicts before the first reduce DB", 2000, IntRange(0, INT32_MAX)); +static IntOption opt_inc_reduce_db (_cred, "incReduceDB", "Increment for reduce DB", 300, IntRange(0, INT32_MAX)); +static IntOption opt_spec_inc_reduce_db (_cred, "specialIncReduceDB", "Special increment for reduce DB", 1000, IntRange(0, INT32_MAX)); +static IntOption opt_lb_lbd_frozen_clause (_cred, "minLBDFrozenClause", "Protect clauses if their LBD decrease and is lower than (for one turn)", 30, IntRange(0, INT32_MAX)); + +static IntOption opt_lb_size_minimzing_clause (_cm, "minSizeMinimizingClause", "The min size required to minimize clause", 30, IntRange(3, INT32_MAX)); +static IntOption opt_lb_lbd_minimzing_clause (_cm, "minLBDMinimizingClause", "The min LBD required to minimize clause", 6, IntRange(3, INT32_MAX)); + + +static DoubleOption opt_var_decay (_cat, "var-decay", "The variable activity decay factor", 0.8, DoubleRange(0, false, 1, false)); +static DoubleOption opt_clause_decay (_cat, "cla-decay", "The clause activity decay factor", 0.999, DoubleRange(0, false, 1, false)); +static DoubleOption opt_random_var_freq (_cat, "rnd-freq", "The frequency with which the decision heuristic tries to choose a random variable", 0, DoubleRange(0, true, 1, true)); +static DoubleOption opt_random_seed (_cat, "rnd-seed", "Used by the random variable selection", 91648253, DoubleRange(0, false, HUGE_VAL, false)); +static IntOption opt_ccmin_mode (_cat, "ccmin-mode", "Controls conflict clause minimization (0=none, 1=basic, 2=deep)", 2, IntRange(0, 2)); +static IntOption opt_phase_saving (_cat, "phase-saving", "Controls the level of phase saving (0=none, 1=limited, 2=full)", 2, IntRange(0, 2)); +static BoolOption opt_rnd_init_act (_cat, "rnd-init", "Randomize the initial activity", false); +/* +static IntOption opt_restart_first (_cat, "rfirst", "The base restart interval", 100, IntRange(1, INT32_MAX)); +static DoubleOption opt_restart_inc (_cat, "rinc", "Restart interval increase factor", 2, DoubleRange(1, false, HUGE_VAL, false)); +*/ +static DoubleOption opt_garbage_frac (_cat, "gc-frac", "The fraction of wasted memory allowed before a garbage collection is triggered", 0.20, DoubleRange(0, false, HUGE_VAL, false)); + + +BoolOption opt_certified_ (_certified, "certified", "Certified UNSAT using DRUP format", false ); +StringOption opt_certified_file_ (_certified, "certified-output", "Certified UNSAT output file", "NULL"); +}; + +//================================================================================================= +// Constructor/Destructor: + + +Solver::Solver() : + + // Parameters (user settable): + // + SolverType(0) + , pCnfFunc(NULL) + , nCallConfl(1000) + , terminate_search_early(false) + , pstop(NULL) + , nRuntimeLimit(0) + + , verbosity (0) + , verbEveryConflicts(10000) + , showModel (0) + , K (opt_K) + , R (opt_R) + , sizeLBDQueue (opt_size_lbd_queue) + , sizeTrailQueue (opt_size_trail_queue) + , firstReduceDB (opt_first_reduce_db) + , incReduceDB (opt_inc_reduce_db) + , specialIncReduceDB (opt_spec_inc_reduce_db) + , lbLBDFrozenClause (opt_lb_lbd_frozen_clause) + , lbSizeMinimizingClause (opt_lb_size_minimzing_clause) + , lbLBDMinimizingClause (opt_lb_lbd_minimzing_clause) + , var_decay (opt_var_decay) + , clause_decay (opt_clause_decay) + , random_var_freq (opt_random_var_freq) + , random_seed (opt_random_seed) + , ccmin_mode (opt_ccmin_mode) + , phase_saving (opt_phase_saving) + , rnd_pol (false) + , rnd_init_act (opt_rnd_init_act) + , garbage_frac (opt_garbage_frac) + , certifiedOutput (NULL) + , certifiedUNSAT (opt_certified_) + // Statistics: (formerly in 'SolverStats') + // + , nbRemovedClauses(0),nbReducedClauses(0), nbDL2(0),nbBin(0),nbUn(0) , nbReduceDB(0) + , solves(0), starts(0), decisions(0), rnd_decisions(0), propagations(0),conflicts(0),conflictsRestarts(0),nbstopsrestarts(0),nbstopsrestartssame(0),lastblockatrestart(0) + , dec_vars(0), clauses_literals(0), learnts_literals(0), max_literals(0), tot_literals(0) + , curRestart(1) + + , ok (true) + , cla_inc (1) + , var_inc (1) + , watches (WatcherDeleted(ca)) + , watchesBin (WatcherDeleted(ca)) + , qhead (0) + , simpDB_assigns (-1) + , simpDB_props (0) + , order_heap (VarOrderLt(activity)) + , progress_estimate (0) + , remove_satisfied (true) + + // Resource constraints: + // + , conflict_budget (-1) + , propagation_budget (-1) + , asynch_interrupt (false) + , incremental(opt_incremental) + , nbVarsInitialFormula(INT32_MAX) + + #ifdef CGLUCOSE_EXP + //, jheap (JustOrderLt(this)) + , jheap (JustOrderLt2(this)) + #endif +{ + MYFLAG=0; + + // Initialize only first time. Useful for incremental solving, useless otherwise + lbdQueue.initSize(sizeLBDQueue); + trailQueue.initSize(sizeTrailQueue); + sumLBD = 0; + nbclausesbeforereduce = firstReduceDB; + totalTime4Sat=0;totalTime4Unsat=0; + nbSatCalls=0;nbUnsatCalls=0; + + + if(certifiedUNSAT) { + if(!strcmp(opt_certified_file_,"NULL")) { + certifiedOutput = fopen("/dev/stdout", "wb"); + } else { + certifiedOutput = fopen(opt_certified_file_, "wb"); + } + // fprintf(certifiedOutput,"o proof DRUP\n"); + } + + #ifdef CGLUCOSE_EXP + jhead= 0; + jftr = 0; + travId = 0; + travId_prev = 0; + + // allocate space for clause interpretation + vec<Lit> tmp; tmp.growTo(3); + itpc = ca.alloc(tmp); + ca[itpc].shrink( ca[itpc].size() ); + + #endif +} + + +Solver::~Solver() +{ +} + + +/**************************************************************** + Set the incremental mode +****************************************************************/ + +// This function set the incremental mode to true. +// You can add special code for this mode here. + +void Solver::setIncrementalMode() { + incremental = true; +} + +// Number of variables without selectors +void Solver::initNbInitialVars(int nb) { + nbVarsInitialFormula = nb; +} + + +//================================================================================================= +// Minor methods: + + +// Creates a new SAT variable in the solver. If 'decision' is cleared, variable will not be +// used as a decision variable (NOTE! This has effects on the meaning of a SATISFIABLE result). +// +Var Solver::newVar(bool sign, bool dvar) +{ + int v = nVars(); + watches .init(mkLit(v, false)); + watches .init(mkLit(v, true )); + watchesBin .init(mkLit(v, false)); + watchesBin .init(mkLit(v, true )); + assigns .push(l_Undef); + vardata .push(mkVarData(CRef_Undef, 0)); + //activity .push(0); + activity .push(rnd_init_act ? drand(random_seed) * 0.00001 : 0); + seen .push(0); + permDiff .push(0); + polarity .push(sign); + decision .push(); + trail .capacity(v+1); + + + #ifdef CGLUCOSE_EXP + //jreason .capacity(v+1); + if( justUsage() ){ + //jdata .push(mkJustData(false)); + //jwatch .push(mkJustWatch()); + + jlevel .push(-1); + jnext .push(-1); + + var2FanoutN.growTo( nVars()<<1, toLit(~0)); + //var2FanoutP.growTo( nVars()<<1, toLit(~0)); + var2Fanout0.growTo( nVars(), toLit(~0)); + var2NodeData.growTo( nVars(), mkNodeData()); + var2TravId .growTo( nVars(), 0); + + setDecisionVar(v, dvar, false); + } else + setDecisionVar(v, dvar); + #else + setDecisionVar(v, dvar); + #endif + + return v; +} + + + +bool Solver::addClause_(vec<Lit>& ps) +{ + assert(decisionLevel() == 0); + if (!ok) return false; + + if ( 0 ) { + for ( int i = 0; i < ps.size(); i++ ) + printf( "%s%d ", (toInt(ps[i]) & 1) ? "-":"", toInt(ps[i]) >> 1 ); + printf( "\n" ); + } + + // Check if clause is satisfied and remove false/duplicate literals: + sort(ps); + + vec<Lit> oc; + oc.clear(); + + Lit p; int i, j, flag = 0; + if(certifiedUNSAT) { + for (i = j = 0, p = lit_Undef; i < ps.size(); i++) { + oc.push(ps[i]); + if (value(ps[i]) == l_True || ps[i] == ~p || value(ps[i]) == l_False) + flag = 1; + } + } + + for (i = j = 0, p = lit_Undef; i < ps.size(); i++) + if (value(ps[i]) == l_True || ps[i] == ~p) + return true; + else if (value(ps[i]) != l_False && ps[i] != p) + ps[j++] = p = ps[i]; + ps.shrink_(i - j); + + if ( 0 ) { + for ( int i = 0; i < ps.size(); i++ ) + printf( "%s%d ", (toInt(ps[i]) & 1) ? "-":"", toInt(ps[i]) >> 1 ); + printf( "\n" ); + } + + if (flag && (certifiedUNSAT)) { + for (i = j = 0, p = lit_Undef; i < ps.size(); i++) + fprintf(certifiedOutput, "%i ", (var(ps[i]) + 1) * (-2 * sign(ps[i]) + 1)); + fprintf(certifiedOutput, "0\n"); + + fprintf(certifiedOutput, "d "); + for (i = j = 0, p = lit_Undef; i < oc.size(); i++) + fprintf(certifiedOutput, "%i ", (var(oc[i]) + 1) * (-2 * sign(oc[i]) + 1)); + fprintf(certifiedOutput, "0\n"); + } + + if (ps.size() == 0) + return ok = false; + else if (ps.size() == 1){ + uncheckedEnqueue(ps[0]); + return ok = (propagate() == CRef_Undef); + }else{ + CRef cr = ca.alloc(ps, false); + clauses.push(cr); + attachClause(cr); + } + + return true; +} + + +void Solver::attachClause(CRef cr) { + const Clause& c = ca[cr]; + + assert(c.size() > 1); + if(c.size()==2) { + watchesBin[~c[0]].push(Watcher(cr, c[1])); + watchesBin[~c[1]].push(Watcher(cr, c[0])); + } else { + watches[~c[0]].push(Watcher(cr, c[1])); + watches[~c[1]].push(Watcher(cr, c[0])); + } + if (c.learnt()) learnts_literals += c.size(); + else clauses_literals += c.size(); } + + + + +void Solver::detachClause(CRef cr, bool strict) { + const Clause& c = ca[cr]; + + assert(c.size() > 1); + if(c.size()==2) { + if (strict){ + remove(watchesBin[~c[0]], Watcher(cr, c[1])); + remove(watchesBin[~c[1]], Watcher(cr, c[0])); + }else{ + // Lazy detaching: (NOTE! Must clean all watcher lists before garbage collecting this clause) + watchesBin.smudge(~c[0]); + watchesBin.smudge(~c[1]); + } + } else { + if (strict){ + remove(watches[~c[0]], Watcher(cr, c[1])); + remove(watches[~c[1]], Watcher(cr, c[0])); + }else{ + // Lazy detaching: (NOTE! Must clean all watcher lists before garbage collecting this clause) + watches.smudge(~c[0]); + watches.smudge(~c[1]); + } + } + if (c.learnt()) learnts_literals -= c.size(); + else clauses_literals -= c.size(); } + + +void Solver::removeClause(CRef cr) { + + Clause& c = ca[cr]; + + if (certifiedUNSAT) { + fprintf(certifiedOutput, "d "); + for (int i = 0; i < c.size(); i++) + fprintf(certifiedOutput, "%i ", (var(c[i]) + 1) * (-2 * sign(c[i]) + 1)); + fprintf(certifiedOutput, "0\n"); + } + + detachClause(cr); + // Don't leave pointers to free'd memory! + if (locked(c)) vardata[var(c[0])].reason = CRef_Undef; + c.mark(1); + ca.free_(cr); +} + + +bool Solver::satisfied(const Clause& c) const { + if(incremental) // Check clauses with many selectors is too time consuming + return (value(c[0]) == l_True) || (value(c[1]) == l_True); + + // Default mode. + for (int i = 0; i < c.size(); i++) + if (value(c[i]) == l_True) + return true; + return false; +} + +/************************************************************ + * Compute LBD functions + *************************************************************/ + +inline unsigned int Solver::computeLBD(const vec<Lit> & lits,int end) { + int nblevels = 0; + MYFLAG++; + + if(incremental) { // ----------------- INCREMENTAL MODE + if(end==-1) end = lits.size(); + unsigned int nbDone = 0; + for(int i=0;i<lits.size();i++) { + if(nbDone>=end) break; + if(isSelector(var(lits[i]))) continue; + nbDone++; + int l = level(var(lits[i])); + if (permDiff[l] != MYFLAG) { + permDiff[l] = MYFLAG; + nblevels++; + } + } + } else { // -------- DEFAULT MODE. NOT A LOT OF DIFFERENCES... BUT EASIER TO READ + for(int i=0;i<lits.size();i++) { + int l = level(var(lits[i])); + if (permDiff[l] != MYFLAG) { + permDiff[l] = MYFLAG; + nblevels++; + } + } + } + + return nblevels; +} + +inline unsigned int Solver::computeLBD(const Clause &c) { + int nblevels = 0; + MYFLAG++; + + if(incremental) { // ----------------- INCREMENTAL MODE + int nbDone = 0; + for(int i=0;i<c.size();i++) { + if(nbDone>=c.sizeWithoutSelectors()) break; + if(isSelector(var(c[i]))) continue; + nbDone++; + int l = level(var(c[i])); + if (permDiff[l] != MYFLAG) { + permDiff[l] = MYFLAG; + nblevels++; + } + } + } else { // -------- DEFAULT MODE. NOT A LOT OF DIFFERENCES... BUT EASIER TO READ + for(int i=0;i<c.size();i++) { + int l = level(var(c[i])); + if (permDiff[l] != MYFLAG) { + permDiff[l] = MYFLAG; + nblevels++; + } + } + } + return nblevels; +} + + +/****************************************************************** + * Minimisation with binary reolution + ******************************************************************/ +void Solver::minimisationWithBinaryResolution(vec<Lit> &out_learnt) { + + // Find the LBD measure + unsigned int lbd = computeLBD(out_learnt); + Lit p = ~out_learnt[0]; + + if(lbd<=lbLBDMinimizingClause){ + MYFLAG++; + + for(int i = 1;i<out_learnt.size();i++) { + permDiff[var(out_learnt[i])] = MYFLAG; + } + + vec<Watcher>& wbin = watchesBin[p]; + int nb = 0; + for(int k = 0;k<wbin.size();k++) { + Lit imp = wbin[k].blocker; + if(permDiff[var(imp)]==MYFLAG && value(imp)==l_True) { + nb++; + permDiff[var(imp)]= MYFLAG-1; + } + } + int l = out_learnt.size()-1; + if(nb>0) { + nbReducedClauses++; + for(int i = 1;i<out_learnt.size()-nb;i++) { + if(permDiff[var(out_learnt[i])]!=MYFLAG) { + Lit p = out_learnt[l]; + out_learnt[l] = out_learnt[i]; + out_learnt[i] = p; + l--;i--; + } + } + + out_learnt.shrink_(nb); + + } + } +} + +// Revert to the state at given level (keeping all assignment at 'level' but not beyond). +// +void Solver::cancelUntil(int level) { + if (decisionLevel() > level){ + + #ifdef CGLUCOSE_EXP + if( 0 < justUsage() ){ + + for (int c = trail.size()-1; c >= trail_lim[level]; c--){ + Var x = var(trail[c]); + assigns [x] = l_Undef; + if (phase_saving > 1 || ((phase_saving == 1) && c > trail_lim.last())) + polarity[x] = sign(trail[c]); + //gateClearJwatch(x, level); + + var2NodeData[x].now = false; + } + for (int l = decisionLevel(); l > level; l -- ){ + int q = jlevel[l], k; + jlevel[l] = -1; + while( -1 != q ){ + k = jnext[q]; + jnext[q] = -1; + Var v = var(trail[q]); + if( Solver::level(v) <= level ){ + pushJustQueue(v,q); + } + q = k; + } + } + } else + #endif + for (int c = trail.size()-1; c >= trail_lim[level]; c--){ + Var x = var(trail[c]); + assigns [x] = l_Undef; + if (phase_saving > 1 || ((phase_saving == 1) && c > trail_lim.last())) + polarity[x] = sign(trail[c]); + insertVarOrder(x); + } + + jhead = qhead = trail_lim[level]; + + trail.shrink_(trail.size() - trail_lim[level]); + trail_lim.shrink_(trail_lim.size() - level); + } +} + + +//================================================================================================= +// Major methods: + + +Lit Solver::pickBranchLit() +{ + Var next = var_Undef; + + // Random decision: + if (drand(random_seed) < random_var_freq && !order_heap.empty()){ + next = order_heap[irand(random_seed,order_heap.size())]; + if (value(next) == l_Undef && decision[next]) + rnd_decisions++; } + + // Activity based decision: + while (next == var_Undef || value(next) != l_Undef || !decision[next]) + if (order_heap.empty()){ + next = var_Undef; + break; + }else + next = order_heap.removeMin(); + + return next == var_Undef ? lit_Undef : mkLit(next, rnd_pol ? drand(random_seed) < 0.5 : (polarity[next] != 0)); +} + + +/*_________________________________________________________________________________________________ +| +| analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&) -> [void] +| +| Description: +| Analyze conflict and produce a reason clause. +| +| Pre-conditions: +| * 'out_learnt' is assumed to be cleared. +| * Current decision level must be greater than root level. +| +| Post-conditions: +| * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'. +| * If out_learnt.size() > 1 then 'out_learnt[1]' has the greatest decision level of the +| rest of literals. There may be others from the same level though. +| +|________________________________________________________________________________________________@*/ +void Solver::analyze(CRef confl, vec<Lit>& out_learnt,vec<Lit>&selectors, int& out_btlevel,unsigned int &lbd,unsigned int &szWithoutSelectors) +{ + //double clk = Abc_Clock(); + heap_rescale = 0; + + int pathC = 0; + Lit p = lit_Undef; + + // Generate conflict clause: + // + out_learnt.push(); // (leave room for the asserting literal) + int index = trail.size() - 1; + + analyze_toclear.shrink_( analyze_toclear.size() ); + do{ + assert(confl != CRef_Undef); // (otherwise should be UIP) + + #ifdef CGLUCOSE_EXP + Clause& c = ca[ lit_Undef != p ? castCRef(p): getConfClause(confl) ]; + #else + Clause& c = ca[confl]; + #endif + + // Special case for binary clauses + // The first one has to be SAT + if( p != lit_Undef && c.size()==2 && value(c[0])==l_False) { + + assert(value(c[1])==l_True); + Lit tmp = c[0]; + c[0] = c[1], c[1] = tmp; + } + + if (c.learnt()) + claBumpActivity(c); + +#ifdef DYNAMICNBLEVEL + // DYNAMIC NBLEVEL trick (see competition'09 companion paper) + if(c.learnt() && c.lbd()>2) { + unsigned int nblevels = computeLBD(c); + if(nblevels+1<c.lbd() ) { // improve the LBD + if(c.lbd()<=lbLBDFrozenClause) { + c.setCanBeDel(false); + } + // seems to be interesting : keep it for the next round + c.setLBD(nblevels); // Update it + } + } +#endif + + + for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){ + Lit q = c[j]; + bool fBump = 0; + + if (!seen[var(q)] && level(var(q)) > 0){ + if(!isSelector(var(q))){ + fBump = 1; + varBumpActivity(var(q)); + } + seen[var(q)] = 1; + if (level(var(q)) >= decisionLevel()) { + if( fBump ) + analyze_toclear.push(q); + pathC++; + #ifdef UPDATEVARACTIVITY + // UPDATEVARACTIVITY trick (see competition'09 companion paper) + #ifdef CGLUCOSE_EXP + if(!isSelector(var(q)) && (reason(var(q))!= CRef_Undef) + && ! isGateCRef(reason(var(q))) && ca[reason(var(q))].learnt()) + lastDecisionLevel.push(q); + #else + if(!isSelector(var(q)) && (reason(var(q))!= CRef_Undef) && ca[reason(var(q))].learnt()) + lastDecisionLevel.push(q); + #endif + #endif + + } else { + if(isSelector(var(q))) { + assert(value(q) == l_False); + selectors.push(q); + } else + out_learnt.push(q); + } + } + } + + // Select next clause to look at: + while (!seen[var(trail[index--])]); + p = trail[index+1]; + confl = reason(var(p)); + seen[var(p)] = 0; + pathC--; + + }while (pathC > 0); + out_learnt[0] = ~p; + + // Simplify conflict clause: + // + int i, j; + + for(i = 0;i<selectors.size();i++) out_learnt.push(selectors[i]); + + + #ifdef CGLUCOSE_EXP + for(i = 0;i<out_learnt.size();i++) + analyze_toclear.push(out_learnt[i]); + #else + out_learnt.copyTo_(analyze_toclear); + #endif + if (ccmin_mode == 2){ + uint32_t abstract_level = 0; + for (i = 1; i < out_learnt.size(); i++) + abstract_level |= abstractLevel(var(out_learnt[i])); // (maintain an abstraction of levels involved in conflict) + + for (i = j = 1; i < out_learnt.size(); i++) + if (reason(var(out_learnt[i])) == CRef_Undef || !litRedundant(out_learnt[i], abstract_level)) + out_learnt[j++] = out_learnt[i]; + + }else if (ccmin_mode == 1){ + for (i = j = 1; i < out_learnt.size(); i++){ + Var x = var(out_learnt[i]); + + if (reason(x) == CRef_Undef) + out_learnt[j++] = out_learnt[i]; + else{ + #ifdef CGLUCOSE_EXP + Clause& c = ca[castCRef(out_learnt[i])]; + #else + Clause& c = ca[reason(var(out_learnt[i]))]; + #endif + // Thanks to Siert Wieringa for this bug fix! + for (int k = ((c.size()==2) ? 0:1); k < c.size(); k++) + if (!seen[var(c[k])] && level(var(c[k])) > 0){ + out_learnt[j++] = out_learnt[i]; + break; } + } + } + }else + i = j = out_learnt.size(); + + max_literals += out_learnt.size(); + out_learnt.shrink_(i - j); + tot_literals += out_learnt.size(); + + + /* *************************************** + Minimisation with binary clauses of the asserting clause + First of all : we look for small clauses + Then, we reduce clauses with small LBD. + Otherwise, this can be useless + */ + if(!incremental && out_learnt.size()<=lbSizeMinimizingClause) { + minimisationWithBinaryResolution(out_learnt); + } + // Find correct backtrack level: + // + if (out_learnt.size() == 1) + out_btlevel = 0; + else{ + int max_i = 1; + // Find the first literal assigned at the next-highest level: + for (int i = 2; i < out_learnt.size(); i++) + if (level(var(out_learnt[i])) > level(var(out_learnt[max_i]))) + max_i = i; + // Swap-in this literal at index 1: + Lit p = out_learnt[max_i]; + out_learnt[max_i] = out_learnt[1]; + out_learnt[1] = p; + out_btlevel = level(var(p)); + } + + + // Compute the size of the clause without selectors (incremental mode) + if(incremental) { + szWithoutSelectors = 0; + for(int i=0;i<out_learnt.size();i++) { + if(!isSelector(var((out_learnt[i])))) szWithoutSelectors++; + else if(i>0) break; + } + } else + szWithoutSelectors = out_learnt.size(); + + // Compute LBD + lbd = computeLBD(out_learnt,out_learnt.size()-selectors.size()); + + +#ifdef UPDATEVARACTIVITY + // UPDATEVARACTIVITY trick (see competition'09 companion paper) + if(lastDecisionLevel.size()>0) { + for(int i = 0;i<lastDecisionLevel.size();i++) { + Lit t = lastDecisionLevel[i]; + //assert( ca[reason(var(t))].learnt() ); + if(ca[reason(var(t))].lbd()<lbd) + varBumpActivity(var(t)); + } + lastDecisionLevel.shrink_( lastDecisionLevel.size() ); + } +#endif + + + if( justUsage() ){ + if( heap_rescale ) + { + for (j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0; + + analyze_toclear.shrink_( analyze_toclear.size() ); + for (j = 0; j < jheap.size(); j++){ + Var x = jheap[j]; + if( var2NodeData[x].now ) + analyze_toclear.push(mkLit(x)); + } + for (j = 0; j < analyze_toclear.size(); j++){ + Var x = var(analyze_toclear[j]); +// jdata[x].act_fanin = activity[getFaninVar0(x)] > activity[getFaninVar1(x)]? activity[getFaninVar0(x)]: activity[getFaninVar1(x)]; +// jheap.update(x); + if( activity[getFaninVar1(x)] > activity[getFaninVar0(x)] ) + jheap.update( JustKey( activity[getFaninVar1(x)], x, jheap.data_attr(x) ) ); + else + jheap.update( JustKey( activity[getFaninVar0(x)], x, jheap.data_attr(x) ) ); + } + + } else { + + for (j = 0; j < analyze_toclear.size(); j++) + { + seen[var(analyze_toclear[j])] = 0; + updateJustActivity(var(analyze_toclear[j])); + } + } + } else + for (j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0; // ('seen[]' is now cleared) + for(j = 0 ; j<selectors.size() ; j++) seen[var(selectors[j])] = 0; +} + + +// Check if 'p' can be removed. 'abstract_levels' is used to abort early if the algorithm is +// visiting literals at levels that cannot be removed later. +bool Solver::litRedundant(Lit p, uint32_t abstract_levels) +{ + analyze_stack.shrink_( analyze_stack.size() ); analyze_stack.push(p); + int top = analyze_toclear.size(); + while (analyze_stack.size() > 0){ + assert(reason(var(analyze_stack.last())) != CRef_Undef); + #ifdef CGLUCOSE_EXP + Clause& c = ca[castCRef(analyze_stack.last())]; analyze_stack.pop(); + #else + Clause& c = ca[reason(var(analyze_stack.last()))]; analyze_stack.pop(); + #endif + if(c.size()==2 && value(c[0])==l_False) { + assert(value(c[1])==l_True); + Lit tmp = c[0]; + c[0] = c[1], c[1] = tmp; + } + + for (int i = 1; i < c.size(); i++){ + Lit p = c[i]; + if (!seen[var(p)] && level(var(p)) > 0){ + if (reason(var(p)) != CRef_Undef && (abstractLevel(var(p)) & abstract_levels) != 0){ + seen[var(p)] = 1; + analyze_stack.push(p); + analyze_toclear.push(p); + }else{ + for (int j = top; j < analyze_toclear.size(); j++) + seen[var(analyze_toclear[j])] = 0; + analyze_toclear.shrink_(analyze_toclear.size() - top); + return false; + } + } + } + } + + return true; +} + + +/*_________________________________________________________________________________________________ +| +| analyzeFinal : (p : Lit) -> [void] +| +| Description: +| Specialized analysis procedure to express the final conflict in terms of assumptions. +| Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and +| stores the result in 'out_conflict'. +|________________________________________________________________________________________________@*/ +void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict) +{ + out_conflict.shrink_( out_conflict.size() ); + out_conflict.push(p); + + if (decisionLevel() == 0) + return; + + seen[var(p)] = 1; + + for (int i = trail.size()-1; i >= trail_lim[0]; i--){ + Var x = var(trail[i]); + if (seen[x]){ + if (reason(x) == CRef_Undef){ + assert(level(x) > 0); + out_conflict.push(~trail[i]); + }else{ + #ifdef CGLUCOSE_EXP + Clause& c = ca[castCRef(trail[i])]; + #else + Clause& c = ca[reason(x)]; + #endif + // for (int j = 1; j < c.size(); j++) Minisat (glucose 2.0) loop + // Bug in case of assumptions due to special data structures for Binary. + // Many thanks to Sam Bayless (sbayless@cs.ubc.ca) for discover this bug. + for (int j = ((c.size()==2) ? 0:1); j < c.size(); j++) + if (level(var(c[j])) > 0) + seen[var(c[j])] = 1; + } + + seen[x] = 0; + } + } + + seen[var(p)] = 0; +} + +void Solver::uncheckedEnqueue(Lit p, CRef from) +{ + if( justUsage() && !isRoundWatch(var(p)) ) + return; + assert(value(p) == l_Undef); + assigns[var(p)] = lbool(!sign(p)); + vardata[var(p)] = mkVarData(from, decisionLevel()); + trail.push_(p); +} + + +/*_________________________________________________________________________________________________ +| +| propagate : [void] -> [Clause*] +| +| Description: +| Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned, +| otherwise CRef_Undef. +| +| Post-conditions: +| * the propagation queue is empty, even if there was a conflict. +|________________________________________________________________________________________________@*/ +CRef Solver::propagate() +{ + CRef confl = CRef_Undef; + int num_props = 0; + watches.cleanAll(); + watchesBin.cleanAll(); + while (qhead < trail.size()){ + Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate. + vec<Watcher>& ws = watches[p]; + Watcher *i, *j, *end; + num_props++; + + #ifdef CGLUCOSE_EXP + if( 2 <= justUsage() ){ + CRef stats; + if( CRef_Undef != (stats = gatePropagate(p)) ){ + confl = stats; + if( l_True == value(var(p)) ) return confl; + } + } + #endif + + // First, Propagate binary clauses + vec<Watcher>& wbin = watchesBin[p]; + for(int k = 0;k<wbin.size();k++) { + Lit imp = wbin[k].blocker; + if(value(imp) == l_False) { + return wbin[k].cref; + } + if(value(imp) == l_Undef) { + uncheckedEnqueue(imp,wbin[k].cref); + } + } + + + + for (i = j = (Watcher*)ws, end = i + ws.size(); i != end;){ + // Try to avoid inspecting the clause: + Lit blocker = i->blocker; + if (value(blocker) == l_True){ + *j++ = *i++; continue; } + + // Make sure the false literal is data[1]: + CRef cr = i->cref; + Clause& c = ca[cr]; + Lit false_lit = ~p; + if (c[0] == false_lit) + c[0] = c[1], c[1] = false_lit; + assert(c[1] == false_lit); + i++; + + // If 0th watch is true, then clause is already satisfied. + Lit first = c[0]; + Watcher w = Watcher(cr, first); + if (first != blocker && value(first) == l_True){ + *j++ = w; continue; } + + // Look for new watch: + if(incremental) { // ----------------- INCREMENTAL MODE + int choosenPos = -1; + for (int k = 2; k < c.size(); k++) { + + if (value(c[k]) != l_False){ + if(decisionLevel()>assumptions.size()) { + choosenPos = k; + break; + } else { + choosenPos = k; + + if(value(c[k])==l_True || !isSelector(var(c[k]))) { + break; + } + } + + } + } + if(choosenPos!=-1) { + c[1] = c[choosenPos]; c[choosenPos] = false_lit; + watches[~c[1]].push(w); + goto NextClause; } + } else { // ----------------- DEFAULT MODE (NOT INCREMENTAL) + for (int k = 2; k < c.size(); k++) { + + if (value(c[k]) != l_False){ + c[1] = c[k]; c[k] = false_lit; + watches[~c[1]].push(w); + goto NextClause; } + } + } + + // Did not find watch -- clause is unit under assignment: + *j++ = w; + if (value(first) == l_False){ + confl = cr; + qhead = trail.size(); + // Copy the remaining watches: + while (i < end) + *j++ = *i++; + }else { + uncheckedEnqueue(first, cr); + + + } + NextClause:; + } + ws.shrink_(i - j); + } + propagations += num_props; + simpDB_props -= num_props; + + return confl; +} + + + + + + +/*_________________________________________________________________________________________________ +| +| reduceDB : () -> [void] +| +| Description: +| Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked +| clauses are clauses that are reason to some assignment. Binary clauses are never removed. +|________________________________________________________________________________________________@*/ +struct reduceDB_lt { + ClauseAllocator& ca; + reduceDB_lt(ClauseAllocator& ca_) : ca(ca_) {} + bool operator () (CRef x, CRef y) { + + // Main criteria... Like in MiniSat we keep all binary clauses + if(ca[x].size()> 2 && ca[y].size()==2) return 1; + + if(ca[y].size()> 2 && ca[x].size()==2) return 0; + if(ca[x].size()==2 && ca[y].size()==2) return 0; + + // Second one based on literal block distance + if(ca[x].lbd()> ca[y].lbd()) return 1; + if(ca[x].lbd()< ca[y].lbd()) return 0; + + // Finally we can use old activity or size, we choose the last one + return ca[x].activity() < ca[y].activity(); + //return x->size() < y->size(); + //return ca[x].size() > 2 && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity()); } + } +}; + +void Solver::reduceDB() +{ + int i, j; + nbReduceDB++; + sort(learnts, reduceDB_lt(ca)); + + // We have a lot of "good" clauses, it is difficult to compare them. Keep more ! + if(ca[learnts[learnts.size() / RATIOREMOVECLAUSES]].lbd()<=3) nbclausesbeforereduce +=specialIncReduceDB; + // Useless :-) + if(ca[learnts.last()].lbd()<=5) nbclausesbeforereduce +=specialIncReduceDB; + + // Don't delete binary or locked clauses. From the rest, delete clauses from the first half + // Keep clauses which seem to be usefull (their lbd was reduce during this sequence) + + int limit = learnts.size() / 2; + for (i = j = 0; i < learnts.size(); i++){ + Clause& c = ca[learnts[i]]; + if (c.lbd()>2 && c.size() > 2 && c.canBeDel() && !locked(c) && (i < limit)) { + removeClause(learnts[i]); + nbRemovedClauses++; + } + else { + if(!c.canBeDel()) limit++; //we keep c, so we can delete an other clause + c.setCanBeDel(true); // At the next step, c can be delete + learnts[j++] = learnts[i]; + } + } + learnts.shrink_(i - j); + checkGarbage(); +} + + +void Solver::removeSatisfied(vec<CRef>& cs) +{ + int i, j; + for (i = j = 0; i < cs.size(); i++){ + Clause& c = ca[cs[i]]; + if (satisfied(c)) + removeClause(cs[i]); + else + cs[j++] = cs[i]; + } + cs.shrink_(i - j); +} + + +void Solver::rebuildOrderHeap() +{ + vec<Var> vs; + for (Var v = 0; v < nVars(); v++) + if (decision[v] && value(v) == l_Undef) + vs.push(v); + order_heap.build(vs); +} + + +/*_________________________________________________________________________________________________ +| +| simplify : [void] -> [bool] +| +| Description: +| Simplify the clause database according to the current top-level assigment. Currently, the only +| thing done here is the removal of satisfied clauses, but more things can be put here. +|________________________________________________________________________________________________@*/ +bool Solver::simplify() +{ + assert(decisionLevel() == 0); + + if (!ok || propagate() != CRef_Undef) + return ok = false; + + if (nAssigns() == simpDB_assigns || (simpDB_props > 0)) + return true; + + // Remove satisfied clauses: + removeSatisfied(learnts); + if (remove_satisfied) // Can be turned off. + removeSatisfied(clauses); + + checkGarbage(); + + #ifdef CGLUCOSE_EXP + if( !justUsage() ) + #endif + rebuildOrderHeap(); + + simpDB_assigns = nAssigns(); + simpDB_props = clauses_literals + learnts_literals; // (shouldn't depend on stats really, but it will do for now) + + return true; +} + + +/*_________________________________________________________________________________________________ +| +| search : (nof_conflicts : int) (params : const SearchParams&) -> [lbool] +| +| Description: +| Search for a model the specified number of conflicts. +| NOTE! Use negative value for 'nof_conflicts' indicate infinity. +| +| Output: +| 'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If +| all variables are decision variables, this means that the clause set is satisfiable. 'l_False' +| if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached. +|________________________________________________________________________________________________@*/ +lbool Solver::search(int nof_conflicts) +{ + assert(ok); + int backtrack_level; + int conflictC = 0; + vec<Lit> learnt_clause,selectors; + unsigned int nblevels,szWoutSelectors; + bool blocked=false; + starts++; + + for (;;){ + CRef confl = propagate(); + + // exact conflict limit + if ( !withinBudget() && confl != CRef_Undef ) { + lbdQueue.fastclear(); + cancelUntil(0); + return l_Undef; } + + if (confl != CRef_Undef){ + + // CONFLICT + conflicts++; conflictC++;conflictsRestarts++; + if(conflicts%5000==0 && var_decay<0.95) + var_decay += 0.01; + + if (verbosity >= 1 && conflicts%verbEveryConflicts==0){ + printf("c | %8d %7d %5d | %7d %8d %8d | %5d %8d %6d %8d | %6.3f %% \n", + (int)starts,(int)nbstopsrestarts, (int)(conflicts/starts), + (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]), nClauses(), (int)clauses_literals, + (int)nbReduceDB, nLearnts(), (int)nbDL2,(int)nbRemovedClauses, progressEstimate()*100); + } + if (decisionLevel() == 0) + return l_False; + + + trailQueue.push(trail.size()); + // BLOCK RESTART (CP 2012 paper) + if( conflictsRestarts>LOWER_BOUND_FOR_BLOCKING_RESTART && lbdQueue.isvalid() && trail.size()>R*trailQueue.getavg()) { + lbdQueue.fastclear(); + nbstopsrestarts++; + if(!blocked) {lastblockatrestart=starts;nbstopsrestartssame++;blocked=true;} + } + + learnt_clause.shrink_( learnt_clause.size() ); + selectors .shrink_( selectors.size() ); + analyze(confl, learnt_clause, selectors,backtrack_level,nblevels,szWoutSelectors); + + lbdQueue.push(nblevels); + sumLBD += nblevels; + cancelUntil(backtrack_level); + if (certifiedUNSAT) { + for (int i = 0; i < learnt_clause.size(); i++) + fprintf(certifiedOutput, "%i " , (var(learnt_clause[i]) + 1) * + (-2 * sign(learnt_clause[i]) + 1) ); + fprintf(certifiedOutput, "0\n"); + } + + if (learnt_clause.size() == 1){ + uncheckedEnqueue(learnt_clause[0]);nbUn++; + }else{ + CRef cr = ca.alloc(learnt_clause, true); + ca[cr].setLBD(nblevels); + ca[cr].setSizeWithoutSelectors(szWoutSelectors); + if(nblevels<=2) nbDL2++; // stats + if(ca[cr].size()==2) nbBin++; // stats + learnts.push(cr); + attachClause(cr); + + claBumpActivity(ca[cr]); + uncheckedEnqueue(learnt_clause[0], cr); + } + varDecayActivity(); + claDecayActivity(); + + }else{ + // Our dynamic restart, see the SAT09 competition compagnion paper + if ( (conflictsRestarts && lbdQueue.isvalid() && lbdQueue.getavg()*K > sumLBD/conflictsRestarts) || (pstop && *pstop) ) { + lbdQueue.fastclear(); + progress_estimate = progressEstimate(); + int bt = 0; + if(incremental) { // DO NOT BACKTRACK UNTIL 0.. USELESS + bt = (decisionLevel()<assumptions.size()) ? decisionLevel() : assumptions.size(); + } + cancelUntil(bt); + return l_Undef; + } + + // Simplify the set of problem clauses: + if (decisionLevel() == 0 && !simplify()) { + return l_False; + } + // Perform clause database reduction ! + if(conflicts>=curRestart* nbclausesbeforereduce) + { + assert(learnts.size()>0); + curRestart = (conflicts/ nbclausesbeforereduce)+1; + reduceDB(); + nbclausesbeforereduce += incReduceDB; + } + + Lit next = lit_Undef; + while (decisionLevel() < assumptions.size()){ + // Perform user provided assumption: + Lit p = assumptions[decisionLevel()]; + if (value(p) == l_True){ + // Dummy decision level: + newDecisionLevel(); + } else if (value(p) == l_False){ + analyzeFinal(~p, conflict); + return l_False; + } else { + next = p; + break; + } + } + + #ifdef CGLUCOSE_EXP + // pick from JustQueue + + if (0 < justUsage()) + if ( next == lit_Undef ){ + int index = -1; + decisions++; + next = pickJustLit( index ); + if(next == lit_Undef) + return l_True; + //addJwatch(var(next), j_reason); + jnext[index] = jlevel[decisionLevel()+1]; + jlevel[decisionLevel()+1] = index; + } + #endif + + if (next == lit_Undef){ + // New variable decision: + decisions++; + next = pickBranchLit(); + + if (next == lit_Undef){ + // Model found: + return l_True; + } + } + + // Increase decision level and enqueue 'next' + newDecisionLevel(); + uncheckedEnqueue(next); + } + } +} + + + +double Solver::progressEstimate() const +{ + double progress = 0; + double F = 1.0 / nVars(); + + for (int i = 0; i <= decisionLevel(); i++){ + int beg = i == 0 ? 0 : trail_lim[i - 1]; + int end = i == decisionLevel() ? trail.size() : trail_lim[i]; + progress += pow(F, i) * (end - beg); + } + + return progress / nVars(); +} + +void Solver::printIncrementalStats() { + + printf("c---------- Glucose Stats -------------------------\n"); + printf("c restarts : %ld\n", starts); + printf("c nb ReduceDB : %ld\n", nbReduceDB); + printf("c nb removed Clauses : %ld\n", nbRemovedClauses); + printf("c nb learnts DL2 : %ld\n", nbDL2); + printf("c nb learnts size 2 : %ld\n", nbBin); + printf("c nb learnts size 1 : %ld\n", nbUn); + + printf("c conflicts : %ld\n", conflicts); + printf("c decisions : %ld\n", decisions); + printf("c propagations : %ld\n", propagations); + + printf("c SAT Calls : %d in %g seconds\n", nbSatCalls, totalTime4Sat); + printf("c UNSAT Calls : %d in %g seconds\n", nbUnsatCalls, totalTime4Unsat); + printf("c--------------------------------------------------\n"); + + +} + + +// NOTE: assumptions passed in member-variable 'assumptions'. +lbool Solver::solve_() +{ + + #ifdef CGLUCOSE_EXP + ResetJustData(false); + #endif + + if(incremental && certifiedUNSAT) { + printf("Can not use incremental and certified unsat in the same time\n"); + exit(-1); + } + + conflict.shrink_(conflict.size()); + if (!ok){ + travId_prev = travId; + return l_False; + } + double curTime = cpuTime(); + + solves++; + + lbool status = l_Undef; + if(!incremental && verbosity>=1) { + printf("c ========================================[ MAGIC CONSTANTS ]==============================================\n"); + printf("c | Constants are supposed to work well together :-) |\n"); + printf("c | however, if you find better choices, please let us known... |\n"); + printf("c |-------------------------------------------------------------------------------------------------------|\n"); + printf("c | | | |\n"); + printf("c | - Restarts: | - Reduce Clause DB: | - Minimize Asserting: |\n"); + printf("c | * LBD Queue : %6d | * First : %6d | * size < %3d |\n",lbdQueue.maxSize(),nbclausesbeforereduce,lbSizeMinimizingClause); + printf("c | * Trail Queue : %6d | * Inc : %6d | * lbd < %3d |\n",trailQueue.maxSize(),incReduceDB,lbLBDMinimizingClause); + printf("c | * K : %6.2f | * Special : %6d | |\n",K,specialIncReduceDB); + printf("c | * R : %6.2f | * Protected : (lbd)< %2d | |\n",R,lbLBDFrozenClause); + printf("c | | | |\n"); +printf("c ==================================[ Search Statistics (every %6d conflicts) ]=========================\n",verbEveryConflicts); + printf("c | |\n"); + + printf("c | RESTARTS | ORIGINAL | LEARNT | Progress |\n"); + printf("c | NB Blocked Avg Cfc | Vars Clauses Literals | Red Learnts LBD2 Removed | | pol-inconsist\n"); + printf("c =========================================================================================================\n"); + } + + // Search: + int curr_restarts = 0; + while (status == l_Undef){ + status = search(0); // the parameter is useless in glucose, kept to allow modifications + if (!withinBudget() || terminate_search_early || (pstop && *pstop)) break; + if (nRuntimeLimit && Abc_Clock() > nRuntimeLimit) break; + curr_restarts++; + } + + if (!incremental && verbosity >= 1) + printf("c =========================================================================================================\n"); + + + if (certifiedUNSAT){ // Want certified output + if (status == l_False) + fprintf(certifiedOutput, "0\n"); + fclose(certifiedOutput); + } + + + if (status == l_True){ + + if( justUsage() ){ + JustModel.shrink_(JustModel.size()); + assert(jheap.empty()); + //JustModel.growTo(nVars()); + int i = 0, j = 0; + JustModel.push(toLit(0)); + for (; i < trail.size(); i++) + if( isRoundWatch(var(trail[i])) && !isTwoFanin(var(trail[i])) ) + JustModel.push(trail[i]), j++; + JustModel[0] = toLit(j); + } else { + // Extend & copy model: + model.shrink_(model.size()); + model.growTo(nVars()); + for (int i = 0; i < trail.size(); i++) model[ var(trail[i]) ] = value(var(trail[i])); + } + }else if (status == l_False && conflict.size() == 0) + ok = false; + + //#ifdef CGLUCOSE_EXP + //if(status == l_True && 0 < justUsage()) + // justCheck(); + //#endif + + cancelUntil(0); + + double finalTime = cpuTime(); + if(status==l_True) { + nbSatCalls++; + totalTime4Sat +=(finalTime-curTime); + } + if(status==l_False) { + nbUnsatCalls++; + totalTime4Unsat +=(finalTime-curTime); + } + + // ABC callback + if (pCnfFunc && !terminate_search_early) {// hack to avoid calling callback twise if the solver was terminated early + int * pCex = NULL; + int message = (status == l_True ? 1 : status == l_False ? 0 : -1); + if (status == l_True) { + pCex = new int[nVars()]; + for (int i = 0; i < nVars(); i++) + pCex[i] = (model[i] == l_True); + } + + int callback_result = pCnfFunc(pCnfMan, message, pCex); + assert(callback_result == 0); + } + else if (pCnfFunc) + terminate_search_early = false; // for next run + + travId_prev = travId; + return status; +} + +//================================================================================================= +// Writing CNF to DIMACS: +// +// FIXME: this needs to be rewritten completely. + +static Var mapVar(Var x, vec<Var>& map, Var& max) +{ + if (map.size() <= x || map[x] == -1){ + map.growTo(x+1, -1); + map[x] = max++; + } + return map[x]; +} + + +void Solver::toDimacs(FILE* f, Clause& c, vec<Var>& map, Var& max) +{ + if (satisfied(c)) return; + + for (int i = 0; i < c.size(); i++) + if (value(c[i]) != l_False) + fprintf(f, "%s%d ", sign(c[i]) ? "-" : "", mapVar(var(c[i]), map, max)+1); + fprintf(f, "0\n"); +} + + +void Solver::toDimacs(const char *file, const vec<Lit>& assumps) +{ + FILE* f = fopen(file, "wr"); + if (f == NULL) + fprintf(stderr, "could not open file %s\n", file), exit(1); + toDimacs(f, assumps); + fclose(f); +} + + +void Solver::toDimacs(FILE* f, const vec<Lit>& assumps) +{ + // Handle case when solver is in contradictory state: + if (!ok){ + fprintf(f, "p cnf 1 2\n1 0\n-1 0\n"); + return; } + + vec<Var> map; Var max = 0; + + // Cannot use removeClauses here because it is not safe + // to deallocate them at this point. Could be improved. + int i, cnt = 0; + for (i = 0; i < clauses.size(); i++) + if (!satisfied(ca[clauses[i]])) + cnt++; + + for (i = 0; i < clauses.size(); i++) + if (!satisfied(ca[clauses[i]])){ + Clause& c = ca[clauses[i]]; + for (int j = 0; j < c.size(); j++) + if (value(c[j]) != l_False) + mapVar(var(c[j]), map, max); + } + + // Assumptions are added as unit clauses: + cnt += assumptions.size(); + + fprintf(f, "p cnf %d %d\n", max, cnt); + + for (i = 0; i < assumptions.size(); i++){ + assert(value(assumptions[i]) != l_False); + fprintf(f, "%s%d 0\n", sign(assumptions[i]) ? "-" : "", mapVar(var(assumptions[i]), map, max)+1); + } + + for (i = 0; i < clauses.size(); i++) + toDimacs(f, ca[clauses[i]], map, max); + + if (verbosity > 0) + printf("Wrote %d clauses with %d variables.\n", cnt, max); +} + + +//================================================================================================= +// Garbage Collection methods: + +void Solver::relocAll(ClauseAllocator& to) +{ + #ifdef CGLUCOSE_EXP + if( CRef_Undef != itpc ){ + setItpcSize(3); + ca.reloc(itpc, to); + } + #endif + int v, s, i, j; + // All watchers: + // + // for (int i = 0; i < watches.size(); i++) + watches.cleanAll(); + watchesBin.cleanAll(); + for (v = 0; v < nVars(); v++) + for (s = 0; s < 2; s++){ + Lit p = mkLit(v, s != 0); + // printf(" >>> RELOCING: %s%d\n", sign(p)?"-":"", var(p)+1); + vec<Watcher>& ws = watches[p]; + for (j = 0; j < ws.size(); j++) + ca.reloc(ws[j].cref, to); + vec<Watcher>& ws2 = watchesBin[p]; + for (j = 0; j < ws2.size(); j++) + ca.reloc(ws2[j].cref, to); + } + + // All reasons: + // + for (i = 0; i < trail.size(); i++){ + Var v = var(trail[i]); + + #ifdef CGLUCOSE_EXP + if( isGateCRef(reason(v)) ) + continue; + #endif + if (reason(v) != CRef_Undef && (ca[reason(v)].reloced() || locked(ca[reason(v)]))) + ca.reloc(vardata[v].reason, to); + } + + // All learnt: + // + for (i = 0; i < learnts.size(); i++) + ca.reloc(learnts[i], to); + + // All original: + // + for (i = 0; i < clauses.size(); i++) + ca.reloc(clauses[i], to); +} + + +void Solver::garbageCollect() +{ + // Initialize the next region to a size corresponding to the estimated utilization degree. This + // is not precise but should avoid some unnecessary reallocations for the new region: + ClauseAllocator to(ca.size() - ca.wasted()); + + relocAll(to); + if (verbosity >= 2) + printf("| Garbage collection: %12d bytes => %12d bytes |\n", + ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size); + to.moveTo(ca); +} + +void Solver::reset() +{ + // Reset everything + ok = true; + K = (double)opt_K; + R = (double)opt_R; + firstReduceDB = opt_first_reduce_db; + var_decay = (double)opt_var_decay; + //max_var_decay = opt_max_var_decay; + solves = starts = decisions = propagations = conflicts = conflictsRestarts = 0; + curRestart = 1; + cla_inc = var_inc = 1; + watches.clear(false); // We don't free the memory, new calls should be of the same size order. + watchesBin.clear(false); + //unaryWatches.clear(false); + qhead = 0; + simpDB_assigns = -1; + simpDB_props = 0; + order_heap.clear(false); + progress_estimate = 0; + //lastLearntClause = CRef_Undef; + conflict_budget = -1; + propagation_budget = -1; + nbVarsInitialFormula = INT32_MAX; + totalTime4Sat = 0.; + totalTime4Unsat = 0.; + nbSatCalls = nbUnsatCalls = 0; + MYFLAG = 0; + lbdQueue.clear(false); + lbdQueue.initSize(sizeLBDQueue); + trailQueue.clear(false); + trailQueue.initSize(sizeTrailQueue); + sumLBD = 0; + nbclausesbeforereduce = firstReduceDB; + //stats.clear(); + //stats.growTo(coreStatsSize, 0); + clauses.clear(false); + learnts.clear(false); + //permanentLearnts.clear(false); + //unaryWatchedClauses.clear(false); + model .shrink_(model .size()); + conflict.shrink_(conflict.size()); + activity.shrink_(activity.size()); + assigns .shrink_(assigns .size()); + polarity.shrink_(polarity.size()); + //forceUNSAT.clear(false); + decision .shrink_(decision .size()); + trail .shrink_(trail .size()); + trail_lim .shrink_(trail_lim .size()); + vardata .shrink_(vardata .size()); + assumptions.shrink_(assumptions.size()); + nbpos .shrink_(nbpos .size()); + permDiff .shrink_(permDiff .size()); + #ifdef UPDATEVARACTIVITY + lastDecisionLevel.shrink_(lastDecisionLevel.size()); + #endif + ca.clear(); + seen .shrink_(seen.size()); + analyze_stack .shrink_(analyze_stack .size()); + analyze_toclear.shrink_(analyze_toclear.size()); + add_tmp.clear(false); + assumptionPositions.clear(false); + initialPositions.clear(false); + + #ifdef CGLUCOSE_EXP + + ResetJustData(false); + + //jwatch.shrink_(jwatch.size()); + //jdata .shrink_(jdata .size()); + + jhead = 0; + travId = 0; + travId_prev = 0; + var2TravId .shrink_(var2TravId.size()); + JustModel .shrink_(JustModel .size()); + jlevel .shrink_(jlevel.size()); + jnext .shrink_(jnext.size()); + + //var2FaninLits.shrink_(var2FaninLits.size()); + var2NodeData .shrink_(var2NodeData .size()); + var2Fanout0 .shrink_(var2Fanout0 .size()); + var2FanoutN .shrink_(var2FanoutN .size()); + //var2FanoutP.clear(false); + if( CRef_Undef != itpc ){ + itpc = CRef_Undef; // clause allocator has been cleared, do not worry + // allocate space for clause interpretation + vec<Lit> tmp; tmp.growTo(3); + itpc = ca.alloc(tmp); + ca[itpc].shrink( ca[itpc].size() ); + } + #endif +} + +ABC_NAMESPACE_IMPL_END diff --git a/src/sat/glucose2/Heap.h b/src/sat/glucose2/Heap.h new file mode 100644 index 00000000..d68229f6 --- /dev/null +++ b/src/sat/glucose2/Heap.h @@ -0,0 +1,163 @@ +/******************************************************************************************[Heap.h] +Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson +Copyright (c) 2007-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#ifndef Glucose_Heap_h +#define Glucose_Heap_h + +#include "sat/glucose2/Vec.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace Gluco2 { + +//================================================================================================= +// A heap implementation with support for decrease/increase key. + + +template<class Comp> +class Heap { + Comp lt; // The heap is a minimum-heap with respect to this comparator + vec<int> heap; // Heap of integers + vec<int> indices; // Each integers position (index) in the Heap + + // Index "traversal" functions + static inline int left (int i) { return i*2+1; } + static inline int right (int i) { return (i+1)*2; } + static inline int parent(int i) { return (i-1) >> 1; } + + + void percolateUp(int i) + { + int x = heap[i]; + int p = parent(i); + + while (i != 0 && lt(x, heap[p])){ + heap[i] = heap[p]; + indices[heap[p]] = i; + i = p; + p = parent(p); + } + heap [i] = x; + indices[x] = i; + } + + + void percolateDown(int i) + { + int x = heap[i]; + while (left(i) < heap.size()){ + int child = right(i) < heap.size() && lt(heap[right(i)], heap[left(i)]) ? right(i) : left(i); + if (!lt(heap[child], x)) break; + heap[i] = heap[child]; + indices[heap[i]] = i; + i = child; + } + heap [i] = x; + indices[x] = i; + } + + + public: + Heap(const Comp& c) : lt(c) { } + + int size () const { return heap.size(); } + bool empty () const { return heap.size() == 0; } + bool inHeap (int n) const { return n < indices.size() && indices[n] >= 0; } + int operator[](int index) const { assert(index < heap.size()); return heap[index]; } + + + void decrease (int n) { assert(inHeap(n)); percolateUp (indices[n]); } + void increase (int n) { assert(inHeap(n)); percolateDown(indices[n]); } + void prelocate (int ext_cap){ indices.prelocate(ext_cap); } + + // Safe variant of insert/decrease/increase: + void update(int n) + { + if (!inHeap(n)) + insert(n); + else { + percolateUp(indices[n]); + percolateDown(indices[n]); } + } + + + void insert(int n) + { + indices.growTo(n+1, -1); + assert(!inHeap(n)); + + indices[n] = heap.size(); + heap.push(n); + percolateUp(indices[n]); + } + + + int removeMin() + { + int x = heap[0]; + heap[0] = heap.last(); + indices[heap[0]] = 0; + indices[x] = -1; + heap.pop(); + if (heap.size() > 1) percolateDown(0); + return x; + } + + + // Rebuild the heap from scratch, using the elements in 'ns': + void build(vec<int>& ns) { + int i; + for (i = 0; i < heap.size(); i++) + indices[heap[i]] = -1; + heap.clear(); + + for (i = 0; i < ns.size(); i++){ + indices[ns[i]] = i; + heap.push(ns[i]); } + + for (i = heap.size() / 2 - 1; i >= 0; i--) + percolateDown(i); + } + + void clear(bool dealloc = false) + { + int i; + for (i = 0; i < heap.size(); i++) + indices[heap[i]] = -1; + heap.clear(dealloc); + } + void clear_(bool dealloc = false) + { + int i; + for (i = 0; i < heap.size(); i++) + indices[heap[i]] = -1; + + if( ! dealloc ) heap.shrink_( heap.size() ); + else heap.clear(true); + } +}; + + +//================================================================================================= +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/src/sat/glucose2/Heap2.h b/src/sat/glucose2/Heap2.h new file mode 100644 index 00000000..ef6d8302 --- /dev/null +++ b/src/sat/glucose2/Heap2.h @@ -0,0 +1,169 @@ +/******************************************************************************************[Heap.h] +Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson +Copyright (c) 2007-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#ifndef Glucose_Heap2_h +#define Glucose_Heap2_h + +#include "sat/glucose2/Vec.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace Gluco2 { + +//================================================================================================= +// A heap implementation with support for decrease/increase key. + + +template<class Comp, class Obj> +class Heap2 { + Comp lt; // The heap is a minimum-heap with respect to this comparator + vec<Obj> heap; // Heap of integers + vec<int> indices; // Each integers position (index) in the Heap + + // Index "traversal" functions + static inline int left (int i) { return i*2+1; } + static inline int right (int i) { return (i+1)*2; } + static inline int parent(int i) { return (i-1) >> 1; } + + inline int data (int i) const { return heap[i].data();} + + void percolateUp(int i) + { + Obj x = heap[i]; + int p = parent(i); + + while (i != 0 && lt(x, heap[p])){ + heap[i] = heap[p]; + indices[data(p)] = i; + i = p; + p = parent(p); + } + heap [i] = x; + indices[x.data()] = i; + } + + + void percolateDown(int i) + { + Obj x = heap[i]; + while (left(i) < heap.size()){ + int child = right(i) < heap.size() && lt(heap[right(i)], heap[left(i)]) ? right(i) : left(i); + if (!lt(heap[child], x)) break; + heap[i] = heap[child]; + indices[data(i)] = i; + i = child; + } + heap [i] = x; + indices[x.data()] = i; + } + + + public: + Heap2(const Comp& c) : lt(c) { } + + int size () const { return heap.size(); } + bool empty () const { return heap.size() == 0; } + bool inHeap (int n) const { return n < indices.size() && indices[n] >= 0; } + int operator[](int index) const { assert(index < heap.size()); return heap[index].data(); } + + + void decrease (int n) { assert(inHeap(n)); percolateUp (indices[n]); } + void increase (int n) { assert(inHeap(n)); percolateDown(indices[n]); } + void prelocate (int ext_cap){ indices.prelocate(ext_cap); } + int data_attr (int n) const { return heap[indices[n]].attr(); } + // Safe variant of insert/decrease/increase: + void update(const Obj& x) + { + int n = x.data(); + if (!inHeap(n)) + insert(x); + else { + heap[indices[x.data()]] = x; + percolateUp(indices[n]); + percolateDown(indices[n]); } + } + + + void insert(const Obj& x) + { + int n = x.data(); + indices.growTo(n+1, -1); + assert(!inHeap(n)); + + indices[n] = heap.size(); + heap.push(x); + percolateUp(indices[n]); + } + + //Obj prev; + int removeMin(int& _attr) + { + Obj x = heap[0]; + heap[0] = heap.last(); + indices[heap[0].data()] = 0; + indices[x.data()]= -1; + heap.pop(); + if (heap.size() > 1) percolateDown(0); + //prev = x; + _attr = x.attr(); + return x.data(); + } + + + // Rebuild the heap from scratch, using the elements in 'ns': +// void build(vec<int>& ns) { +// int i; +// for (i = 0; i < heap.size(); i++) +// indices[heap[i]] = -1; +// heap.clear(); +// +// for (i = 0; i < ns.size(); i++){ +// indices[ns[i]] = i; +// heap.push(ns[i]); } +// +// for (i = heap.size() / 2 - 1; i >= 0; i--) +// percolateDown(i); +// } + + void clear(bool dealloc = false) + { + int i; + for (i = 0; i < heap.size(); i++) + indices[heap[i].data()] = -1; + heap.clear(dealloc); + } + void clear_(bool dealloc = false) + { + int i; + for (i = 0; i < heap.size(); i++) + indices[heap[i].data()] = -1; + + if( ! dealloc ) heap.shrink_( heap.size() ); + else heap.clear(true); + } +}; + + +//================================================================================================= +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/src/sat/glucose2/IntTypes.h b/src/sat/glucose2/IntTypes.h new file mode 100644 index 00000000..3f75862b --- /dev/null +++ b/src/sat/glucose2/IntTypes.h @@ -0,0 +1,49 @@ +/**************************************************************************************[IntTypes.h] +Copyright (c) 2009-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#ifndef Glucose_IntTypes_h +#define Glucose_IntTypes_h + +#ifdef __sun + // Not sure if there are newer versions that support C99 headers. The + // needed features are implemented in the headers below though: + +# include <sys/int_types.h> +# include <sys/int_fmtio.h> +# include <sys/int_limits.h> + +#else + +#define __STDC_LIMIT_MACROS +# include "pstdint.h" +//# include <inttypes.h> + +#endif + +#include <limits.h> + +#ifndef PRIu64 +#define PRIu64 "lu" +#define PRIi64 "ld" +#endif +//================================================================================================= + +#include <misc/util/abc_namespaces.h> + +#endif diff --git a/src/sat/glucose2/Map.h b/src/sat/glucose2/Map.h new file mode 100644 index 00000000..d9c31aae --- /dev/null +++ b/src/sat/glucose2/Map.h @@ -0,0 +1,197 @@ +/*******************************************************************************************[Map.h] +Copyright (c) 2006-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#ifndef Glucose_Map_h +#define Glucose_Map_h + +#include "sat/glucose2/IntTypes.h" +#include "sat/glucose2/Vec.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace Gluco2 { + +//================================================================================================= +// Default hash/equals functions +// + +template<class K> struct Hash { uint32_t operator()(const K& k) const { return hash(k); } }; +template<class K> struct Equal { bool operator()(const K& k1, const K& k2) const { return k1 == k2; } }; + +template<class K> struct DeepHash { uint32_t operator()(const K* k) const { return hash(*k); } }; +template<class K> struct DeepEqual { bool operator()(const K* k1, const K* k2) const { return *k1 == *k2; } }; + +static inline uint32_t hash(uint32_t x){ return x; } +static inline uint32_t hash(uint64_t x){ return (uint32_t)x; } +static inline uint32_t hash(int32_t x) { return (uint32_t)x; } +static inline uint32_t hash(int64_t x) { return (uint32_t)x; } + + +//================================================================================================= +// Some primes +// + +static const int nprimes = 25; +static const int primes [nprimes] = { 31, 73, 151, 313, 643, 1291, 2593, 5233, 10501, 21013, 42073, 84181, 168451, 337219, 674701, 1349473, 2699299, 5398891, 10798093, 21596719, 43193641, 86387383, 172775299, 345550609, 691101253 }; + +//================================================================================================= +// Hash table implementation of Maps +// + +template<class K, class D, class H = Hash<K>, class E = Equal<K> > +class Map { + public: + struct Pair { K key; D data; }; + + private: + H hash; + E equals; + + vec<Pair>* table; + int cap; + int size; + + // Don't allow copying (error prone): + Map<K,D,H,E>& operator = (Map<K,D,H,E>& other) { assert(0); } + Map (Map<K,D,H,E>& other) { assert(0); } + + bool checkCap(int new_size) const { return new_size > cap; } + + int32_t index (const K& k) const { return hash(k) % cap; } + void _insert (const K& k, const D& d) { + vec<Pair>& ps = table[index(k)]; + ps.push(); ps.last().key = k; ps.last().data = d; } + + void rehash () { + const vec<Pair>* old = table; + + int old_cap = cap; + int newsize = primes[0]; + for (int i = 1; newsize <= cap && i < nprimes; i++) + newsize = primes[i]; + + table = new vec<Pair>[newsize]; + cap = newsize; + + for (int i = 0; i < old_cap; i++){ + for (int j = 0; j < old[i].size(); j++){ + _insert(old[i][j].key, old[i][j].data); }} + + delete [] old; + + // printf(" --- rehashing, old-cap=%d, new-cap=%d\n", cap, newsize); + } + + + public: + + Map () : table(NULL), cap(0), size(0) {} + Map (const H& h, const E& e) : hash(h), equals(e), table(NULL), cap(0), size(0){} + ~Map () { delete [] table; } + + // PRECONDITION: the key must already exist in the map. + const D& operator [] (const K& k) const + { + assert(size != 0); + const D* res = NULL; + const vec<Pair>& ps = table[index(k)]; + for (int i = 0; i < ps.size(); i++) + if (equals(ps[i].key, k)) + res = &ps[i].data; + assert(res != NULL); + return *res; + } + + // PRECONDITION: the key must already exist in the map. + D& operator [] (const K& k) + { + assert(size != 0); + D* res = NULL; + vec<Pair>& ps = table[index(k)]; + for (int i = 0; i < ps.size(); i++) + if (equals(ps[i].key, k)) + res = &ps[i].data; + assert(res != NULL); + return *res; + } + + // PRECONDITION: the key must *NOT* exist in the map. + void insert (const K& k, const D& d) { if (checkCap(size+1)) rehash(); _insert(k, d); size++; } + bool peek (const K& k, D& d) const { + if (size == 0) return false; + const vec<Pair>& ps = table[index(k)]; + for (int i = 0; i < ps.size(); i++) + if (equals(ps[i].key, k)){ + d = ps[i].data; + return true; } + return false; + } + + bool has (const K& k) const { + if (size == 0) return false; + const vec<Pair>& ps = table[index(k)]; + for (int i = 0; i < ps.size(); i++) + if (equals(ps[i].key, k)) + return true; + return false; + } + + // PRECONDITION: the key must exist in the map. + void remove(const K& k) { + assert(table != NULL); + vec<Pair>& ps = table[index(k)]; + int j = 0; + for (; j < ps.size() && !equals(ps[j].key, k); j++); + assert(j < ps.size()); + ps[j] = ps.last(); + ps.pop(); + size--; + } + + void clear () { + cap = size = 0; + delete [] table; + table = NULL; + } + + int elems() const { return size; } + int bucket_count() const { return cap; } + + // NOTE: the hash and equality objects are not moved by this method: + void moveTo(Map& other){ + delete [] other.table; + + other.table = table; + other.cap = cap; + other.size = size; + + table = NULL; + size = cap = 0; + } + + // NOTE: given a bit more time, I could make a more C++-style iterator out of this: + const vec<Pair>& bucket(int i) const { return table[i]; } +}; + +//================================================================================================= +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/src/sat/glucose2/Options.h b/src/sat/glucose2/Options.h new file mode 100644 index 00000000..f2d4d493 --- /dev/null +++ b/src/sat/glucose2/Options.h @@ -0,0 +1,392 @@ +/***************************************************************************************[Options.h] +Copyright (c) 2008-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#ifndef Glucose_Options_h +#define Glucose_Options_h + +#define __STDC_FORMAT_MACROS + +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <string.h> + +#include "sat/glucose2/IntTypes.h" +#include "sat/glucose2/Vec.h" +#include "sat/glucose2/ParseUtils.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace Gluco2 { + +//================================================================================================== +// Top-level option parse/help functions: + + +extern void parseOptions (int& argc, char** argv, bool strict = false); +extern void printUsageAndExit(int argc, char** argv, bool verbose = false); +extern void setUsageHelp (const char* str); +extern void setHelpPrefixStr (const char* str); + + +//================================================================================================== +// Options is an abstract class that gives the interface for all types options: + + +class Option +{ + public: + const char* name; + const char* description; + const char* category; + const char* type_name; + + static vec<Option*>& getOptionList () { static vec<Option*> options; return options; } + static const char*& getUsageString() { static const char* usage_str; return usage_str; } + static const char*& getHelpPrefixString() { static const char* help_prefix_str = ""; return help_prefix_str; } + + struct OptionLt { + bool operator()(const Option* x, const Option* y) { + int test1 = strcmp(x->category, y->category); + return test1 < 0 || (test1 == 0 && strcmp(x->type_name, y->type_name) < 0); + } + }; + + Option(const char* name_, + const char* desc_, + const char* cate_, + const char* type_) : + name (name_) + , description(desc_) + , category (cate_) + , type_name (type_) + { + getOptionList().push(this); + } + + public: + virtual ~Option() {} + + virtual bool parse (const char* str) = 0; + virtual void help (bool verbose = false) = 0; + + friend void parseOptions (int& argc, char** argv, bool strict); + friend void printUsageAndExit (int argc, char** argv, bool verbose); + friend void setUsageHelp (const char* str); + friend void setHelpPrefixStr (const char* str); +}; + + +//================================================================================================== +// Range classes with specialization for floating types: + + +struct IntRange { + int begin; + int end; + IntRange(int b, int e) : begin(b), end(e) {} +}; + +struct Int64Range { + int64_t begin; + int64_t end; + Int64Range(int64_t b, int64_t e) : begin(b), end(e) {} +}; + +struct DoubleRange { + double begin; + double end; + bool begin_inclusive; + bool end_inclusive; + DoubleRange(double b, bool binc, double e, bool einc) : begin(b), end(e), begin_inclusive(binc), end_inclusive(einc) {} +}; + + +//================================================================================================== +// Double options: + + +class DoubleOption : public Option +{ + protected: + DoubleRange range; + double value; + + public: + DoubleOption(const char* c, const char* n, const char* d, double def = double(), DoubleRange r = DoubleRange(-HUGE_VAL, false, HUGE_VAL, false)) + : Option(n, d, c, "<double>"), range(r), value(def) { + // FIXME: set LC_NUMERIC to "C" to make sure that strtof/strtod parses decimal point correctly. + } + + operator double (void) const { return value; } + operator double& (void) { return value; } + DoubleOption& operator=(double x) { value = x; return *this; } + + virtual bool parse(const char* str){ + const char* span = str; + + if (!match(span, "-") || !match(span, name) || !match(span, "=")) + return false; + + char* end; + double tmp = strtod(span, &end); + + if (end == NULL) + return false; + else if (tmp >= range.end && (!range.end_inclusive || tmp != range.end)){ + fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name); + exit(1); + }else if (tmp <= range.begin && (!range.begin_inclusive || tmp != range.begin)){ + fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name); + exit(1); } + + value = tmp; + // fprintf(stderr, "READ VALUE: %g\n", value); + + return true; + } + + virtual void help (bool verbose = false){ + fprintf(stderr, " -%-12s = %-8s %c%4.2g .. %4.2g%c (default: %g)\n", + name, type_name, + range.begin_inclusive ? '[' : '(', + range.begin, + range.end, + range.end_inclusive ? ']' : ')', + value); + if (verbose){ + fprintf(stderr, "\n %s\n", description); + fprintf(stderr, "\n"); + } + } +}; + + +//================================================================================================== +// Int options: + + +class IntOption : public Option +{ + protected: + IntRange range; + int32_t value; + + public: + IntOption(const char* c, const char* n, const char* d, int32_t def = int32_t(), IntRange r = IntRange(INT32_MIN, INT32_MAX)) + : Option(n, d, c, "<int32>"), range(r), value(def) {} + + operator int32_t (void) const { return value; } + operator int32_t& (void) { return value; } + IntOption& operator= (int32_t x) { value = x; return *this; } + + virtual bool parse(const char* str){ + const char* span = str; + + if (!match(span, "-") || !match(span, name) || !match(span, "=")) + return false; + + char* end; + int32_t tmp = strtol(span, &end, 10); + + if (end == NULL) + return false; + else if (tmp > range.end){ + fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name); + exit(1); + }else if (tmp < range.begin){ + fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name); + exit(1); } + + value = tmp; + + return true; + } + + virtual void help (bool verbose = false){ + fprintf(stderr, " -%-12s = %-8s [", name, type_name); + if (range.begin == INT32_MIN) + fprintf(stderr, "imin"); + else + fprintf(stderr, "%4d", range.begin); + + fprintf(stderr, " .. "); + if (range.end == INT32_MAX) + fprintf(stderr, "imax"); + else + fprintf(stderr, "%4d", range.end); + + fprintf(stderr, "] (default: %d)\n", value); + if (verbose){ + fprintf(stderr, "\n %s\n", description); + fprintf(stderr, "\n"); + } + } +}; + + +// Leave this out for visual C++ until Microsoft implements C99 and gets support for strtoll. +#ifndef _MSC_VER + +class Int64Option : public Option +{ + protected: + Int64Range range; + int64_t value; + + public: + Int64Option(const char* c, const char* n, const char* d, int64_t def = int64_t(), Int64Range r = Int64Range(INT64_MIN, INT64_MAX)) + : Option(n, d, c, "<int64>"), range(r), value(def) {} + + operator int64_t (void) const { return value; } + operator int64_t& (void) { return value; } + Int64Option& operator= (int64_t x) { value = x; return *this; } + + virtual bool parse(const char* str){ + const char* span = str; + + if (!match(span, "-") || !match(span, name) || !match(span, "=")) + return false; + + char* end; + int64_t tmp = strtoll(span, &end, 10); + + if (end == NULL) + return false; + else if (tmp > range.end){ + fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name); + exit(1); + }else if (tmp < range.begin){ + fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name); + exit(1); } + + value = tmp; + + return true; + } + + virtual void help (bool verbose = false){ + fprintf(stderr, " -%-12s = %-8s [", name, type_name); + if (range.begin == INT64_MIN) + fprintf(stderr, "imin"); + else + fprintf(stderr, "%4d", (int)range.begin); + + fprintf(stderr, " .. "); + if (range.end == INT64_MAX) + fprintf(stderr, "imax"); + else + fprintf(stderr, "%4d", (int)range.end); + + fprintf(stderr, "] (default: %d)\n", (int)value); + if (verbose){ + fprintf(stderr, "\n %s\n", description); + fprintf(stderr, "\n"); + } + } +}; +#endif + +//================================================================================================== +// String option: + + +class StringOption : public Option +{ + const char* value; + public: + StringOption(const char* c, const char* n, const char* d, const char* def = NULL) + : Option(n, d, c, "<string>"), value(def) {} + + operator const char* (void) const { return value; } + operator const char*& (void) { return value; } + StringOption& operator= (const char* x) { value = x; return *this; } + + virtual bool parse(const char* str){ + const char* span = str; + + if (!match(span, "-") || !match(span, name) || !match(span, "=")) + return false; + + value = span; + return true; + } + + virtual void help (bool verbose = false){ + fprintf(stderr, " -%-10s = %8s\n", name, type_name); + if (verbose){ + fprintf(stderr, "\n %s\n", description); + fprintf(stderr, "\n"); + } + } +}; + + +//================================================================================================== +// Bool option: + + +class BoolOption : public Option +{ + bool value; + + public: + BoolOption(const char* c, const char* n, const char* d, bool v) + : Option(n, d, c, "<bool>"), value(v) {} + + operator bool (void) const { return value; } + operator bool& (void) { return value; } + BoolOption& operator=(bool b) { value = b; return *this; } + + virtual bool parse(const char* str){ + const char* span = str; + + if (match(span, "-")){ + bool b = !match(span, "no-"); + + if (strcmp(span, name) == 0){ + value = b; + return true; } + } + + return false; + } + + virtual void help (bool verbose = false){ + + fprintf(stderr, " -%s, -no-%s", name, name); + + for (uint32_t i = 0; i < 32 - strlen(name)*2; i++) + fprintf(stderr, " "); + + fprintf(stderr, " "); + fprintf(stderr, "(default: %s)\n", value ? "on" : "off"); + if (verbose){ + fprintf(stderr, "\n %s\n", description); + fprintf(stderr, "\n"); + } + } +}; + +//================================================================================================= +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/src/sat/glucose2/Options2.cpp b/src/sat/glucose2/Options2.cpp new file mode 100644 index 00000000..b419e054 --- /dev/null +++ b/src/sat/glucose2/Options2.cpp @@ -0,0 +1,95 @@ +/**************************************************************************************[Options.cc] +Copyright (c) 2008-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#include "sat/glucose2/Sort.h" +#include "sat/glucose2/Options.h" +#include "sat/glucose2/ParseUtils.h" + +ABC_NAMESPACE_IMPL_START + +using namespace Gluco2; + +void Gluco2::parseOptions(int& argc, char** argv, bool strict) +{ + int i, j; + for (i = j = 1; i < argc; i++){ + const char* str = argv[i]; + if (match(str, "--") && match(str, Option::getHelpPrefixString()) && match(str, "help")){ + if (*str == '\0') + printUsageAndExit(argc, argv); + else if (match(str, "-verb")) + printUsageAndExit(argc, argv, true); + } else { + bool parsed_ok = false; + + for (int k = 0; !parsed_ok && k < Option::getOptionList().size(); k++){ + parsed_ok = Option::getOptionList()[k]->parse(argv[i]); + + // fprintf(stderr, "checking %d: %s against flag <%s> (%s)\n", i, argv[i], Option::getOptionList()[k]->name, parsed_ok ? "ok" : "skip"); + } + + if (!parsed_ok) { + if (strict && match(argv[i], "-")) + fprintf(stderr, "ERROR! Unknown flag \"%s\". Use '--%shelp' for help.\n", argv[i], Option::getHelpPrefixString()), exit(1); + else + argv[j++] = argv[i]; + } + } + } + + argc -= (i - j); +} + + +void Gluco2::setUsageHelp (const char* str){ Option::getUsageString() = str; } +void Gluco2::setHelpPrefixStr (const char* str){ Option::getHelpPrefixString() = str; } +void Gluco2::printUsageAndExit (int argc, char** argv, bool verbose) +{ + const char* usage = Option::getUsageString(); + if (usage != NULL) + fprintf(stderr, usage, argv[0]); + + sort(Option::getOptionList(), Option::OptionLt()); + + const char* prev_cat = NULL; + const char* prev_type = NULL; + + for (int i = 0; i < Option::getOptionList().size(); i++){ + const char* cat = Option::getOptionList()[i]->category; + const char* type = Option::getOptionList()[i]->type_name; + + if (cat != prev_cat) + fprintf(stderr, "\n%s OPTIONS:\n\n", cat); + else if (type != prev_type) + fprintf(stderr, "\n"); + + Option::getOptionList()[i]->help(verbose); + + prev_cat = Option::getOptionList()[i]->category; + prev_type = Option::getOptionList()[i]->type_name; + } + + fprintf(stderr, "\nHELP OPTIONS:\n\n"); + fprintf(stderr, " --%shelp Print help message.\n", Option::getHelpPrefixString()); + fprintf(stderr, " --%shelp-verb Print verbose help message.\n", Option::getHelpPrefixString()); + fprintf(stderr, "\n"); + exit(0); +} + +ABC_NAMESPACE_IMPL_END diff --git a/src/sat/glucose2/ParseUtils.h b/src/sat/glucose2/ParseUtils.h new file mode 100644 index 00000000..54a139b1 --- /dev/null +++ b/src/sat/glucose2/ParseUtils.h @@ -0,0 +1,155 @@ +/************************************************************************************[ParseUtils.h] +Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson +Copyright (c) 2007-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#ifndef Glucose2_ParseUtils_h +#define Glucose2_ParseUtils_h + +#include <stdlib.h> +#include <stdio.h> +#include <math.h> + +#include "misc/zlib/zlib.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace Gluco2 { + +//------------------------------------------------------------------------------------------------- +// A simple buffered character stream class: + +static const int buffer_size = 1048576; + + +class StreamBuffer { + gzFile in; + unsigned char buf[buffer_size]; + int pos; + int size; + + void assureLookahead() { + if (pos >= size) { + pos = 0; + size = gzread(in, buf, sizeof(buf)); } } + +public: + explicit StreamBuffer(gzFile i) : in(i), pos(0), size(0) { assureLookahead(); } + + int operator * () const { return (pos >= size) ? EOF : buf[pos]; } + void operator ++ () { pos++; assureLookahead(); } + int position () const { return pos; } +}; + + +//------------------------------------------------------------------------------------------------- +// End-of-file detection functions for StreamBuffer and char*: + + +static inline bool isEof(StreamBuffer& in) { return *in == EOF; } +static inline bool isEof(const char* in) { return *in == '\0'; } + +//------------------------------------------------------------------------------------------------- +// Generic parse functions parametrized over the input-stream type. + + +template<class B> +static void skipWhitespace(B& in) { + while ((*in >= 9 && *in <= 13) || *in == 32) + ++in; } + + +template<class B> +static void skipLine(B& in) { + for (;;){ + if (isEof(in)) return; + if (*in == '\n') { ++in; return; } + ++in; } } + +template<class B> +static double parseDouble(B& in) { // only in the form X.XXXXXe-XX + bool neg= false; + double accu = 0.0; + double currentExponent = 1; + int exponent; + + skipWhitespace(in); + if(*in == EOF) return 0; + if (*in == '-') neg = true, ++in; + else if (*in == '+') ++in; + if (*in < '1' || *in > '9') printf("PARSE ERROR! Unexpected char: %c\n", *in), exit(3); + accu = (double)(*in - '0'); + ++in; + if (*in != '.') printf("PARSE ERROR! Unexpected char: %c\n", *in),exit(3); + ++in; // skip dot + currentExponent = 0.1; + while (*in >= '0' && *in <= '9') + accu = accu + currentExponent * ((double)(*in - '0')), + currentExponent /= 10, + ++in; + if (*in != 'e') printf("PARSE ERROR! Unexpected char: %c\n", *in),exit(3); + ++in; // skip dot + exponent = parseInt(in); // read exponent + accu *= pow(10,exponent); + return neg ? -accu:accu; +} + + +template<class B> +static int parseInt(B& in) { + int val = 0; + bool neg = false; + skipWhitespace(in); + if (*in == '-') neg = true, ++in; + else if (*in == '+') ++in; + if (*in < '0' || *in > '9') fprintf(stderr, "PARSE ERROR! Unexpected char: %c\n", *in), exit(3); + while (*in >= '0' && *in <= '9') + val = val*10 + (*in - '0'), + ++in; + return neg ? -val : val; } + + +// String matching: in case of a match the input iterator will be advanced the corresponding +// number of characters. +template<class B> +static bool match(B& in, const char* str) { + int i; + for (i = 0; str[i] != '\0'; i++) + if (in[i] != str[i]) + return false; + + in += i; + + return true; +} + +// String matching: consumes characters eagerly, but does not require random access iterator. +template<class B> +static bool eagerMatch(B& in, const char* str) { + for (; *str != '\0'; ++str, ++in) + if (*str != *in) + return false; + return true; } + + +//================================================================================================= +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/src/sat/glucose2/Queue.h b/src/sat/glucose2/Queue.h new file mode 100644 index 00000000..2328fdf9 --- /dev/null +++ b/src/sat/glucose2/Queue.h @@ -0,0 +1,73 @@ +/*****************************************************************************************[Queue.h] +Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson +Copyright (c) 2007-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#ifndef Glucose_Queue_h +#define Glucose_Queue_h + +#include "sat/glucose2/Vec.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace Gluco2 { + +//================================================================================================= + +template<class T> +class Queue { + vec<T> buf; + int first; + int end; + +public: + typedef T Key; + + Queue() : buf(1), first(0), end(0) {} + + void clear (bool dealloc = false) { buf.clear(dealloc); buf.growTo(1); first = end = 0; } + int size () const { return (end >= first) ? end - first : end - first + buf.size(); } + + const T& operator [] (int index) const { assert(index >= 0); assert(index < size()); return buf[(first + index) % buf.size()]; } + T& operator [] (int index) { assert(index >= 0); assert(index < size()); return buf[(first + index) % buf.size()]; } + + T peek () const { assert(first != end); return buf[first]; } + void pop () { assert(first != end); first++; if (first == buf.size()) first = 0; } + void insert(T elem) { // INVARIANT: buf[end] is always unused + buf[end++] = elem; + if (end == buf.size()) end = 0; + if (first == end){ // Resize: + vec<T> tmp((buf.size()*3 + 1) >> 1); + //**/printf("queue alloc: %d elems (%.1f MB)\n", tmp.size(), tmp.size() * sizeof(T) / 1000000.0); + int j, i = 0; + for (j = first; j < buf.size(); j++) tmp[i++] = buf[j]; + for (j = 0 ; j < end ; j++) tmp[i++] = buf[j]; + first = 0; + end = buf.size(); + tmp.moveTo(buf); + } + } +}; + + +//================================================================================================= +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/src/sat/glucose2/SimpSolver.h b/src/sat/glucose2/SimpSolver.h new file mode 100644 index 00000000..36d625e9 --- /dev/null +++ b/src/sat/glucose2/SimpSolver.h @@ -0,0 +1,230 @@ +/************************************************************************************[SimpSolver.h] +Copyright (c) 2006, Niklas Een, Niklas Sorensson +Copyright (c) 2007-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#ifndef Glucose_SimpSolver_h +#define Glucose_SimpSolver_h + +#include "sat/glucose2/Queue.h" +#include "sat/glucose2/Solver.h" + +#include "sat/glucose2/CGlucose.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace Gluco2 { + +//================================================================================================= + + +class SimpSolver : public Solver { + public: + // Constructor/Destructor: + // + SimpSolver(); + ~SimpSolver(); + + // Problem specification: + // + Var newVar (bool polarity = true, bool dvar = true); + void addVar (Var v); + bool addClause (const vec<Lit>& ps); + bool addEmptyClause(); // Add the empty clause to the solver. + bool addClause (Lit p); // Add a unit clause to the solver. + bool addClause (Lit p, Lit q); // Add a binary clause to the solver. + bool addClause (Lit p, Lit q, Lit r); // Add a ternary clause to the solver. + bool addClause_( vec<Lit>& ps); + bool substitute(Var v, Lit x); // Replace all occurences of v with x (may cause a contradiction). + + // Variable mode: + // + void setFrozen (Var v, bool b); // If a variable is frozen it will not be eliminated. + bool isEliminated(Var v) const; + + // Solving: + // + bool solve (const vec<Lit>& assumps, bool do_simp = true, bool turn_off_simp = false); + lbool solveLimited(const vec<Lit>& assumps, bool do_simp = true, bool turn_off_simp = false); + int solveLimited(int * lit0, int nlits, bool do_simp = false, bool turn_off_simp = false); + bool solve ( bool do_simp = true, bool turn_off_simp = false); + bool solve (Lit p , bool do_simp = true, bool turn_off_simp = false); + bool solve (Lit p, Lit q, bool do_simp = true, bool turn_off_simp = false); + bool solve (Lit p, Lit q, Lit r, bool do_simp = true, bool turn_off_simp = false); + bool eliminate (bool turn_off_elim = false); // Perform variable elimination based simplification. + + void prelocate(int base_var_num){ + Solver::prelocate(base_var_num); + frozen .prelocate( base_var_num ); + eliminated.prelocate( base_var_num ); + + if (use_simplification){ + n_occ .prelocate( base_var_num << 1 ); + occurs .prelocate( base_var_num ); + touched .prelocate( base_var_num ); + elim_heap .prelocate( base_var_num ); + } + } + // Memory managment: + // + virtual void reset(); + virtual void garbageCollect(); + + + // Generate a (possibly simplified) DIMACS file: + // +#if 0 + void toDimacs (const char* file, const vec<Lit>& assumps); + void toDimacs (const char* file); + void toDimacs (const char* file, Lit p); + void toDimacs (const char* file, Lit p, Lit q); + void toDimacs (const char* file, Lit p, Lit q, Lit r); +#endif + + // Mode of operation: + // + int parsing; + int grow; // Allow a variable elimination step to grow by a number of clauses (default to zero). + int clause_lim; // Variables are not eliminated if it produces a resolvent with a length above this limit. + // -1 means no limit. + int subsumption_lim; // Do not check if subsumption against a clause larger than this. -1 means no limit. + double simp_garbage_frac; // A different limit for when to issue a GC during simplification (Also see 'garbage_frac'). + + bool use_asymm; // Shrink clauses by asymmetric branching. + bool use_rcheck; // Check if a clause is already implied. Prett costly, and subsumes subsumptions :) + bool use_elim; // Perform variable elimination. + + // Statistics: + // + int merges; + int asymm_lits; + int eliminated_vars; + int eliminated_clauses; + + protected: + + // Helper structures: + // + struct ElimLt { + const vec<int>& n_occ; + explicit ElimLt(const vec<int>& no) : n_occ(no) {} + + // TODO: are 64-bit operations here noticably bad on 32-bit platforms? Could use a saturating + // 32-bit implementation instead then, but this will have to do for now. + uint64_t cost (Var x) const { return (uint64_t)n_occ[toInt(mkLit(x))] * (uint64_t)n_occ[toInt(~mkLit(x))]; } + bool operator()(Var x, Var y) const { return cost(x) < cost(y); } + + // TODO: investigate this order alternative more. + // bool operator()(Var x, Var y) const { + // int c_x = cost(x); + // int c_y = cost(y); + // return c_x < c_y || c_x == c_y && x < y; } + }; + + struct ClauseDeleted { + const ClauseAllocator& ca; + explicit ClauseDeleted(const ClauseAllocator& _ca) : ca(_ca) {} + bool operator()(const CRef& cr) const { return ca[cr].mark() == 1; } }; + + // Solver state: + // + int elimorder; + bool use_simplification; + vec<uint32_t> elimclauses; + vec<char> touched; + OccLists<Var, vec<CRef>, ClauseDeleted> + occurs; + vec<int> n_occ; + Heap<ElimLt> elim_heap; + Queue<CRef> subsumption_queue; + vec<char> frozen; + vec<char> eliminated; + int bwdsub_assigns; + int n_touched; + + // Temporaries: + // + CRef bwdsub_tmpunit; + + // Main internal methods: + // + lbool solve_ (bool do_simp = true, bool turn_off_simp = false); + bool asymm (Var v, CRef cr); + bool asymmVar (Var v); + void updateElimHeap (Var v); + void gatherTouchedClauses (); + bool merge (const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause); + bool merge (const Clause& _ps, const Clause& _qs, Var v, int& size); + bool backwardSubsumptionCheck (bool verbose = false); + bool eliminateVar (Var v); + void extendModel (); + + void removeClause (CRef cr); + bool strengthenClause (CRef cr, Lit l); + void cleanUpClauses (); + bool implied (const vec<Lit>& c); + void relocAll (ClauseAllocator& to); +}; + + +//================================================================================================= +// Implementation of inline methods: + + +//inline bool SimpSolver::isEliminated (Var v) const { return eliminated[v]; } +inline bool SimpSolver::isEliminated (Var v) const { return eliminated.size() > 0 ? eliminated[v] != 0 : 0; } +inline void SimpSolver::updateElimHeap(Var v) { + assert(use_simplification); + // if (!frozen[v] && !isEliminated(v) && value(v) == l_Undef) + if (elim_heap.inHeap(v) || (!frozen[v] && !isEliminated(v) && value(v) == l_Undef)) + elim_heap.update(v); } + + +inline bool SimpSolver::addClause (const vec<Lit>& ps) { ps.copyTo(add_tmp); return addClause_(add_tmp); } +inline bool SimpSolver::addEmptyClause() { add_tmp.clear(); return addClause_(add_tmp); } +inline bool SimpSolver::addClause (Lit p) { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp); } +inline bool SimpSolver::addClause (Lit p, Lit q) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp); } +inline bool SimpSolver::addClause (Lit p, Lit q, Lit r) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp); } +inline void SimpSolver::setFrozen (Var v, bool b) { frozen[v] = (char)b; if (use_simplification && !b) { updateElimHeap(v); } } + +inline bool SimpSolver::solve ( bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); return solve_(do_simp, turn_off_simp) == l_True; } +inline bool SimpSolver::solve (Lit p , bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); return solve_(do_simp, turn_off_simp) == l_True; } +inline bool SimpSolver::solve (Lit p, Lit q, bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); return solve_(do_simp, turn_off_simp) == l_True; } +inline bool SimpSolver::solve (Lit p, Lit q, Lit r, bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_(do_simp, turn_off_simp) == l_True; } +inline bool SimpSolver::solve (const vec<Lit>& assumps, bool do_simp, bool turn_off_simp){ + budgetOff(); assumps.copyTo(assumptions); return solve_(do_simp, turn_off_simp) == l_True; } + +inline lbool SimpSolver::solveLimited (const vec<Lit>& assumps, bool do_simp, bool turn_off_simp){ + assumps.copyTo(assumptions); return solve_(do_simp, turn_off_simp); } + +inline int SimpSolver::solveLimited(int * lit0, int nlits, bool do_simp, bool turn_off_simp){ + assumptions.clear(); + for(int i = 0; i < nlits; i ++) + assumptions.push(toLit(lit0[i])); + lbool res = solve_(do_simp, turn_off_simp); + return res == l_True ? 1 : (res == l_False ? -1 : 0); +} + +inline void SimpSolver::addVar(Var v) { while (v >= nVars()) newVar(); } + +//================================================================================================= +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/src/sat/glucose2/SimpSolver2.cpp b/src/sat/glucose2/SimpSolver2.cpp new file mode 100644 index 00000000..37093277 --- /dev/null +++ b/src/sat/glucose2/SimpSolver2.cpp @@ -0,0 +1,781 @@ +/***********************************************************************************[SimpSolver.cc] +Copyright (c) 2006, Niklas Een, Niklas Sorensson +Copyright (c) 2007-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#include "sat/glucose2/Sort.h" +#include "sat/glucose2/SimpSolver.h" +#include "sat/glucose2/System.h" + +ABC_NAMESPACE_IMPL_START + +using namespace Gluco2; + +//================================================================================================= +// Options: + + +static const char* _cat = "SIMP"; + +static BoolOption opt_use_asymm (_cat, "asymm", "Shrink clauses by asymmetric branching.", false); +static BoolOption opt_use_rcheck (_cat, "rcheck", "Check if a clause is already implied. (costly)", false); +static BoolOption opt_use_elim (_cat, "elim", "Perform variable elimination.", true); +static IntOption opt_grow (_cat, "grow", "Allow a variable elimination step to grow by a number of clauses.", 0); +static IntOption opt_clause_lim (_cat, "cl-lim", "Variables are not eliminated if it produces a resolvent with a length above this limit. -1 means no limit", 20, IntRange(-1, INT32_MAX)); +static IntOption opt_subsumption_lim (_cat, "sub-lim", "Do not check if subsumption against a clause larger than this. -1 means no limit.", 1000, IntRange(-1, INT32_MAX)); +static DoubleOption opt_simp_garbage_frac(_cat, "simp-gc-frac", "The fraction of wasted memory allowed before a garbage collection is triggered during simplification.", 0.5, DoubleRange(0, false, HUGE_VAL, false)); + + +//================================================================================================= +// Constructor/Destructor: + + +SimpSolver::SimpSolver() : + grow (opt_grow) + , clause_lim (opt_clause_lim) + , subsumption_lim (opt_subsumption_lim) + , simp_garbage_frac (opt_simp_garbage_frac) + , use_asymm (opt_use_asymm) + , use_rcheck (opt_use_rcheck) + , use_elim (opt_use_elim) + , merges (0) + , asymm_lits (0) + , eliminated_vars (0) + , eliminated_clauses (0) + , elimorder (1) + , use_simplification (true) + , occurs (ClauseDeleted(ca)) + , elim_heap (ElimLt(n_occ)) + , bwdsub_assigns (0) + , n_touched (0) +{ + vec<Lit> dummy(1,lit_Undef); + ca.extra_clause_field = true; // NOTE: must happen before allocating the dummy clause below. + bwdsub_tmpunit = ca.alloc(dummy); + remove_satisfied = false; + parsing = 0; +} + + +SimpSolver::~SimpSolver() +{ +} + + +Var SimpSolver::newVar(bool sign, bool dvar) { + Var v = Solver::newVar(sign, dvar); + + frozen .push((char)false); + eliminated.push((char)false); + + if (use_simplification){ + n_occ .push(0); + n_occ .push(0); + occurs .init(v); + touched .push(0); + elim_heap .insert(v); + } + return v; } + + + +lbool SimpSolver::solve_(bool do_simp, bool turn_off_simp) +{ + vec<Var> extra_frozen; + lbool result = l_True; + + do_simp &= use_simplification; + + if (do_simp){ + // Assumptions must be temporarily frozen to run variable elimination: + for (int i = 0; i < assumptions.size(); i++){ + Var v = var(assumptions[i]); + + // If an assumption has been eliminated, remember it. + assert(!isEliminated(v)); + + if (!frozen[v]){ + // Freeze and store. + setFrozen(v, true); + extra_frozen.push(v); + } } + + result = lbool(eliminate(turn_off_simp)); + } + + if (result == l_True) + result = Solver::solve_(); + else if (verbosity >= 1) + printf("===============================================================================\n"); + + if (result == l_True) + extendModel(); + + if (do_simp) + // Unfreeze the assumptions that were frozen: + for (int i = 0; i < extra_frozen.size(); i++) + setFrozen(extra_frozen[i], false); + + return result; +} + + + +bool SimpSolver::addClause_(vec<Lit>& ps) +{ +#ifndef NDEBUG + for (int i = 0; i < ps.size(); i++) + assert(!isEliminated(var(ps[i]))); +#endif + int nclauses = clauses.size(); + + if (use_rcheck && implied(ps)) + return true; + + if (!Solver::addClause_(ps)) + return false; + + if(!parsing && certifiedUNSAT) { + for (int i = 0; i < ps.size(); i++) + fprintf(certifiedOutput, "%i " , (var(ps[i]) + 1) * (-2 * sign(ps[i]) + 1) ); + fprintf(certifiedOutput, "0\n"); + } + + if (use_simplification && clauses.size() == nclauses + 1){ + CRef cr = clauses.last(); + const Clause& c = ca[cr]; + + // NOTE: the clause is added to the queue immediately and then + // again during 'gatherTouchedClauses()'. If nothing happens + // in between, it will only be checked once. Otherwise, it may + // be checked twice unnecessarily. This is an unfortunate + // consequence of how backward subsumption is used to mimic + // forward subsumption. + subsumption_queue.insert(cr); + for (int i = 0; i < c.size(); i++){ + occurs[var(c[i])].push(cr); + n_occ[toInt(c[i])]++; + touched[var(c[i])] = 1; + n_touched++; + if (elim_heap.inHeap(var(c[i]))) + elim_heap.increase(var(c[i])); + } + } + + return true; +} + + +void SimpSolver::removeClause(CRef cr) +{ + const Clause& c = ca[cr]; + + if (use_simplification) + for (int i = 0; i < c.size(); i++){ + n_occ[toInt(c[i])]--; + updateElimHeap(var(c[i])); + occurs.smudge(var(c[i])); + } + + Solver::removeClause(cr); +} + + +bool SimpSolver::strengthenClause(CRef cr, Lit l) +{ + Clause& c = ca[cr]; + assert(decisionLevel() == 0); + assert(use_simplification); + + // FIX: this is too inefficient but would be nice to have (properly implemented) + // if (!find(subsumption_queue, &c)) + subsumption_queue.insert(cr); + + if (certifiedUNSAT) { + for (int i = 0; i < c.size(); i++) + if (c[i] != l) fprintf(certifiedOutput, "%i " , (var(c[i]) + 1) * (-2 * sign(c[i]) + 1) ); + fprintf(certifiedOutput, "0\n"); + } + + if (c.size() == 2){ + removeClause(cr); + c.strengthen(l); + }else{ + if (certifiedUNSAT) { + fprintf(certifiedOutput, "d "); + for (int i = 0; i < c.size(); i++) + fprintf(certifiedOutput, "%i " , (var(c[i]) + 1) * (-2 * sign(c[i]) + 1) ); + fprintf(certifiedOutput, "0\n"); + } + + detachClause(cr, true); + c.strengthen(l); + attachClause(cr); + remove(occurs[var(l)], cr); + n_occ[toInt(l)]--; + updateElimHeap(var(l)); + } + + return c.size() == 1 ? enqueue(c[0]) && propagate() == CRef_Undef : true; +} + + +// Returns FALSE if clause is always satisfied ('out_clause' should not be used). +bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause) +{ + merges++; + out_clause.clear(); + + bool ps_smallest = _ps.size() < _qs.size(); + const Clause& ps = ps_smallest ? _qs : _ps; + const Clause& qs = ps_smallest ? _ps : _qs; + + int i, j; + for (i = 0; i < qs.size(); i++){ + if (var(qs[i]) != v){ + for (j = 0; j < ps.size(); j++) + if (var(ps[j]) == var(qs[i])) { + if (ps[j] == ~qs[i]) + return false; + else + goto next; + } + out_clause.push(qs[i]); + } + next:; + } + + for (i = 0; i < ps.size(); i++) + if (var(ps[i]) != v) + out_clause.push(ps[i]); + + return true; +} + + +// Returns FALSE if clause is always satisfied. +bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, int& size) +{ + merges++; + + bool ps_smallest = _ps.size() < _qs.size(); + const Clause& ps = ps_smallest ? _qs : _ps; + const Clause& qs = ps_smallest ? _ps : _qs; + const Lit* __ps = (const Lit*)ps; + const Lit* __qs = (const Lit*)qs; + + size = ps.size()-1; + + for (int i = 0; i < qs.size(); i++){ + if (var(__qs[i]) != v){ + for (int j = 0; j < ps.size(); j++) + if (var(__ps[j]) == var(__qs[i])) { + if (__ps[j] == ~__qs[i]) + return false; + else + goto next; + } + size++; + } + next:; + } + + return true; +} + + +void SimpSolver::gatherTouchedClauses() +{ + if (n_touched == 0) return; + + int i,j; + for (i = j = 0; i < subsumption_queue.size(); i++) + if (ca[subsumption_queue[i]].mark() == 0) + ca[subsumption_queue[i]].mark(2); + + for (i = 0; i < touched.size(); i++) + if (touched[i]){ + const vec<CRef>& cs = occurs.lookup(i); + for (j = 0; j < cs.size(); j++) + if (ca[cs[j]].mark() == 0){ + subsumption_queue.insert(cs[j]); + ca[cs[j]].mark(2); + } + touched[i] = 0; + } + + for (i = 0; i < subsumption_queue.size(); i++) + if (ca[subsumption_queue[i]].mark() == 2) + ca[subsumption_queue[i]].mark(0); + + n_touched = 0; +} + + +bool SimpSolver::implied(const vec<Lit>& c) +{ + assert(decisionLevel() == 0); + + trail_lim.push(trail.size()); + for (int i = 0; i < c.size(); i++) + if (value(c[i]) == l_True){ + cancelUntil(0); + return false; + }else if (value(c[i]) != l_False){ + assert(value(c[i]) == l_Undef); + uncheckedEnqueue(~c[i]); + } + + bool result = propagate() != CRef_Undef; + cancelUntil(0); + return result; +} + + +// Backward subsumption + backward subsumption resolution +bool SimpSolver::backwardSubsumptionCheck(bool verbose) +{ + int cnt = 0; + int subsumed = 0; + int deleted_literals = 0; + assert(decisionLevel() == 0); + + while (subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()){ + + // Empty subsumption queue and return immediately on user-interrupt: + if (asynch_interrupt){ + subsumption_queue.clear(); + bwdsub_assigns = trail.size(); + break; } + + // Check top-level assignments by creating a dummy clause and placing it in the queue: + if (subsumption_queue.size() == 0 && bwdsub_assigns < trail.size()){ + Lit l = trail[bwdsub_assigns++]; + ca[bwdsub_tmpunit][0] = l; + ca[bwdsub_tmpunit].calcAbstraction(); + subsumption_queue.insert(bwdsub_tmpunit); } + + CRef cr = subsumption_queue.peek(); subsumption_queue.pop(); + Clause& c = ca[cr]; + + if (c.mark()) continue; + + if (verbose && verbosity >= 2 && cnt++ % 1000 == 0) + printf("subsumption left: %10d (%10d subsumed, %10d deleted literals)\r", subsumption_queue.size(), subsumed, deleted_literals); + + assert(c.size() > 1 || value(c[0]) == l_True); // Unit-clauses should have been propagated before this point. + + // Find best variable to scan: + Var best = var(c[0]); + for (int i = 1; i < c.size(); i++) + if (occurs[var(c[i])].size() < occurs[best].size()) + best = var(c[i]); + + // Search all candidates: + vec<CRef>& _cs = occurs.lookup(best); + CRef* cs = (CRef*)_cs; + + for (int j = 0; j < _cs.size(); j++) + if (c.mark()) + break; + else if (!ca[cs[j]].mark() && cs[j] != cr && (subsumption_lim == -1 || ca[cs[j]].size() < subsumption_lim)){ + Lit l = c.subsumes(ca[cs[j]]); + + if (l == lit_Undef) + subsumed++, removeClause(cs[j]); + else if (l != lit_Error){ + deleted_literals++; + + if (!strengthenClause(cs[j], ~l)) + return false; + + // Did current candidate get deleted from cs? Then check candidate at index j again: + if (var(l) == best) + j--; + } + } + } + + return true; +} + + +bool SimpSolver::asymm(Var v, CRef cr) +{ + Clause& c = ca[cr]; + assert(decisionLevel() == 0); + + if (c.mark() || satisfied(c)) return true; + + trail_lim.push(trail.size()); + Lit l = lit_Undef; + for (int i = 0; i < c.size(); i++) + if (var(c[i]) != v && value(c[i]) != l_False) + uncheckedEnqueue(~c[i]); + else + l = c[i]; + + if (propagate() != CRef_Undef){ + cancelUntil(0); + asymm_lits++; + if (!strengthenClause(cr, l)) + return false; + }else + cancelUntil(0); + + return true; +} + + +bool SimpSolver::asymmVar(Var v) +{ + assert(use_simplification); + + const vec<CRef>& cls = occurs.lookup(v); + + if (value(v) != l_Undef || cls.size() == 0) + return true; + + for (int i = 0; i < cls.size(); i++) + if (!asymm(v, cls[i])) + return false; + + return backwardSubsumptionCheck(); +} + + +static void mkElimClause(vec<uint32_t>& elimclauses, Lit x) +{ + elimclauses.push(toInt(x)); + elimclauses.push(1); +} + + +static void mkElimClause(vec<uint32_t>& elimclauses, Var v, Clause& c) +{ + int first = elimclauses.size(); + int v_pos = -1; + + // Copy clause to elimclauses-vector. Remember position where the + // variable 'v' occurs: + for (int i = 0; i < c.size(); i++){ + elimclauses.push(toInt(c[i])); + if (var(c[i]) == v) + v_pos = i + first; + } + assert(v_pos != -1); + + // Swap the first literal with the 'v' literal, so that the literal + // containing 'v' will occur first in the clause: + uint32_t tmp = elimclauses[v_pos]; + elimclauses[v_pos] = elimclauses[first]; + elimclauses[first] = tmp; + + // Store the length of the clause last: + elimclauses.push(c.size()); +} + + + +bool SimpSolver::eliminateVar(Var v) +{ + int i, j; + assert(!frozen[v]); + assert(!isEliminated(v)); + assert(value(v) == l_Undef); + + // Split the occurrences into positive and negative: + // + const vec<CRef>& cls = occurs.lookup(v); + vec<CRef> pos, neg; + for (i = 0; i < cls.size(); i++) + (find(ca[cls[i]], mkLit(v)) ? pos : neg).push(cls[i]); + + // Check wether the increase in number of clauses stays within the allowed ('grow'). Moreover, no + // clause must exceed the limit on the maximal clause size (if it is set): + // + int cnt = 0; + int clause_size = 0; + + for (i = 0; i < pos.size(); i++) + for (j = 0; j < neg.size(); j++) + if (merge(ca[pos[i]], ca[neg[j]], v, clause_size) && + (++cnt > cls.size() + grow || (clause_lim != -1 && clause_size > clause_lim))) + return true; + + // Delete and store old clauses: + eliminated[v] = true; + setDecisionVar(v, false); + eliminated_vars++; + + if (pos.size() > neg.size()){ + for (i = 0; i < neg.size(); i++) + mkElimClause(elimclauses, v, ca[neg[i]]); + mkElimClause(elimclauses, mkLit(v)); + eliminated_clauses += neg.size(); + }else{ + for (i = 0; i < pos.size(); i++) + mkElimClause(elimclauses, v, ca[pos[i]]); + mkElimClause(elimclauses, ~mkLit(v)); + eliminated_clauses += pos.size(); + } + + + // Produce clauses in cross product: + vec<Lit>& resolvent = add_tmp; + for (i = 0; i < pos.size(); i++) + for (j = 0; j < neg.size(); j++) + if (merge(ca[pos[i]], ca[neg[j]], v, resolvent) && !addClause_(resolvent)) + return false; + + for (i = 0; i < cls.size(); i++) + removeClause(cls[i]); + + // Free occurs list for this variable: + occurs[v].clear(true); + + // Free watchers lists for this variable, if possible: + if (watches[ mkLit(v)].size() == 0) watches[ mkLit(v)].clear(true); + if (watches[~mkLit(v)].size() == 0) watches[~mkLit(v)].clear(true); + + return backwardSubsumptionCheck(); +} + + +bool SimpSolver::substitute(Var v, Lit x) +{ + assert(!frozen[v]); + assert(!isEliminated(v)); + assert(value(v) == l_Undef); + + if (!ok) return false; + + eliminated[v] = true; + setDecisionVar(v, false); + const vec<CRef>& cls = occurs.lookup(v); + + vec<Lit>& subst_clause = add_tmp; + for (int i = 0; i < cls.size(); i++){ + Clause& c = ca[cls[i]]; + + subst_clause.clear(); + for (int j = 0; j < c.size(); j++){ + Lit p = c[j]; + subst_clause.push(var(p) == v ? x ^ sign(p) : p); + } + + + if (!addClause_(subst_clause)) + return ok = false; + + removeClause(cls[i]); + + } + + return true; +} + + +void SimpSolver::extendModel() +{ + int i, j; + Lit x; + + for (i = elimclauses.size()-1; i > 0; i -= j){ + for (j = elimclauses[i--]; j > 1; j--, i--) + if (modelValue(toLit(elimclauses[i])) != l_False) + goto next; + + x = toLit(elimclauses[i]); + model[var(x)] = lbool(!sign(x)); + next:; + } +} + + +bool SimpSolver::eliminate(bool turn_off_elim) +{ + //abctime clk = Abc_Clock(); + if (!simplify()) + return false; + else if (!use_simplification) + return true; + + // Main simplification loop: + // + + int toPerform = clauses.size()<=4800000; + + if(!toPerform) { + printf("c Too many clauses... No preprocessing\n"); + } + + while (toPerform && (n_touched > 0 || bwdsub_assigns < trail.size() || elim_heap.size() > 0)){ + + gatherTouchedClauses(); + // printf(" ## (time = %6.2f s) BWD-SUB: queue = %d, trail = %d\n", cpuTime(), subsumption_queue.size(), trail.size() - bwdsub_assigns); + if ((subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()) && + !backwardSubsumptionCheck(true)){ + ok = false; goto cleanup; } + + // Empty elim_heap and return immediately on user-interrupt: + if (asynch_interrupt){ + assert(bwdsub_assigns == trail.size()); + assert(subsumption_queue.size() == 0); + assert(n_touched == 0); + elim_heap.clear(); + goto cleanup; } + + // printf(" ## (time = %6.2f s) ELIM: vars = %d\n", cpuTime(), elim_heap.size()); + for (int cnt = 0; !elim_heap.empty(); cnt++){ + Var elim = elim_heap.removeMin(); + + if (asynch_interrupt) break; + + if (isEliminated(elim) || value(elim) != l_Undef) continue; + + if (verbosity >= 2 && cnt % 100 == 0) + printf("elimination left: %10d\r", elim_heap.size()); + + if (use_asymm){ + // Temporarily freeze variable. Otherwise, it would immediately end up on the queue again: + bool was_frozen = frozen[elim] != 0; + frozen[elim] = true; + if (!asymmVar(elim)){ + ok = false; goto cleanup; } + frozen[elim] = was_frozen; } + + // At this point, the variable may have been set by assymetric branching, so check it + // again. Also, don't eliminate frozen variables: + if (use_elim && value(elim) == l_Undef && !frozen[elim] && !eliminateVar(elim)){ + ok = false; goto cleanup; } + + checkGarbage(simp_garbage_frac); + } + + assert(subsumption_queue.size() == 0); + } + cleanup: + + // If no more simplification is needed, free all simplification-related data structures: + if (turn_off_elim){ + touched .clear(true); + occurs .clear(true); + n_occ .clear(true); + elim_heap.clear(true); + subsumption_queue.clear(true); + + use_simplification = false; + remove_satisfied = true; + ca.extra_clause_field = false; + + // Force full cleanup (this is safe and desirable since it only happens once): + rebuildOrderHeap(); + garbageCollect(); + }else{ + // Cheaper cleanup: + cleanUpClauses(); // TODO: can we make 'cleanUpClauses()' not be linear in the problem size somehow? + checkGarbage(); + } + + if (verbosity >= 1 && elimclauses.size() > 0) + printf("c | Eliminated clauses: %10.2f Mb |\n", + double(elimclauses.size() * sizeof(uint32_t)) / (1024*1024)); + return ok; +} + + +void SimpSolver::cleanUpClauses() +{ + occurs.cleanAll(); + int i,j; + for (i = j = 0; i < clauses.size(); i++) + if (ca[clauses[i]].mark() == 0) + clauses[j++] = clauses[i]; + clauses.shrink_(i - j); +} + + +//================================================================================================= +// Garbage Collection methods: + + +void SimpSolver::relocAll(ClauseAllocator& to) +{ + int i; + if (!use_simplification) return; + + // All occurs lists: + // + for (i = 0; i < nVars(); i++){ + vec<CRef>& cs = occurs[i]; + for (int j = 0; j < cs.size(); j++) + ca.reloc(cs[j], to); + } + + // Subsumption queue: + // + for (i = 0; i < subsumption_queue.size(); i++) + ca.reloc(subsumption_queue[i], to); + + // Temporary clause: + // + ca.reloc(bwdsub_tmpunit, to); +} + + +void SimpSolver::garbageCollect() +{ + // Initialize the next region to a size corresponding to the estimated utilization degree. This + // is not precise but should avoid some unnecessary reallocations for the new region: + ClauseAllocator to(ca.size() - ca.wasted()); + + cleanUpClauses(); + to.extra_clause_field = ca.extra_clause_field; // NOTE: this is important to keep (or lose) the extra fields. + relocAll(to); + Solver::relocAll(to); + if (verbosity >= 2) + printf("| Garbage collection: %12d bytes => %12d bytes |\n", + ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size); + to.moveTo(ca); +} + +void SimpSolver::reset() +{ + Solver::reset(); + grow = opt_grow; + asymm_lits = eliminated_vars = bwdsub_assigns = n_touched = 0; + + subsumption_queue.clear(false); + vec<Lit> dummy(1,lit_Undef); + ca.extra_clause_field = true; // NOTE: must happen before allocating the dummy clause below. + bwdsub_tmpunit = ca.alloc(dummy); + remove_satisfied = false; + + occurs.clear(false); + + touched .shrink_( touched .size() ); + n_occ .shrink_( n_occ .size() ); + eliminated .shrink_( eliminated .size() ); + frozen .shrink_( frozen .size() ); + elimclauses .shrink_( elimclauses .size() ); + + elim_heap .clear_(false); +} + +ABC_NAMESPACE_IMPL_END diff --git a/src/sat/glucose2/Solver.h b/src/sat/glucose2/Solver.h new file mode 100644 index 00000000..b1d38d79 --- /dev/null +++ b/src/sat/glucose2/Solver.h @@ -0,0 +1,653 @@ +/****************************************************************************************[Solver.h] + Glucose -- Copyright (c) 2009, Gilles Audemard, Laurent Simon + CRIL - Univ. Artois, France + LRI - Univ. Paris Sud, France + +Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of +Glucose are exactly the same as Minisat on which it is based on. (see below). + +--------------- +Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson +Copyright (c) 2007-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#ifndef Glucose_Solver_h +#define Glucose_Solver_h + +#include "sat/glucose2/Vec.h" +#include "sat/glucose2/Heap.h" +#include "sat/glucose2/Alg.h" +#include "sat/glucose2/Options.h" +#include "sat/glucose2/SolverTypes.h" +#include "sat/glucose2/BoundedQueue.h" +#include "sat/glucose2/Constants.h" + +#include "sat/glucose2/CGlucose.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace Gluco2 { + +//================================================================================================= +// Solver -- the main class: + +class Solver { +public: + + int SolverType; // ABC identifies Glucose's type as 0 + + // Constructor/Destructor: + // + Solver(); + virtual ~Solver(); + + // ABC callbacks + void * pCnfMan; // external CNF manager + int(*pCnfFunc)(void * p, int, int*); // external callback. messages: 0: unsat; 1: sat; -1: still working + int nCallConfl; // callback will be called every this number of conflicts + bool terminate_search_early; // used to stop the solver early if it as instructed by an external caller + int * pstop; // another callback + uint64_t nRuntimeLimit; // runtime limit + vec<int> user_vec; + vec<Lit> user_lits; + + // circuit-based solving + int jftr; + void sat_solver_set_var_fanin_lit(int, int, int); + void sat_solver_start_new_round(); + void sat_solver_mark_cone(int); + void sat_solver_set_jftr(int); + int sat_solver_jftr(); + void sat_solver_reset(); + + // Problem specification: + // + Var newVar (bool polarity = true, bool dvar = true); // Add a new variable with parameters specifying variable mode. + void addVar (Var v); // Add enough variables to make sure there is variable v. + + bool addClause (const vec<Lit>& ps); // Add a clause to the solver. + bool addEmptyClause(); // Add the empty clause, making the solver contradictory. + bool addClause (Lit p); // Add a unit clause to the solver. + bool addClause (Lit p, Lit q); // Add a binary clause to the solver. + bool addClause (Lit p, Lit q, Lit r); // Add a ternary clause to the solver. + bool addClause_( vec<Lit>& ps); // Add a clause to the solver without making superflous internal copy. Will + // change the passed vector 'ps'. + + // Solving: + // + bool simplify (); // Removes already satisfied clauses. + bool solve (const vec<Lit>& assumps); // Search for a model that respects a given set of assumptions. + lbool solveLimited (const vec<Lit>& assumps); // Search for a model that respects a given set of assumptions (With resource constraints). + bool solve (); // Search without assumptions. + bool solve (Lit p); // Search for a model that respects a single assumption. + bool solve (Lit p, Lit q); // Search for a model that respects two assumptions. + bool solve (Lit p, Lit q, Lit r); // Search for a model that respects three assumptions. + bool okay () const; // FALSE means solver is in a conflicting state + + void toDimacs (FILE* f, const vec<Lit>& assumps); // Write CNF to file in DIMACS-format. + void toDimacs (const char *file, const vec<Lit>& assumps); + void toDimacs (FILE* f, Clause& c, vec<Var>& map, Var& max); + void printLit(Lit l); + void printClause(CRef c); + void printInitialClause(CRef c); + // Convenience versions of 'toDimacs()': + void toDimacs (const char* file); + void toDimacs (const char* file, Lit p); + void toDimacs (const char* file, Lit p, Lit q); + void toDimacs (const char* file, Lit p, Lit q, Lit r); + + // Variable mode: + // + void setPolarity (Var v, bool b); // Declare which polarity the decision heuristic should use for a variable. Requires mode 'polarity_user'. + void setDecisionVar (Var v, bool b, bool use_oheap = true); // Declare if a variable should be eligible for selection in the decision heuristic. + + // Read state: + // + lbool value (Var x) const; // The current value of a variable. + lbool value (Lit p) const; // The current value of a literal. + lbool modelValue (Var x) const; // The value of a variable in the last model. The last call to solve must have been satisfiable. + lbool modelValue (Lit p) const; // The value of a literal in the last model. The last call to solve must have been satisfiable. + int nAssigns () const; // The current number of assigned literals. + int nClauses () const; // The current number of original clauses. + int nLearnts () const; // The current number of learnt clauses. + int nVars () const; // The current number of variables. + int nFreeVars () const; + int * getCex () const; + int level (Var x) const; // moved level() to public to compile "struct JustOrderLt" -- alanmi + + // Incremental mode + void setIncrementalMode(); + void initNbInitialVars(int nb); + void printIncrementalStats(); + + // Resource contraints: + // + void setConfBudget(int64_t x); + void setPropBudget(int64_t x); + void budgetOff(); + void interrupt(); // Trigger a (potentially asynchronous) interruption of the solver. + void clearInterrupt(); // Clear interrupt indicator flag. + + // Memory managment: + // + virtual void reset(); + virtual void garbageCollect(); // virtuality causes segfault for some reason + void checkGarbage(double gf); + void checkGarbage(); + + + + + // Extra results: (read-only member variable) + // + vec<lbool> model; // If problem is satisfiable, this vector contains the model (if any). + vec<Lit> conflict; // If problem is unsatisfiable (possibly under assumptions), + // this vector represent the final conflict clause expressed in the assumptions. + + // Mode of operation: + // + int verbosity; + int verbEveryConflicts; + int showModel; + // Constants For restarts + double K; + double R; + double sizeLBDQueue; + double sizeTrailQueue; + + // Constants for reduce DB + int firstReduceDB; + int incReduceDB; + int specialIncReduceDB; + unsigned int lbLBDFrozenClause; + + // Constant for reducing clause + int lbSizeMinimizingClause; + unsigned int lbLBDMinimizingClause; + + double var_decay; + double clause_decay; + double random_var_freq; + double random_seed; + int ccmin_mode; // Controls conflict clause minimization (0=none, 1=basic, 2=deep). + int phase_saving; // Controls the level of phase saving (0=none, 1=limited, 2=full). + bool rnd_pol; // Use random polarities for branching heuristics. + bool rnd_init_act; // Initialize variable activities with a small random value. + double garbage_frac; // The fraction of wasted memory allowed before a garbage collection is triggered. + + // Certified UNSAT ( Thanks to Marijn Heule) + FILE* certifiedOutput; + bool certifiedUNSAT; + + + // Statistics: (read-only member variable) + // + int64_t nbRemovedClauses,nbReducedClauses,nbDL2,nbBin,nbUn,nbReduceDB,solves, starts, decisions, rnd_decisions, propagations, conflicts,conflictsRestarts,nbstopsrestarts,nbstopsrestartssame,lastblockatrestart; + int64_t dec_vars, clauses_literals, learnts_literals, max_literals, tot_literals; + +protected: + long curRestart; + // Helper structures: + // + struct VarData { CRef reason; int level; }; + static inline VarData mkVarData(CRef cr, int l){ VarData d = {cr, l}; return d; } + + struct Watcher { + CRef cref; + Lit blocker; + Watcher(CRef cr, Lit p) : cref(cr), blocker(p) {} + bool operator==(const Watcher& w) const { return cref == w.cref; } + bool operator!=(const Watcher& w) const { return cref != w.cref; } + }; + + struct WatcherDeleted + { + const ClauseAllocator& ca; + WatcherDeleted(const ClauseAllocator& _ca) : ca(_ca) {} + bool operator()(const Watcher& w) const { return ca[w.cref].mark() == 1; } + }; + + struct VarOrderLt { + const vec<double>& activity; + bool operator () (Var x, Var y) const { return activity[x] > activity[y]; } + VarOrderLt(const vec<double>& act) : activity(act) { } + }; + + + // Solver state: + // + int lastIndexRed; + bool ok; // If FALSE, the constraints are already unsatisfiable. No part of the solver state may be used! + double cla_inc; // Amount to bump next clause with. + vec<double> activity; // A heuristic measurement of the activity of a variable. + double var_inc; // Amount to bump next variable with. + OccLists<Lit, vec<Watcher>, WatcherDeleted> + watches; // 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true). + OccLists<Lit, vec<Watcher>, WatcherDeleted> + watchesBin; // 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true). + vec<CRef> clauses; // List of problem clauses. + vec<CRef> learnts; // List of learnt clauses. + + vec<lbool> assigns; // The current assignments. + vec<char> polarity; // The preferred polarity of each variable. + vec<char> decision; // Declares if a variable is eligible for selection in the decision heuristic. + vec<Lit> trail; // Assignment stack; stores all assigments made in the order they were made. + vec<int> nbpos; + vec<int> trail_lim; // Separator indices for different decision levels in 'trail'. + vec<VarData> vardata; // Stores reason and level for each variable. + int qhead; // Head of queue (as index into the trail -- no more explicit propagation queue in MiniSat). + int simpDB_assigns; // Number of top-level assignments since last execution of 'simplify()'. + int64_t simpDB_props; // Remaining number of propagations that must be made before next execution of 'simplify()'. + vec<Lit> assumptions; // Current set of assumptions provided to solve by the user. + Heap<VarOrderLt> order_heap; // A priority queue of variables ordered with respect to the variable activity. + double progress_estimate;// Set by 'search()'. + bool remove_satisfied; // Indicates whether possibly inefficient linear scan for satisfied clauses should be performed in 'simplify'. + vec<unsigned int> permDiff; // permDiff[var] contains the current conflict number... Used to count the number of LBD + +#ifdef UPDATEVARACTIVITY + // UPDATEVARACTIVITY trick (see competition'09 companion paper) + vec<Lit> lastDecisionLevel; +#endif + + ClauseAllocator ca; + + int nbclausesbeforereduce; // To know when it is time to reduce clause database + + bqueue<unsigned int> trailQueue,lbdQueue; // Bounded queues for restarts. + float sumLBD; // used to compute the global average of LBD. Restarts... + int sumAssumptions; + + + // Temporaries (to reduce allocation overhead). Each variable is prefixed by the method in which it is + // used, exept 'seen' wich is used in several places. + // + vec<char> seen; + vec<Lit> analyze_stack; + vec<Lit> analyze_toclear; + vec<Lit> add_tmp; + unsigned int MYFLAG; + + + double max_learnts; + double learntsize_adjust_confl; + int learntsize_adjust_cnt; + + // Resource contraints: + // + int64_t conflict_budget; // -1 means no budget. + int64_t propagation_budget; // -1 means no budget. + bool asynch_interrupt; + + + // Variables added for incremental mode + int incremental; // Use incremental SAT Solver + int nbVarsInitialFormula; // nb VAR in formula without assumptions (incremental SAT) + double totalTime4Sat,totalTime4Unsat; + int nbSatCalls,nbUnsatCalls; + vec<int> assumptionPositions,initialPositions; + + + // Main internal methods: + // + void insertVarOrder (Var x); // Insert a variable in the decision order priority queue. + Lit pickBranchLit (); // Return the next decision variable. + void newDecisionLevel (); // Begins a new decision level. + void uncheckedEnqueue (Lit p, CRef from = CRef_Undef); // Enqueue a literal. Assumes value of literal is undefined. + bool enqueue (Lit p, CRef from = CRef_Undef); // Test if fact 'p' contradicts current state, enqueue otherwise. + CRef propagate (); // Perform unit propagation. Returns possibly conflicting clause. + void cancelUntil (int level); // Backtrack until a certain level. + void analyze (CRef confl, vec<Lit>& out_learnt, vec<Lit> & selectors, int& out_btlevel,unsigned int &nblevels,unsigned int &szWithoutSelectors); // (bt = backtrack) + void analyzeFinal (Lit p, vec<Lit>& out_conflict); // COULD THIS BE IMPLEMENTED BY THE ORDINARIY "analyze" BY SOME REASONABLE GENERALIZATION? + bool litRedundant (Lit p, uint32_t abstract_levels); // (helper method for 'analyze()') + lbool search (int nof_conflicts); // Search for a given number of conflicts. + lbool solve_ (); // Main solve method (assumptions given in 'assumptions'). + void reduceDB (); // Reduce the set of learnt clauses. + void removeSatisfied (vec<CRef>& cs); // Shrink 'cs' to contain only non-satisfied clauses. + void rebuildOrderHeap (); + + // Maintaining Variable/Clause activity: + // + void varDecayActivity (); // Decay all variables with the specified factor. Implemented by increasing the 'bump' value instead. + void varBumpActivity (Var v, double inc); // Increase a variable with the current 'bump' value. + void varBumpActivity (Var v); // Increase a variable with the current 'bump' value. + void claDecayActivity (); // Decay all clauses with the specified factor. Implemented by increasing the 'bump' value instead. + void claBumpActivity (Clause& c); // Increase a clause with the current 'bump' value. + + // Operations on clauses: + // + void attachClause (CRef cr); // Attach a clause to watcher lists. + void detachClause (CRef cr, bool strict = false); // Detach a clause to watcher lists. + void removeClause (CRef cr); // Detach and free a clause. + bool locked (const Clause& c) const; // Returns TRUE if a clause is a reason for some implication in the current state. + bool satisfied (const Clause& c) const; // Returns TRUE if a clause is satisfied in the current state. + + unsigned int computeLBD(const vec<Lit> & lits,int end=-1); + unsigned int computeLBD(const Clause &c); + void minimisationWithBinaryResolution(vec<Lit> &out_learnt); + + void relocAll (ClauseAllocator& to); + + // Misc: + // + int decisionLevel () const; // Gives the current decisionlevel. + uint32_t abstractLevel (Var x) const; // Used to represent an abstraction of sets of decision levels. + CRef reason (Var x) const; + double progressEstimate () const; // DELETE THIS ?? IT'S NOT VERY USEFUL ... + bool withinBudget () const; + inline bool isSelector(Var v) {return (incremental && v>nbVarsInitialFormula);} + + // Static helpers: + // + + // Returns a random float 0 <= x < 1. Seed must never be 0. + static inline double drand(double& seed) { + seed *= 1389796; + int q = (int)(seed / 2147483647); + seed -= (double)q * 2147483647; + return seed / 2147483647; } + + // Returns a random integer 0 <= x < size. Seed must never be 0. + static inline int irand(double& seed, int size) { + return (int)(drand(seed) * size); } + + + // circuit-based solver +protected: + void uncheckedEnqueue2(Lit p, CRef from = CRef_Undef); + bool heap_rescale; + + void addJwatch( Var host, Var member, int index ); + //void delJwatch( Var member ); + + struct NodeData { Lit lit0; Lit lit1; unsigned sort:30; unsigned dir:1; unsigned now:1; }; + static inline NodeData mkNodeData(){ NodeData w; w.lit0 = toLit(~0); w.lit1 = toLit(~0); w.sort = 0; w.dir = 0; w.now = 0; return w; } + vec<NodeData> var2NodeData; + //vec<Lit> var2FaninLits; // (~0): undefine + vec<unsigned> var2TravId; + vec<Lit> var2Fanout0, var2FanoutN;//, var2FanoutP; + CRef itpc; // the interpreted clause of a gate + void inplace_sort( Var v ); + + bool isTwoFanin ( Var v ) const ; // this var has two fanins + bool isAND ( Var v ) const { return getFaninVar0(v) < getFaninVar1(v); } + bool isJReason ( Var v ) const { return isTwoFanin(v) && ( l_False == value(v) || (!isAND(v) && l_Undef != value(v)) ); } + Lit getFaninLit0( Var v ) const { return var2NodeData[ v ].lit0; } + Lit getFaninLit1( Var v ) const { return var2NodeData[ v ].lit1; } + bool getFaninC0 ( Var v ) const { return sign(getFaninLit0(v)); } + bool getFaninC1 ( Var v ) const { return sign(getFaninLit1(v)); } + Var getFaninVar0( Var v ) const { return var(getFaninLit0(v)); } + Var getFaninVar1( Var v ) const { return var(getFaninLit1(v)); } + Lit getFaninPlt0( Var v ) const { return mkLit(getFaninVar0(v), 1 == polarity[getFaninVar0(v)]); } + Lit getFaninPlt1( Var v ) const { return mkLit(getFaninVar1(v), 1 == polarity[getFaninVar1(v)]); } + Lit maxActiveLit(Lit lit0, Lit lit1) const { return activity[var(lit0)] < activity[var(lit1)]? lit1: lit0; } + + Lit gateJustFanin(Var v) const ; // l_Undef=satisfied, 0/1 = fanin0/fanin1 requires justify + void gateAddJwatch(Var v,int index); + CRef gatePropagateCheck( Var v, Var t ); + CRef gatePropagateCheckThis( Var v ); + CRef gatePropagateCheckFanout( Var v, Lit lfo ); + void setItpcSize( int sz ); // sz <= 3 + + // directly call by original glucose functions + void updateJustActivity( Var v ); + void ResetJustData(bool fCleanMemory); + Lit pickJustLit( int& index ); + void justCheck(); + void pushJustQueue(Var v, int index); + void restoreJustQueue(int level); // call with cancelUntil + void gateClearJwatch( Var v, int backtrack_level ); + + CRef gatePropagate( Lit p ); + + CRef interpret( Var v, Var t ); + CRef castCRef( Lit p ); // interpret a gate into a clause + CRef getConfClause( CRef r ); + + CRef Var2CRef( Var v ) const { return v | (1<<(sizeof(CRef)*8-1)); } + Var CRef2Var( CRef cr ) const { return cr & ~(1<<(sizeof(CRef)*8-1)); } + bool isGateCRef( CRef cr ) const { return CRef_Undef != cr && 0 != (cr & (1<<(sizeof(CRef)*8-1))); } + + unsigned travId_prev, travId; + + //Heap<JustOrderLt> jheap; + int jhead; + + struct JustKey { + typedef double Key; + typedef Var Data; + typedef int Attr; + Key _key; + Data _data; + Attr _attr; + Data data() const { return _data; } + Key key() const { return _key; } + Attr attr() const { return _attr; } + JustKey():_key(0),_data(0),_attr(0){} + JustKey( const Key& nkey, const Data& ndata, const Attr& nattr ): _key(nkey), _data(ndata), _attr(nattr) {} + }; + struct JustOrderLt2 { + const Solver * pS; + bool operator () (const JustKey& x, const JustKey& y) const { + if( x.key() != y.key() ) return x.key() > y.key(); + if( pS->level( x.data() ) != pS->level( y.data() ) ) + return pS->level( x.data() ) < pS->level( y.data() ); + return x.data() > y.data(); + } + JustOrderLt2(const Solver * _pS) : pS(_pS) { } + }; + Heap2<JustOrderLt2, JustKey> jheap; + vec<int> jlevel; + vec<int> jnext; +public: + void prelocate( int var_num ); + void setVarFaninLits( Var v, Lit lit1, Lit lit2 ); + void setVarFaninLits( int v, int lit1, int lit2 ){ setVarFaninLits( Var(v), toLit(lit1), toLit(lit2) ); } + //void delVarFaninLits( Var v); + + void setNewRound(){ travId ++ ; } + void markCone( Var v ); + void setJust( int njftr ){ jftr = njftr; } + bool isRoundWatch( Var v ) const { return travId==var2TravId[v]; } + void justReset(){ jftr = 0; reset(); } + + + //const JustData& getJustData(int v) const { return jdata[v]; } + double varActivity(int v) const { return activity[v];} + //double justActivity(int v) const { return jdata[v].act_fanin;} + int varPolarity(int v){ return polarity[v]? 1: 0;} + vec<Lit> JustModel; // model obtained by justification enabled + + int justUsage() const ; + int solveLimited( int * , int nlits ); +}; + + +//================================================================================================= +// Implementation of inline methods: + +inline CRef Solver::reason(Var x) const { return vardata[x].reason; } +inline int Solver::level (Var x) const { return vardata[x].level; } + +inline void Solver::insertVarOrder(Var x) { + #ifdef CGLUCOSE_EXP + if (!justUsage() && !order_heap.inHeap(x) && decision[x]) order_heap.insert(x); + #else + if (!order_heap.inHeap(x) && decision[x]) order_heap.insert(x); + #endif +} + +inline void Solver::varDecayActivity() { var_inc *= (1 / var_decay); } +inline void Solver::varBumpActivity(Var v) { varBumpActivity(v, var_inc); } +inline void Solver::varBumpActivity(Var v, double inc) { + if ( (activity[v] += inc) > 1e100 ) { + heap_rescale = 1; + // Rescale: + for (int i = 0; i < nVars(); i++) + activity[i] *= 1e-100; + var_inc *= 1e-100; } + + // Update order_heap with respect to new activity: + if (!justUsage() && order_heap.inHeap(v)) + order_heap.decrease(v); +} + +inline void Solver::claDecayActivity() { cla_inc *= (1 / clause_decay); } +inline void Solver::claBumpActivity (Clause& c) { + if ( (c.activity() += cla_inc) > 1e20 ) { + // Rescale: + for (int i = 0; i < learnts.size(); i++) + ca[learnts[i]].activity() *= (float)1e-20; + cla_inc *= 1e-20; } } + +inline void Solver::checkGarbage(void){ checkGarbage(garbage_frac); } +inline void Solver::checkGarbage(double gf){ + if (ca.wasted() > ca.size() * gf) + garbageCollect();} + +// NOTE: enqueue does not set the ok flag! (only public methods do) +inline bool Solver::enqueue (Lit p, CRef from) { return value(p) != l_Undef ? value(p) != l_False : (uncheckedEnqueue(p, from), true); } +inline bool Solver::addClause (const vec<Lit>& ps) { ps.copyTo(add_tmp); return addClause_(add_tmp); } +inline bool Solver::addEmptyClause () { add_tmp.clear(); return addClause_(add_tmp); } +inline bool Solver::addClause (Lit p) { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp); } +inline bool Solver::addClause (Lit p, Lit q) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp); } +inline bool Solver::addClause (Lit p, Lit q, Lit r) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp); } +inline bool Solver::locked (const Clause& c) const { + #ifdef CGLUCOSE_EXP + + if(c.size()>2) + return value(c[0]) == l_True && reason(var(c[0])) != CRef_Undef && !isGateCRef(reason(var(c[0]))) && ca.lea(reason(var(c[0]))) == &c; + return + (value(c[0]) == l_True && reason(var(c[0])) != CRef_Undef && !isGateCRef(reason(var(c[0]))) && ca.lea(reason(var(c[0]))) == &c) + || + (value(c[1]) == l_True && reason(var(c[1])) != CRef_Undef && !isGateCRef(reason(var(c[1]))) && ca.lea(reason(var(c[1]))) == &c); + + #else + + if(c.size()>2) + return value(c[0]) == l_True && reason(var(c[0])) != CRef_Undef && ca.lea(reason(var(c[0]))) == &c; + return + (value(c[0]) == l_True && reason(var(c[0])) != CRef_Undef && ca.lea(reason(var(c[0]))) == &c) + || + (value(c[1]) == l_True && reason(var(c[1])) != CRef_Undef && ca.lea(reason(var(c[1]))) == &c); + + #endif + } +inline void Solver::newDecisionLevel() {trail_lim.push(trail.size());} + +inline int Solver::decisionLevel () const { return trail_lim.size(); } +inline uint32_t Solver::abstractLevel (Var x) const { return 1 << (level(x) & 31); } +inline lbool Solver::value (Var x) const { return assigns[x]; } +inline lbool Solver::value (Lit p) const { return assigns[var(p)] ^ sign(p); } +inline lbool Solver::modelValue (Var x) const { return model[x]; } +inline lbool Solver::modelValue (Lit p) const { return model[var(p)] ^ sign(p); } +inline int Solver::nAssigns () const { return trail.size(); } +inline int Solver::nClauses () const { return clauses.size(); } +inline int Solver::nLearnts () const { return learnts.size(); } +inline int Solver::nVars () const { return vardata.size(); } +inline int Solver::nFreeVars () const { return (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]); } +inline int * Solver::getCex () const { return (int*) &JustModel[0]; } +inline void Solver::setPolarity (Var v, bool b) { polarity[v] = b; } +inline void Solver::setDecisionVar(Var v, bool b, bool use_oheap) +{ + if ( b && !decision[v]) dec_vars++; + else if (!b && decision[v]) dec_vars--; + + decision[v] = b; + if( use_oheap ) insertVarOrder(v); +} +inline void Solver::setConfBudget(int64_t x){ conflict_budget = conflicts + x; } +inline void Solver::setPropBudget(int64_t x){ propagation_budget = propagations + x; } +inline void Solver::interrupt(){ asynch_interrupt = true; } +inline void Solver::clearInterrupt(){ asynch_interrupt = false; } +inline void Solver::budgetOff(){ conflict_budget = propagation_budget = -1; } +inline bool Solver::withinBudget() const { + return !asynch_interrupt && + (conflict_budget < 0 || conflicts < (uint64_t)conflict_budget) && + (propagation_budget < 0 || propagations < (uint64_t)propagation_budget); } + +// FIXME: after the introduction of asynchronous interrruptions the solve-versions that return a +// pure bool do not give a safe interface. Either interrupts must be possible to turn off here, or +// all calls to solve must return an 'lbool'. I'm not yet sure which I prefer. +inline bool Solver::solve () { budgetOff(); assumptions.clear(); return solve_() == l_True; } +inline bool Solver::solve (Lit p) { budgetOff(); assumptions.clear(); assumptions.push(p); return solve_() == l_True; } +inline bool Solver::solve (Lit p, Lit q) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); return solve_() == l_True; } +inline bool Solver::solve (Lit p, Lit q, Lit r) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_() == l_True; } +inline bool Solver::solve (const vec<Lit>& assumps){ budgetOff(); assumps.copyTo(assumptions); return solve_() == l_True; } +inline lbool Solver::solveLimited (const vec<Lit>& assumps){ assumps.copyTo(assumptions); return solve_(); } +inline bool Solver::okay () const { return ok; } + +inline void Solver::toDimacs (const char* file){ vec<Lit> as; toDimacs(file, as); } +inline void Solver::toDimacs (const char* file, Lit p){ vec<Lit> as; as.push(p); toDimacs(file, as); } +inline void Solver::toDimacs (const char* file, Lit p, Lit q){ vec<Lit> as; as.push(p); as.push(q); toDimacs(file, as); } +inline void Solver::toDimacs (const char* file, Lit p, Lit q, Lit r){ vec<Lit> as; as.push(p); as.push(q); as.push(r); toDimacs(file, as); } + +inline void Solver::addVar(Var v) { while (v >= nVars()) newVar(); } + +inline void Solver::sat_solver_set_var_fanin_lit(int v, int lit0, int lit1) { setVarFaninLits( Var(v), toLit(lit0), toLit(lit1) ); } +inline void Solver::sat_solver_start_new_round() { setNewRound(); } +inline void Solver::sat_solver_mark_cone(int v) { markCone(v); } +inline void Solver::sat_solver_set_jftr( int njftr ){ setJust(njftr); } +inline int Solver::sat_solver_jftr(){ return jftr; } +inline void Solver::sat_solver_reset(){ justReset(); } +inline int Solver::solveLimited( int * lit0, int nlits ){ + assumptions.clear(); + for(int i = 0; i < nlits; i ++) + assumptions.push(toLit(lit0[i])); + lbool res = solve_(); + return res == l_True ? 1 : (res == l_False ? -1 : 0); +} +//================================================================================================= +// Debug etc: + + +inline void Solver::printLit(Lit l) +{ + printf("%s%d:%c", sign(l) ? "-" : "", var(l)+1, value(l) == l_True ? '1' : (value(l) == l_False ? '0' : 'X')); +} + + +inline void Solver::printClause(CRef cr) +{ + Clause &c = ca[cr]; + for (int i = 0; i < c.size(); i++){ + printLit(c[i]); + printf(" "); + } +} + +inline void Solver::printInitialClause(CRef cr) +{ + Clause &c = ca[cr]; + for (int i = 0; i < c.size(); i++){ + if(!isSelector(var(c[i]))) { + printLit(c[i]); + printf(" "); + } + } +} + + +//================================================================================================= +} + + +ABC_NAMESPACE_CXX_HEADER_END + +#include "sat/glucose2/CGlucoseCore.h" + +#endif diff --git a/src/sat/glucose2/SolverTypes.h b/src/sat/glucose2/SolverTypes.h new file mode 100644 index 00000000..c0990226 --- /dev/null +++ b/src/sat/glucose2/SolverTypes.h @@ -0,0 +1,450 @@ +/***********************************************************************************[SolverTypes.h] + Glucose -- Copyright (c) 2009, Gilles Audemard, Laurent Simon + CRIL - Univ. Artois, France + LRI - Univ. Paris Sud, France + +Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of +Glucose are exactly the same as Minisat on which it is based on. (see below). + +--------------- +Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson +Copyright (c) 2007-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + + +#ifndef Glucose_SolverTypes_h +#define Glucose_SolverTypes_h + +#include <assert.h> + +#include "sat/glucose2/IntTypes.h" +#include "sat/glucose2/Alg.h" +#include "sat/glucose2/Vec.h" +#include "sat/glucose2/Map.h" +#include "sat/glucose2/Alloc.h" + +#include "sat/glucose2/CGlucose.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace Gluco2 { + +//================================================================================================= +// Variables, literals, lifted booleans, clauses: + + +// NOTE! Variables are just integers. No abstraction here. They should be chosen from 0..N, +// so that they can be used as array indices. + +typedef int Var; +#define var_Undef (-1) + + +struct Lit { + int x; + + // Use this as a constructor: + friend Lit mkLit(Var var, bool sign); + bool operator == (Lit p) const { return x == p.x; } + bool operator != (Lit p) const { return x != p.x; } + bool operator < (Lit p) const { return x < p.x; } // '<' makes p, ~p adjacent in the ordering. +}; + + +inline Lit mkLit (Var var, bool sign = false) { Lit p; p.x = var + var + (int)sign; return p; } +inline Lit operator ~(Lit p) { Lit q; q.x = p.x ^ 1; return q; } +inline Lit operator ^(Lit p, bool b) { Lit q; q.x = p.x ^ (unsigned int)b; return q; } +inline bool sign (Lit p) { return p.x & 1; } +inline int var (Lit p) { return p.x >> 1; } + +// Mapping Literals to and from compact integers suitable for array indexing: +inline int toInt (Var v) { return v; } +inline int toInt (Lit p) { return p.x; } +inline Lit toLit (int i) { Lit p; p.x = i; return p; } + +//const Lit lit_Undef = mkLit(var_Undef, false); // }- Useful special constants. +//const Lit lit_Error = mkLit(var_Undef, true ); // } + +const Lit lit_Undef = { -2 }; // }- Useful special constants. +const Lit lit_Error = { -1 }; // } + + +//================================================================================================= +// Lifted booleans: +// +// NOTE: this implementation is optimized for the case when comparisons between values are mostly +// between one variable and one constant. Some care had to be taken to make sure that gcc +// does enough constant propagation to produce sensible code, and this appears to be somewhat +// fragile unfortunately. + +#define l_True (Gluco2::lbool((uint8_t)0)) // gcc does not do constant propagation if these are real constants. +#define l_False (Gluco2::lbool((uint8_t)1)) +#define l_Undef (Gluco2::lbool((uint8_t)2)) + +class lbool { + uint8_t value; + +public: + explicit lbool(uint8_t v) : value(v) { } + + lbool() : value(0) { } + explicit lbool(bool x) : value(!x) { } + + bool operator == (lbool b) const { return (((b.value&2) & (value&2)) | (!(b.value&2)&(value == b.value))) != 0; } + bool operator != (lbool b) const { return !(*this == b); } + lbool operator ^ (bool b) const { return lbool((uint8_t)(value^(uint8_t)b)); } + + lbool operator && (lbool b) const { + uint8_t sel = (this->value << 1) | (b.value << 3); + uint8_t v = (0xF7F755F4 >> sel) & 3; + return lbool(v); } + + lbool operator || (lbool b) const { + uint8_t sel = (this->value << 1) | (b.value << 3); + uint8_t v = (0xFCFCF400 >> sel) & 3; + return lbool(v); } + + friend int toInt (lbool l); + friend lbool toLbool(int v); +}; +inline int toInt (lbool l) { return l.value; } +inline lbool toLbool(int v) { return lbool((uint8_t)v); } + +//================================================================================================= +// Clause -- a simple class for representing a clause: + +class Clause; +typedef RegionAllocator<uint32_t>::Ref CRef; + +class Clause { + struct { + unsigned mark : 2; + unsigned learnt : 1; + unsigned has_extra : 1; + unsigned reloced : 1; + unsigned lbd : 26; + unsigned canbedel : 1; + unsigned size : 32; + unsigned szWithoutSelectors : 32; + + } header; + union { Lit lit; float act; uint32_t abs; CRef rel; } data[0]; + + friend class ClauseAllocator; + + #ifdef CGLUCOSE_EXP + friend class Solver; + #endif + + // NOTE: This constructor cannot be used directly (doesn't allocate enough memory). + template<class V> + Clause(const V& ps, bool use_extra, bool learnt) { + header.mark = 0; + header.learnt = learnt; + header.has_extra = use_extra; + header.reloced = 0; + header.size = ps.size(); + header.lbd = 0; + header.canbedel = 1; + for (int i = 0; i < ps.size(); i++) + data[i].lit = ps[i]; + + if (header.has_extra){ + if (header.learnt) + data[header.size].act = 0; + else + calcAbstraction(); } + } + +public: + void calcAbstraction() { + assert(header.has_extra); + uint32_t abstraction = 0; + for (int i = 0; i < size(); i++) + abstraction |= 1 << (var(data[i].lit) & 31); + data[header.size].abs = abstraction; } + + + int size () const { return header.size; } + void shrink (int i) { assert(i <= size()); if (header.has_extra) data[header.size-i] = data[header.size]; header.size -= i; } + void pop () { shrink(1); } + bool learnt () const { return header.learnt; } + bool has_extra () const { return header.has_extra; } + uint32_t mark () const { return header.mark; } + void mark (uint32_t m) { header.mark = m; } + const Lit& last () const { return data[header.size-1].lit; } + + bool reloced () const { return header.reloced; } + CRef relocation () const { return data[0].rel; } + void relocate (CRef c) { header.reloced = 1; data[0].rel = c; } + + // NOTE: somewhat unsafe to change the clause in-place! Must manually call 'calcAbstraction' afterwards for + // subsumption operations to behave correctly. + Lit& operator [] (int i) { return data[i].lit; } + Lit operator [] (int i) const { return data[i].lit; } + operator const Lit* (void) const { return (Lit*)data; } + + float& activity () { assert(header.has_extra); return data[header.size].act; } + uint32_t abstraction () const { assert(header.has_extra); return data[header.size].abs; } + + Lit subsumes (const Clause& other) const; + void strengthen (Lit p); + void setLBD(int i) {header.lbd = i;} + // unsigned int& lbd () { return header.lbd; } + unsigned int lbd () const { return header.lbd; } + void setCanBeDel(bool b) {header.canbedel = b;} + bool canBeDel() {return header.canbedel;} + void setSizeWithoutSelectors (unsigned int n) {header.szWithoutSelectors = n; } + unsigned int sizeWithoutSelectors () const { return header.szWithoutSelectors; } + +}; + + +//================================================================================================= +// ClauseAllocator -- a simple class for allocating memory for clauses: + + +const CRef CRef_Undef = RegionAllocator<uint32_t>::Ref_Undef; +class ClauseAllocator : public RegionAllocator<uint32_t> +{ + static int clauseWord32Size(int size, bool has_extra){ + return (sizeof(Clause) + (sizeof(Lit) * (size + (int)has_extra))) / sizeof(uint32_t); } + public: + bool extra_clause_field; + + ClauseAllocator(uint32_t start_cap) : RegionAllocator<uint32_t>(start_cap), extra_clause_field(false){} + ClauseAllocator() : extra_clause_field(false){} + + void moveTo(ClauseAllocator& to){ + to.extra_clause_field = extra_clause_field; + RegionAllocator<uint32_t>::moveTo(to); } + + template<class Lits> + CRef alloc(const Lits& ps, bool learnt = false) + { + assert(sizeof(Lit) == sizeof(uint32_t)); + assert(sizeof(float) == sizeof(uint32_t)); + bool use_extra = learnt | extra_clause_field; + + CRef cid = RegionAllocator<uint32_t>::alloc(clauseWord32Size(ps.size(), use_extra)); + new (lea(cid)) Clause(ps, use_extra, learnt); + + return cid; + } + + // Deref, Load Effective Address (LEA), Inverse of LEA (AEL): + Clause& operator[](Ref r) { return (Clause&)RegionAllocator<uint32_t>::operator[](r); } + const Clause& operator[](Ref r) const { return (Clause&)RegionAllocator<uint32_t>::operator[](r); } + Clause* lea (Ref r) { return (Clause*)RegionAllocator<uint32_t>::lea(r); } + const Clause* lea (Ref r) const { return (Clause*)RegionAllocator<uint32_t>::lea(r); } + Ref ael (const Clause* t){ return RegionAllocator<uint32_t>::ael((uint32_t*)t); } + + void free_(CRef cid) + { + Clause& c = operator[](cid); + RegionAllocator<uint32_t>::free_(clauseWord32Size(c.size(), c.has_extra())); + } + + void reloc(CRef& cr, ClauseAllocator& to) + { + Clause& c = operator[](cr); + + if (c.reloced()) { cr = c.relocation(); return; } + + cr = to.alloc(c, c.learnt()); + c.relocate(cr); + + // Copy extra data-fields: + // (This could be cleaned-up. Generalize Clause-constructor to be applicable here instead?) + to[cr].mark(c.mark()); + if (to[cr].learnt()) { + to[cr].activity() = c.activity(); + to[cr].setLBD(c.lbd()); + to[cr].setSizeWithoutSelectors(c.sizeWithoutSelectors()); + to[cr].setCanBeDel(c.canBeDel()); + } + else if (to[cr].has_extra()) to[cr].calcAbstraction(); + } +}; + + +//================================================================================================= +// OccLists -- a class for maintaining occurence lists with lazy deletion: + +template<class Idx, class Vec, class Deleted> +class OccLists +{ + vec<Vec> occs; + vec<char> dirty; + vec<Idx> dirties; + Deleted deleted; + + public: + OccLists(const Deleted& d) : deleted(d) {} + + void init (const Idx& idx){ occs.growTo(toInt(idx)+1); dirty.growTo(toInt(idx)+1, 0); } + void prelocate (const int num){ occs.prelocate(num); dirty.prelocate(num); } + // Vec& operator[](const Idx& idx){ return occs[toInt(idx)]; } + Vec& operator[](const Idx& idx){ return occs[toInt(idx)]; } + Vec& lookup (const Idx& idx){ if (dirty[toInt(idx)]) clean(idx); return occs[toInt(idx)]; } + + void cleanAll (); + void clean (const Idx& idx); + void smudge (const Idx& idx){ + if (dirty[toInt(idx)] == 0){ + dirty[toInt(idx)] = 1; + dirties.push(idx); + } + } + + void clear(bool free = true){ + if(free){ + occs .clear(free); + dirty .clear(free); + dirties.clear(free); + } else { + occs .shrink (occs .size()); + dirty .shrink_(dirty .size()); + dirties.shrink_(dirties.size()); + } + } +}; + + +template<class Idx, class Vec, class Deleted> +void OccLists<Idx,Vec,Deleted>::cleanAll() +{ + for (int i = 0; i < dirties.size(); i++) + // Dirties may contain duplicates so check here if a variable is already cleaned: + if (dirty[toInt(dirties[i])]) + clean(dirties[i]); + dirties.shrink_( dirties.size() ); +} + + +template<class Idx, class Vec, class Deleted> +void OccLists<Idx,Vec,Deleted>::clean(const Idx& idx) +{ + Vec& vec = occs[toInt(idx)]; + int i, j; + for (i = j = 0; i < vec.size(); i++) + if (!deleted(vec[i])) + vec[j++] = vec[i]; + vec.shrink_(i - j); + dirty[toInt(idx)] = 0; +} + + +//================================================================================================= +// CMap -- a class for mapping clauses to values: + + +template<class T> +class CMap +{ + struct CRefHash { + uint32_t operator()(CRef cr) const { return (uint32_t)cr; } }; + + typedef Map<CRef, T, CRefHash> HashTable; + HashTable map; + + public: + // Size-operations: + void clear () { map.clear(); } + int size () const { return map.elems(); } + + + // Insert/Remove/Test mapping: + void insert (CRef cr, const T& t){ map.insert(cr, t); } + void growTo (CRef cr, const T& t){ map.insert(cr, t); } // NOTE: for compatibility + void remove (CRef cr) { map.remove(cr); } + bool has (CRef cr, T& t) { return map.peek(cr, t); } + + // Vector interface (the clause 'c' must already exist): + const T& operator [] (CRef cr) const { return map[cr]; } + T& operator [] (CRef cr) { return map[cr]; } + + // Iteration (not transparent at all at the moment): + int bucket_count() const { return map.bucket_count(); } + const vec<typename HashTable::Pair>& bucket(int i) const { return map.bucket(i); } + + // Move contents to other map: + void moveTo(CMap& other){ map.moveTo(other.map); } + + // TMP debug: + void debug(){ + printf(" --- size = %d, bucket_count = %d\n", size(), map.bucket_count()); } +}; + + +/*_________________________________________________________________________________________________ +| +| subsumes : (other : const Clause&) -> Lit +| +| Description: +| Checks if clause subsumes 'other', and at the same time, if it can be used to simplify 'other' +| by subsumption resolution. +| +| Result: +| lit_Error - No subsumption or simplification +| lit_Undef - Clause subsumes 'other' +| p - The literal p can be deleted from 'other' +|________________________________________________________________________________________________@*/ +inline Lit Clause::subsumes(const Clause& other) const +{ + //if (other.size() < size() || (extra.abst & ~other.extra.abst) != 0) + //if (other.size() < size() || (!learnt() && !other.learnt() && (extra.abst & ~other.extra.abst) != 0)) + assert(!header.learnt); assert(!other.header.learnt); + assert(header.has_extra); assert(other.header.has_extra); + if (other.header.size < header.size || (data[header.size].abs & ~other.data[other.header.size].abs) != 0) + return lit_Error; + + Lit ret = lit_Undef; + const Lit* c = (const Lit*)(*this); + const Lit* d = (const Lit*)other; + + for (unsigned i = 0; i < header.size; i++) { + // search for c[i] or ~c[i] + for (unsigned j = 0; j < other.header.size; j++) + if (c[i] == d[j]) + goto ok; + else if (ret == lit_Undef && c[i] == ~d[j]){ + ret = c[i]; + goto ok; + } + + // did not find it + return lit_Error; + ok:; + } + + return ret; +} + +inline void Clause::strengthen(Lit p) +{ + remove(*this, p); + calcAbstraction(); +} + +//================================================================================================= +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/src/sat/glucose2/Sort.h b/src/sat/glucose2/Sort.h new file mode 100644 index 00000000..6be112ca --- /dev/null +++ b/src/sat/glucose2/Sort.h @@ -0,0 +1,101 @@ +/******************************************************************************************[Sort.h] +Copyright (c) 2003-2007, Niklas Een, Niklas Sorensson +Copyright (c) 2007-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#ifndef Glucose_Sort_h +#define Glucose_Sort_h + +#include "sat/glucose2/Vec.h" + +//================================================================================================= +// Some sorting algorithms for vec's + +ABC_NAMESPACE_CXX_HEADER_START + +namespace Gluco2 { + +template<class T> +struct LessThan_default { + bool operator () (T x, T y) { return x < y; } +}; + + +template <class T, class LessThan> +void selectionSort(T* array, int size, LessThan lt) +{ + int i, j, best_i; + T tmp; + + for (i = 0; i < size-1; i++){ + best_i = i; + for (j = i+1; j < size; j++){ + if (lt(array[j], array[best_i])) + best_i = j; + } + tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; + } +} +template <class T> static inline void selectionSort(T* array, int size) { + selectionSort(array, size, LessThan_default<T>()); } + +template <class T, class LessThan> +void sort(T* array, int size, LessThan lt) +{ + if (size <= 15) + selectionSort(array, size, lt); + + else{ + T pivot = array[size / 2]; + T tmp; + int i = -1; + int j = size; + + for(;;){ + do i++; while(lt(array[i], pivot)); + do j--; while(lt(pivot, array[j])); + + if (i >= j) break; + + tmp = array[i]; array[i] = array[j]; array[j] = tmp; + } + + sort(array , i , lt); + sort(&array[i], size-i, lt); + } +} +template <class T> static inline void sort(T* array, int size) { + sort(array, size, LessThan_default<T>()); } + + +//================================================================================================= +// For 'vec's: + + +template <class T, class LessThan> void sort(vec<T>& v, LessThan lt) { + sort((T*)v, v.size(), lt); } +template <class T> void sort(vec<T>& v) { + sort(v, LessThan_default<T>()); } + + +//================================================================================================= +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/src/sat/glucose2/System.h b/src/sat/glucose2/System.h new file mode 100644 index 00000000..088bada5 --- /dev/null +++ b/src/sat/glucose2/System.h @@ -0,0 +1,73 @@ +/****************************************************************************************[System.h] +Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson +Copyright (c) 2007-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#ifndef Glucose_System_h +#define Glucose_System_h + +#if defined(__linux__) +//#include <fpu_control.h> +#endif + +#include "sat/glucose2/IntTypes.h" + +ABC_NAMESPACE_CXX_HEADER_START + +//------------------------------------------------------------------------------------------------- + +namespace Gluco2 { + +static inline double cpuTime(void); // CPU-time in seconds. +extern double memUsed(); // Memory in mega bytes (returns 0 for unsupported architectures). +extern double memUsedPeak(); // Peak-memory in mega bytes (returns 0 for unsupported architectures). + +} + +ABC_NAMESPACE_CXX_HEADER_END + +//------------------------------------------------------------------------------------------------- +// Implementation of inline functions: + +#if defined(_MSC_VER) || defined(__MINGW32__) +#include <time.h> + +ABC_NAMESPACE_CXX_HEADER_START + +static inline double Gluco2::cpuTime(void) { return (double)clock() / CLOCKS_PER_SEC; } + +ABC_NAMESPACE_CXX_HEADER_END + + +#else +#include <sys/time.h> +#include <sys/resource.h> +#include <unistd.h> + +ABC_NAMESPACE_CXX_HEADER_START + +static inline double Gluco2::cpuTime(void) { + struct rusage ru; + getrusage(RUSAGE_SELF, &ru); + return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; } + +ABC_NAMESPACE_CXX_HEADER_END + +#endif + +#endif diff --git a/src/sat/glucose2/System2.cpp b/src/sat/glucose2/System2.cpp new file mode 100644 index 00000000..844220a0 --- /dev/null +++ b/src/sat/glucose2/System2.cpp @@ -0,0 +1,116 @@ +/***************************************************************************************[System.cc] +Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson +Copyright (c) 2007-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#include "sat/glucose2/System.h" + +#if defined(__linux__) + +#include <stdio.h> +#include <stdlib.h> + +ABC_NAMESPACE_IMPL_START + +using namespace Gluco2; + +// TODO: split the memory reading functions into two: one for reading high-watermark of RSS, and +// one for reading the current virtual memory size. + +static inline int memReadStat(int field) +{ + char name[256]; + pid_t pid = getpid(); + int value; + + sprintf(name, "/proc/%d/statm", pid); + FILE* in = fopen(name, "rb"); + if (in == NULL) return 0; + + for (; field >= 0; field--) + if (fscanf(in, "%d", &value) != 1) + printf("ERROR! Failed to parse memory statistics from \"/proc\".\n"), exit(1); + fclose(in); + return value; +} + + +static inline int memReadPeak(void) +{ + char name[256]; + pid_t pid = getpid(); + + sprintf(name, "/proc/%d/status", pid); + FILE* in = fopen(name, "rb"); + if (in == NULL) return 0; + + // Find the correct line, beginning with "VmPeak:": + int peak_kb = 0; + while (!feof(in) && fscanf(in, "VmPeak: %d kB", &peak_kb) != 1) + while (!feof(in) && fgetc(in) != '\n') + ; + fclose(in); + + return peak_kb; +} + +double Gluco2::memUsed() { return (double)memReadStat(0) * (double)getpagesize() / (1024*1024); } +double Gluco2::memUsedPeak() { + double peak = memReadPeak() / 1024; + return peak == 0 ? memUsed() : peak; } + +ABC_NAMESPACE_IMPL_END + +#elif defined(__FreeBSD__) + +ABC_NAMESPACE_IMPL_START + +using namespace Gluco2; + +double Gluco2::memUsed(void) { + struct rusage ru; + getrusage(RUSAGE_SELF, &ru); + return (double)ru.ru_maxrss / 1024; } +double memUsedPeak(void) { return memUsed(); } + +ABC_NAMESPACE_IMPL_END + +#elif defined(__APPLE__) + +#include <malloc/malloc.h> + +ABC_NAMESPACE_IMPL_START + +double Gluco2::memUsed(void) { + malloc_statistics_t t; + malloc_zone_statistics(NULL, &t); + return (double)t.max_size_in_use / (1024*1024); } + +ABC_NAMESPACE_IMPL_END + +#else + +ABC_NAMESPACE_IMPL_START + +double Gluco2::memUsed() { + return 0; } + +ABC_NAMESPACE_IMPL_END + +#endif + diff --git a/src/sat/glucose2/Vec.h b/src/sat/glucose2/Vec.h new file mode 100644 index 00000000..eaeed207 --- /dev/null +++ b/src/sat/glucose2/Vec.h @@ -0,0 +1,152 @@ +/*******************************************************************************************[Vec.h] +Copyright (c) 2003-2007, Niklas Een, Niklas Sorensson +Copyright (c) 2007-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#ifndef Glucose_Vec_h +#define Glucose_Vec_h + +#include <assert.h> +#include <new> + +#include "sat/glucose2/IntTypes.h" +#include "sat/glucose2/XAlloc.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace Gluco2 { + +//================================================================================================= +// Automatically resizable arrays +// +// NOTE! Don't use this vector on datatypes that cannot be re-located in memory (with realloc) + +template<class T> +class vec { + T* data; + int sz; + int cap; + + // Don't allow copying (error prone): + vec<T>& operator = (vec<T>& other) { assert(0); return *this; } + vec (vec<T>& other) { assert(0); } + + // Helpers for calculating next capacity: + static inline int imax (int x, int y) { int mask = (y-x) >> (sizeof(int)*8-1); return (x&mask) + (y&(~mask)); } + //static inline void nextCap(int& cap){ cap += ((cap >> 1) + 2) & ~1; } + static inline void nextCap(int& cap){ cap += ((cap >> 1) + 2) & ~1; } + +public: + // Constructors: + vec() : data(NULL) , sz(0) , cap(0) { } + explicit vec(int size) : data(NULL) , sz(0) , cap(0) { growTo(size); } + vec(int size, const T& pad) : data(NULL) , sz(0) , cap(0) { growTo(size, pad); } + ~vec() { clear(true); } + + // Pointer to first element: + operator T* (void) { return data; } + + // Size operations: + int size (void) const { return sz; } + void shrink (int nelems) { assert(nelems <= sz); for (int i = 0; i < nelems; i++) sz--, data[sz].~T(); } + void shrink_ (int nelems) { assert(nelems <= sz); sz -= nelems; } + int capacity (void) const { return cap; } + void capacity (int min_cap); + void prelocate(int ext_cap); + void growTo (int size); + void growTo_ (int size); + void growTo (int size, const T& pad); + void clear (bool dealloc = false); + + // Stack interface: + void push (void) { if (sz == cap) capacity(sz+1); new (&data[sz]) T(); sz++; } + void push (const T& elem) { if (sz == cap) capacity(sz+1); data[sz++] = elem; } + void push_ (const T& elem) { assert(sz < cap); data[sz++] = elem; } + void pop (void) { assert(sz > 0); sz--, data[sz].~T(); } + // NOTE: it seems possible that overflow can happen in the 'sz+1' expression of 'push()', but + // in fact it can not since it requires that 'cap' is equal to INT_MAX. This in turn can not + // happen given the way capacities are calculated (below). Essentially, all capacities are + // even, but INT_MAX is odd. + + const T& last (void) const { return data[sz-1]; } + T& last (void) { return data[sz-1]; } + + // Vector interface: + const T& operator [] (int index) const { return data[index]; } + T& operator [] (int index) { return data[index]; } + + // Duplicatation (preferred instead): + void copyTo (vec<T>& copy) const { copy.clear(); copy.growTo(sz); for (int i = 0; i < sz; i++) copy[i] = data[i]; } + void copyTo_(vec<T>& copy) const { copy.shrink_(copy.size()); copy.growTo_(sz); for (int i = 0; i < sz; i++) copy[i] = data[i]; } + void moveTo(vec<T>& dest) { dest.clear(true); dest.data = data; dest.sz = sz; dest.cap = cap; data = NULL; sz = 0; cap = 0; } +}; + + +template<class T> +void vec<T>::capacity(int min_cap) { + if (cap >= min_cap) return; + int add = imax((min_cap - cap + 1) & ~1, ((cap >> 1) + 2) & ~1); // NOTE: grow by approximately 3/2 + if (add > INT_MAX - cap || (((data = (T*)::realloc(data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM)) + throw OutOfMemoryException(); + } + +template<class T> +void vec<T>::prelocate(int ext_cap) { + if (cap >= ext_cap) return; + if (ext_cap > INT_MAX || (((data = (T*)::realloc(data, ext_cap * sizeof(T))) == NULL) && errno == ENOMEM)) + throw OutOfMemoryException(); + cap = ext_cap; + } + + +template<class T> +void vec<T>::growTo(int size, const T& pad) { + if (sz >= size) return; + capacity(size); + for (int i = sz; i < size; i++) data[i] = pad; + sz = size; } + + +template<class T> +void vec<T>::growTo(int size) { + if (sz >= size) return; + capacity(size); + for (int i = sz; i < size; i++) new (&data[i]) T(); + sz = size; } + + +template<class T> +void vec<T>::growTo_(int size) { + if (sz >= size) return; + capacity(size); + sz = size; } + + +template<class T> +void vec<T>::clear(bool dealloc) { + if (data != NULL){ + for (int i = 0; i < sz; i++) data[i].~T(); + sz = 0; + if (dealloc) free(data), data = NULL, cap = 0; } } + +//================================================================================================= +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/src/sat/glucose2/XAlloc.h b/src/sat/glucose2/XAlloc.h new file mode 100644 index 00000000..716643ef --- /dev/null +++ b/src/sat/glucose2/XAlloc.h @@ -0,0 +1,53 @@ +/****************************************************************************************[XAlloc.h] +Copyright (c) 2009-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + + +#ifndef Glucose_XAlloc_h +#define Glucose_XAlloc_h + +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> + +#include <misc/util/abc_namespaces.h> + +ABC_NAMESPACE_CXX_HEADER_START + +namespace Gluco2 { + +//================================================================================================= +// Simple layer on top of malloc/realloc to catch out-of-memory situtaions and provide some typing: + +class OutOfMemoryException{}; +static inline void* xrealloc(void *ptr, size_t size) +{ + void* mem = realloc(ptr, size); + if (mem == NULL && errno == ENOMEM){ + throw OutOfMemoryException(); + }else { + return mem; + } +} + +//================================================================================================= +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/src/sat/glucose2/license b/src/sat/glucose2/license new file mode 100644 index 00000000..04ed174b --- /dev/null +++ b/src/sat/glucose2/license @@ -0,0 +1,32 @@ +--------------- + +Glucose -- Copyright (c) 2013, Gilles Audemard, Laurent Simon + CRIL - Univ. Artois, France + LRI - Univ. Paris Sud, France + +Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions +and copyrights of Glucose are exactly the same as Minisat on which it is based +on. (see below). + +--------------- + +Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson +Copyright (c) 2007-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*******************************************************************************/
\ No newline at end of file diff --git a/src/sat/glucose2/module.make b/src/sat/glucose2/module.make new file mode 100644 index 00000000..c23cdc53 --- /dev/null +++ b/src/sat/glucose2/module.make @@ -0,0 +1,6 @@ +SRC += src/sat/glucose2/AbcGlucose2.cpp \ + src/sat/glucose2/AbcGlucoseCmd2.cpp \ + src/sat/glucose2/Glucose2.cpp \ + src/sat/glucose2/Options2.cpp \ + src/sat/glucose2/SimpSolver2.cpp \ + src/sat/glucose2/System2.cpp diff --git a/src/sat/glucose2/pstdint.h b/src/sat/glucose2/pstdint.h new file mode 100644 index 00000000..989d0169 --- /dev/null +++ b/src/sat/glucose2/pstdint.h @@ -0,0 +1,919 @@ +/* A portable stdint.h + **************************************************************************** + * BSD License: + **************************************************************************** + * + * Copyright (c) 2005-2016 Paul Hsieh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************** + * + * Version 0.1.16.0 + * + * The ANSI C standard committee, for the C99 standard, specified the + * inclusion of a new standard include file called stdint.h. This is + * a very useful and long desired include file which contains several + * very precise definitions for integer scalar types that is critically + * important for making several classes of applications portable + * including cryptography, hashing, variable length integer libraries + * and so on. But for most developers its likely useful just for + * programming sanity. + * + * The problem is that some compiler vendors chose to ignore the C99 + * standard and some older compilers have no opportunity to be updated. + * Because of this situation, simply including stdint.h in your code + * makes it unportable. + * + * So that's what this file is all about. It's an attempt to build a + * single universal include file that works on as many platforms as + * possible to deliver what stdint.h is supposed to. Even compilers + * that already come with stdint.h can use this file instead without + * any loss of functionality. A few things that should be noted about + * this file: + * + * 1) It is not guaranteed to be portable and/or present an identical + * interface on all platforms. The extreme variability of the + * ANSI C standard makes this an impossibility right from the + * very get go. Its really only meant to be useful for the vast + * majority of platforms that possess the capability of + * implementing usefully and precisely defined, standard sized + * integer scalars. Systems which are not intrinsically 2s + * complement may produce invalid constants. + * + * 2) There is an unavoidable use of non-reserved symbols. + * + * 3) Other standard include files are invoked. + * + * 4) This file may come in conflict with future platforms that do + * include stdint.h. The hope is that one or the other can be + * used with no real difference. + * + * 5) In the current version, if your platform can't represent + * int32_t, int16_t and int8_t, it just dumps out with a compiler + * error. + * + * 6) 64 bit integers may or may not be defined. Test for their + * presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX. + * Note that this is different from the C99 specification which + * requires the existence of 64 bit support in the compiler. If + * this is not defined for your platform, yet it is capable of + * dealing with 64 bits then it is because this file has not yet + * been extended to cover all of your system's capabilities. + * + * 7) (u)intptr_t may or may not be defined. Test for its presence + * with the test: #ifdef PTRDIFF_MAX. If this is not defined + * for your platform, then it is because this file has not yet + * been extended to cover all of your system's capabilities, not + * because its optional. + * + * 8) The following might not been defined even if your platform is + * capable of defining it: + * + * WCHAR_MIN + * WCHAR_MAX + * (u)int64_t + * PTRDIFF_MIN + * PTRDIFF_MAX + * (u)intptr_t + * + * 9) The following have not been defined: + * + * WINT_MIN + * WINT_MAX + * + * 10) The criteria for defining (u)int_least(*)_t isn't clear, + * except for systems which don't have a type that precisely + * defined 8, 16, or 32 bit types (which this include file does + * not support anyways). Default definitions have been given. + * + * 11) The criteria for defining (u)int_fast(*)_t isn't something I + * would trust to any particular compiler vendor or the ANSI C + * committee. It is well known that "compatible systems" are + * commonly created that have very different performance + * characteristics from the systems they are compatible with, + * especially those whose vendors make both the compiler and the + * system. Default definitions have been given, but its strongly + * recommended that users never use these definitions for any + * reason (they do *NOT* deliver any serious guarantee of + * improved performance -- not in this file, nor any vendor's + * stdint.h). + * + * 12) The following macros: + * + * PRINTF_INTMAX_MODIFIER + * PRINTF_INT64_MODIFIER + * PRINTF_INT32_MODIFIER + * PRINTF_INT16_MODIFIER + * PRINTF_LEAST64_MODIFIER + * PRINTF_LEAST32_MODIFIER + * PRINTF_LEAST16_MODIFIER + * PRINTF_INTPTR_MODIFIER + * + * are strings which have been defined as the modifiers required + * for the "d", "u" and "x" printf formats to correctly output + * (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t, + * (u)least32_t, (u)least16_t and (u)intptr_t types respectively. + * PRINTF_INTPTR_MODIFIER is not defined for some systems which + * provide their own stdint.h. PRINTF_INT64_MODIFIER is not + * defined if INT64_MAX is not defined. These are an extension + * beyond what C99 specifies must be in stdint.h. + * + * In addition, the following macros are defined: + * + * PRINTF_INTMAX_HEX_WIDTH + * PRINTF_INT64_HEX_WIDTH + * PRINTF_INT32_HEX_WIDTH + * PRINTF_INT16_HEX_WIDTH + * PRINTF_INT8_HEX_WIDTH + * PRINTF_INTMAX_DEC_WIDTH + * PRINTF_INT64_DEC_WIDTH + * PRINTF_INT32_DEC_WIDTH + * PRINTF_INT16_DEC_WIDTH + * PRINTF_UINT8_DEC_WIDTH + * PRINTF_UINTMAX_DEC_WIDTH + * PRINTF_UINT64_DEC_WIDTH + * PRINTF_UINT32_DEC_WIDTH + * PRINTF_UINT16_DEC_WIDTH + * PRINTF_UINT8_DEC_WIDTH + * + * Which specifies the maximum number of characters required to + * print the number of that type in either hexadecimal or decimal. + * These are an extension beyond what C99 specifies must be in + * stdint.h. + * + * Compilers tested (all with 0 warnings at their highest respective + * settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32 + * bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio + * .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3 + * + * This file should be considered a work in progress. Suggestions for + * improvements, especially those which increase coverage are strongly + * encouraged. + * + * Acknowledgements + * + * The following people have made significant contributions to the + * development and testing of this file: + * + * Chris Howie + * John Steele Scott + * Dave Thorup + * John Dill + * Florian Wobbe + * Christopher Sean Morrison + * Mikkel Fahnoe Jorgensen + * + */ + +#include <stddef.h> +#include <limits.h> +#include <signal.h> + +/* + * For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and + * do nothing else. On the Mac OS X version of gcc this is _STDINT_H_. + */ + +#if ((defined(__SUNPRO_C) && __SUNPRO_C >= 0x570) || (defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (__GNUC__ > 3 || defined(_STDINT_H) || defined(_STDINT_H_) || defined (__UINT_FAST64_TYPE__)) )) && !defined (_PSTDINT_H_INCLUDED) +#include <stdint.h> +#define _PSTDINT_H_INCLUDED +# if defined(__GNUC__) && (defined(__x86_64__) || defined(__ppc64__)) && !(defined(__APPLE__) && defined(__MACH__)) +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "l" +# endif +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +# else +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# ifndef PRINTF_INT32_MODIFIER +# if (UINT_MAX == UINT32_MAX) +# define PRINTF_INT32_MODIFIER "" +# else +# define PRINTF_INT32_MODIFIER "l" +# endif +# endif +# endif +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "h" +# endif +# ifndef PRINTF_INTMAX_MODIFIER +# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER +# endif +# ifndef PRINTF_INT64_HEX_WIDTH +# define PRINTF_INT64_HEX_WIDTH "16" +# endif +# ifndef PRINTF_UINT64_HEX_WIDTH +# define PRINTF_UINT64_HEX_WIDTH "16" +# endif +# ifndef PRINTF_INT32_HEX_WIDTH +# define PRINTF_INT32_HEX_WIDTH "8" +# endif +# ifndef PRINTF_UINT32_HEX_WIDTH +# define PRINTF_UINT32_HEX_WIDTH "8" +# endif +# ifndef PRINTF_INT16_HEX_WIDTH +# define PRINTF_INT16_HEX_WIDTH "4" +# endif +# ifndef PRINTF_UINT16_HEX_WIDTH +# define PRINTF_UINT16_HEX_WIDTH "4" +# endif +# ifndef PRINTF_INT8_HEX_WIDTH +# define PRINTF_INT8_HEX_WIDTH "2" +# endif +# ifndef PRINTF_UINT8_HEX_WIDTH +# define PRINTF_UINT8_HEX_WIDTH "2" +# endif +# ifndef PRINTF_INT64_DEC_WIDTH +# define PRINTF_INT64_DEC_WIDTH "19" +# endif +# ifndef PRINTF_UINT64_DEC_WIDTH +# define PRINTF_UINT64_DEC_WIDTH "20" +# endif +# ifndef PRINTF_INT32_DEC_WIDTH +# define PRINTF_INT32_DEC_WIDTH "10" +# endif +# ifndef PRINTF_UINT32_DEC_WIDTH +# define PRINTF_UINT32_DEC_WIDTH "10" +# endif +# ifndef PRINTF_INT16_DEC_WIDTH +# define PRINTF_INT16_DEC_WIDTH "5" +# endif +# ifndef PRINTF_UINT16_DEC_WIDTH +# define PRINTF_UINT16_DEC_WIDTH "5" +# endif +# ifndef PRINTF_INT8_DEC_WIDTH +# define PRINTF_INT8_DEC_WIDTH "3" +# endif +# ifndef PRINTF_UINT8_DEC_WIDTH +# define PRINTF_UINT8_DEC_WIDTH "3" +# endif +# ifndef PRINTF_INTMAX_HEX_WIDTH +# define PRINTF_INTMAX_HEX_WIDTH PRINTF_UINT64_HEX_WIDTH +# endif +# ifndef PRINTF_UINTMAX_HEX_WIDTH +# define PRINTF_UINTMAX_HEX_WIDTH PRINTF_UINT64_HEX_WIDTH +# endif +# ifndef PRINTF_INTMAX_DEC_WIDTH +# define PRINTF_INTMAX_DEC_WIDTH PRINTF_UINT64_DEC_WIDTH +# endif +# ifndef PRINTF_UINTMAX_DEC_WIDTH +# define PRINTF_UINTMAX_DEC_WIDTH PRINTF_UINT64_DEC_WIDTH +# endif + +/* + * Something really weird is going on with Open Watcom. Just pull some of + * these duplicated definitions from Open Watcom's stdint.h file for now. + */ + +# if defined (__WATCOMC__) && __WATCOMC__ >= 1250 +# if !defined (INT64_C) +# define INT64_C(x) (x + (INT64_MAX - INT64_MAX)) +# endif +# if !defined (UINT64_C) +# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX)) +# endif +# if !defined (INT32_C) +# define INT32_C(x) (x + (INT32_MAX - INT32_MAX)) +# endif +# if !defined (UINT32_C) +# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX)) +# endif +# if !defined (INT16_C) +# define INT16_C(x) (x) +# endif +# if !defined (UINT16_C) +# define UINT16_C(x) (x) +# endif +# if !defined (INT8_C) +# define INT8_C(x) (x) +# endif +# if !defined (UINT8_C) +# define UINT8_C(x) (x) +# endif +# if !defined (UINT64_MAX) +# define UINT64_MAX 18446744073709551615ULL +# endif +# if !defined (INT64_MAX) +# define INT64_MAX 9223372036854775807LL +# endif +# if !defined (UINT32_MAX) +# define UINT32_MAX 4294967295UL +# endif +# if !defined (INT32_MAX) +# define INT32_MAX 2147483647L +# endif +# if !defined (INTMAX_MAX) +# define INTMAX_MAX INT64_MAX +# endif +# if !defined (INTMAX_MIN) +# define INTMAX_MIN INT64_MIN +# endif +# endif +#endif + +/* + * I have no idea what is the truly correct thing to do on older Solaris. + * From some online discussions, this seems to be what is being + * recommended. For people who actually are developing on older Solaris, + * what I would like to know is, does this define all of the relevant + * macros of a complete stdint.h? Remember, in pstdint.h 64 bit is + * considered optional. + */ + +#if (defined(__SUNPRO_C) && __SUNPRO_C >= 0x420) && !defined(_PSTDINT_H_INCLUDED) +#include <sys/inttypes.h> +#define _PSTDINT_H_INCLUDED +#endif + +#ifndef _PSTDINT_H_INCLUDED +#define _PSTDINT_H_INCLUDED + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t)-1) +#endif + +/* + * Deduce the type assignments from limits.h under the assumption that + * integer sizes in bits are powers of 2, and follow the ANSI + * definitions. + */ + +#ifndef UINT8_MAX +# define UINT8_MAX 0xff +#endif +#if !defined(uint8_t) && !defined(_UINT8_T) && !defined(vxWorks) +# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S) + typedef unsigned char uint8_t; +# define UINT8_C(v) ((uint8_t) v) +# else +# error "Platform not supported" +# endif +#endif + +#ifndef INT8_MAX +# define INT8_MAX 0x7f +#endif +#ifndef INT8_MIN +# define INT8_MIN INT8_C(0x80) +#endif +#if !defined(int8_t) && !defined(_INT8_T) && !defined(vxWorks) +# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S) + typedef signed char int8_t; +# define INT8_C(v) ((int8_t) v) +# else +# error "Platform not supported" +# endif +#endif + +#ifndef UINT16_MAX +# define UINT16_MAX 0xffff +#endif +#if !defined(uint16_t) && !defined(_UINT16_T) && !defined(vxWorks) +#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S) + typedef unsigned int uint16_t; +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "" +# endif +# define UINT16_C(v) ((uint16_t) (v)) +#elif (USHRT_MAX == UINT16_MAX) + typedef unsigned short uint16_t; +# define UINT16_C(v) ((uint16_t) (v)) +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "h" +# endif +#else +#error "Platform not supported" +#endif +#endif + +#ifndef INT16_MAX +# define INT16_MAX 0x7fff +#endif +#ifndef INT16_MIN +# define INT16_MIN INT16_C(0x8000) +#endif +#if !defined(int16_t) && !defined(_INT16_T) && !defined(vxWorks) +#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S) + typedef signed int int16_t; +# define INT16_C(v) ((int16_t) (v)) +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "" +# endif +#elif (SHRT_MAX == INT16_MAX) + typedef signed short int16_t; +# define INT16_C(v) ((int16_t) (v)) +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "h" +# endif +#else +#error "Platform not supported" +#endif +#endif + +#ifndef UINT32_MAX +# define UINT32_MAX (0xffffffffUL) +#endif +#if !defined(uint32_t) && !defined(_UINT32_T) && !defined(vxWorks) +#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S) + typedef unsigned long uint32_t; +# define UINT32_C(v) v ## UL +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "l" +# endif +#elif (UINT_MAX == UINT32_MAX) + typedef unsigned int uint32_t; +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +# define UINT32_C(v) v ## U +#elif (USHRT_MAX == UINT32_MAX) + typedef unsigned short uint32_t; +# define UINT32_C(v) ((unsigned short) (v)) +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +#else +#error "Platform not supported" +#endif +#endif + +#ifndef INT32_MAX +# define INT32_MAX (0x7fffffffL) +#endif +#ifndef INT32_MIN +# define INT32_MIN INT32_C(0x80000000) +#endif +#if !defined(int32_t) && !defined(_INT32_T) && !defined(vxWorks) +#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S) + typedef signed long int32_t; +# define INT32_C(v) v ## L +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "l" +# endif +#elif (INT_MAX == INT32_MAX) + typedef signed int int32_t; +# define INT32_C(v) v +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +#elif (SHRT_MAX == INT32_MAX) + typedef signed short int32_t; +# define INT32_C(v) ((short) (v)) +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +#else +#error "Platform not supported" +#endif +#endif + +/* + * The macro stdint_int64_defined is temporarily used to record + * whether or not 64 integer support is available. It must be + * defined for any 64 integer extensions for new platforms that are + * added. + */ + +#undef stdint_int64_defined +#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S) +# if (__STDC__ && __STDC_VERSION__ >= 199901L) || defined (S_SPLINT_S) +# define stdint_int64_defined + typedef long long int64_t; + typedef unsigned long long uint64_t; +# define UINT64_C(v) v ## ULL +# define INT64_C(v) v ## LL +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# endif +#endif + +#if !defined (stdint_int64_defined) +# if defined(__GNUC__) && !defined(vxWorks) +# define stdint_int64_defined + __extension__ typedef long long int64_t; + __extension__ typedef unsigned long long uint64_t; +# define UINT64_C(v) v ## ULL +# define INT64_C(v) v ## LL +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S) +# define stdint_int64_defined + typedef long long int64_t; + typedef unsigned long long uint64_t; +# define UINT64_C(v) v ## ULL +# define INT64_C(v) v ## LL +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC) +# define stdint_int64_defined + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; +# define UINT64_C(v) v ## UI64 +# define INT64_C(v) v ## I64 +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "I64" +# endif +# endif +#endif + +#if !defined (LONG_LONG_MAX) && defined (INT64_C) +# define LONG_LONG_MAX INT64_C (9223372036854775807) +#endif +#ifndef ULONG_LONG_MAX +# define ULONG_LONG_MAX UINT64_C (18446744073709551615) +#endif + +#if !defined (INT64_MAX) && defined (INT64_C) +# define INT64_MAX INT64_C (9223372036854775807) +#endif +#if !defined (INT64_MIN) && defined (INT64_C) +# define INT64_MIN INT64_C (-9223372036854775808) +#endif +#if !defined (UINT64_MAX) && defined (INT64_C) +# define UINT64_MAX UINT64_C (18446744073709551615) +#endif + +/* + * Width of hexadecimal for number field. + */ + +#ifndef PRINTF_INT64_HEX_WIDTH +# define PRINTF_INT64_HEX_WIDTH "16" +#endif +#ifndef PRINTF_INT32_HEX_WIDTH +# define PRINTF_INT32_HEX_WIDTH "8" +#endif +#ifndef PRINTF_INT16_HEX_WIDTH +# define PRINTF_INT16_HEX_WIDTH "4" +#endif +#ifndef PRINTF_INT8_HEX_WIDTH +# define PRINTF_INT8_HEX_WIDTH "2" +#endif +#ifndef PRINTF_INT64_DEC_WIDTH +# define PRINTF_INT64_DEC_WIDTH "19" +#endif +#ifndef PRINTF_INT32_DEC_WIDTH +# define PRINTF_INT32_DEC_WIDTH "10" +#endif +#ifndef PRINTF_INT16_DEC_WIDTH +# define PRINTF_INT16_DEC_WIDTH "5" +#endif +#ifndef PRINTF_INT8_DEC_WIDTH +# define PRINTF_INT8_DEC_WIDTH "3" +#endif +#ifndef PRINTF_UINT64_DEC_WIDTH +# define PRINTF_UINT64_DEC_WIDTH "20" +#endif +#ifndef PRINTF_UINT32_DEC_WIDTH +# define PRINTF_UINT32_DEC_WIDTH "10" +#endif +#ifndef PRINTF_UINT16_DEC_WIDTH +# define PRINTF_UINT16_DEC_WIDTH "5" +#endif +#ifndef PRINTF_UINT8_DEC_WIDTH +# define PRINTF_UINT8_DEC_WIDTH "3" +#endif + +/* + * Ok, lets not worry about 128 bit integers for now. Moore's law says + * we don't need to worry about that until about 2040 at which point + * we'll have bigger things to worry about. + */ + +#ifdef stdint_int64_defined + typedef int64_t intmax_t; + typedef uint64_t uintmax_t; +# define INTMAX_MAX INT64_MAX +# define INTMAX_MIN INT64_MIN +# define UINTMAX_MAX UINT64_MAX +# define UINTMAX_C(v) UINT64_C(v) +# define INTMAX_C(v) INT64_C(v) +# ifndef PRINTF_INTMAX_MODIFIER +# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER +# endif +# ifndef PRINTF_INTMAX_HEX_WIDTH +# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH +# endif +# ifndef PRINTF_INTMAX_DEC_WIDTH +# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH +# endif +#else + typedef int32_t intmax_t; + typedef uint32_t uintmax_t; +# define INTMAX_MAX INT32_MAX +# define UINTMAX_MAX UINT32_MAX +# define UINTMAX_C(v) UINT32_C(v) +# define INTMAX_C(v) INT32_C(v) +# ifndef PRINTF_INTMAX_MODIFIER +# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER +# endif +# ifndef PRINTF_INTMAX_HEX_WIDTH +# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH +# endif +# ifndef PRINTF_INTMAX_DEC_WIDTH +# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH +# endif +#endif + +/* + * Because this file currently only supports platforms which have + * precise powers of 2 as bit sizes for the default integers, the + * least definitions are all trivial. Its possible that a future + * version of this file could have different definitions. + */ + +#ifndef stdint_least_defined + typedef int8_t int_least8_t; + typedef uint8_t uint_least8_t; + typedef int16_t int_least16_t; + typedef uint16_t uint_least16_t; + typedef int32_t int_least32_t; + typedef uint32_t uint_least32_t; +# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER +# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER +# define UINT_LEAST8_MAX UINT8_MAX +# define INT_LEAST8_MAX INT8_MAX +# define UINT_LEAST16_MAX UINT16_MAX +# define INT_LEAST16_MAX INT16_MAX +# define UINT_LEAST32_MAX UINT32_MAX +# define INT_LEAST32_MAX INT32_MAX +# define INT_LEAST8_MIN INT8_MIN +# define INT_LEAST16_MIN INT16_MIN +# define INT_LEAST32_MIN INT32_MIN +# ifdef stdint_int64_defined + typedef int64_t int_least64_t; + typedef uint64_t uint_least64_t; +# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER +# define UINT_LEAST64_MAX UINT64_MAX +# define INT_LEAST64_MAX INT64_MAX +# define INT_LEAST64_MIN INT64_MIN +# endif +#endif +#undef stdint_least_defined + +/* + * The ANSI C committee has defined *int*_fast*_t types as well. This, + * of course, defies rationality -- you can't know what will be fast + * just from the type itself. Even for a given architecture, compatible + * implementations might have different performance characteristics. + * Developers are warned to stay away from these types when using this + * or any other stdint.h. + */ + +typedef int_least8_t int_fast8_t; +typedef uint_least8_t uint_fast8_t; +typedef int_least16_t int_fast16_t; +typedef uint_least16_t uint_fast16_t; +typedef int_least32_t int_fast32_t; +typedef uint_least32_t uint_fast32_t; +#define UINT_FAST8_MAX UINT_LEAST8_MAX +#define INT_FAST8_MAX INT_LEAST8_MAX +#define UINT_FAST16_MAX UINT_LEAST16_MAX +#define INT_FAST16_MAX INT_LEAST16_MAX +#define UINT_FAST32_MAX UINT_LEAST32_MAX +#define INT_FAST32_MAX INT_LEAST32_MAX +#define INT_FAST8_MIN INT_LEAST8_MIN +#define INT_FAST16_MIN INT_LEAST16_MIN +#define INT_FAST32_MIN INT_LEAST32_MIN +#ifdef stdint_int64_defined + typedef int_least64_t int_fast64_t; + typedef uint_least64_t uint_fast64_t; +# define UINT_FAST64_MAX UINT_LEAST64_MAX +# define INT_FAST64_MAX INT_LEAST64_MAX +# define INT_FAST64_MIN INT_LEAST64_MIN +#endif + +#undef stdint_int64_defined + +/* + * Whatever piecemeal, per compiler thing we can do about the wchar_t + * type limits. + */ + +#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__) && !defined(vxWorks) +# include <wchar.h> +# ifndef WCHAR_MIN +# define WCHAR_MIN 0 +# endif +# ifndef WCHAR_MAX +# define WCHAR_MAX ((wchar_t)-1) +# endif +#endif + +/* + * Whatever piecemeal, per compiler/platform thing we can do about the + * (u)intptr_t types and limits. + */ + +#if (defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED)) || defined (_UINTPTR_T) +# define STDINT_H_UINTPTR_T_DEFINED +#endif + +#ifndef STDINT_H_UINTPTR_T_DEFINED +# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64) || defined (__ppc64__) +# define stdint_intptr_bits 64 +# elif defined (__WATCOMC__) || defined (__TURBOC__) +# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__) +# define stdint_intptr_bits 16 +# else +# define stdint_intptr_bits 32 +# endif +# elif defined (__i386__) || defined (_WIN32) || defined (WIN32) || defined (__ppc64__) +# define stdint_intptr_bits 32 +# elif defined (__INTEL_COMPILER) +/* TODO -- what did Intel do about x86-64? */ +# else +/* #error "This platform might not be supported yet" */ +# endif + +# ifdef stdint_intptr_bits +# define stdint_intptr_glue3_i(a,b,c) a##b##c +# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c) +# ifndef PRINTF_INTPTR_MODIFIER +# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER) +# endif +# ifndef PTRDIFF_MAX +# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) +# endif +# ifndef PTRDIFF_MIN +# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) +# endif +# ifndef UINTPTR_MAX +# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX) +# endif +# ifndef INTPTR_MAX +# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) +# endif +# ifndef INTPTR_MIN +# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) +# endif +# ifndef INTPTR_C +# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x) +# endif +# ifndef UINTPTR_C +# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x) +# endif + typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t; + typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t; +# else +/* TODO -- This following is likely wrong for some platforms, and does + nothing for the definition of uintptr_t. */ + typedef ptrdiff_t intptr_t; +# endif +# define STDINT_H_UINTPTR_T_DEFINED +#endif + +/* + * Assumes sig_atomic_t is signed and we have a 2s complement machine. + */ + +#ifndef SIG_ATOMIC_MAX +# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1) +#endif + +#endif + +#if defined (__TEST_PSTDINT_FOR_CORRECTNESS) + +/* + * Please compile with the maximum warning settings to make sure macros are + * not defined more than once. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#define glue3_aux(x,y,z) x ## y ## z +#define glue3(x,y,z) glue3_aux(x,y,z) + +#define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,) = glue3(UINT,bits,_C) (0); +#define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,) = glue3(INT,bits,_C) (0); + +#define DECL(us,bits) glue3(DECL,us,) (bits) + +#define TESTUMAX(bits) glue3(u,bits,) = ~glue3(u,bits,); if (glue3(UINT,bits,_MAX) != glue3(u,bits,)) printf ("Something wrong with UINT%d_MAX\n", bits) + +#define REPORTERROR(msg) { err_n++; if (err_first <= 0) err_first = __LINE__; printf msg; } + +#define X_SIZE_MAX ((size_t)-1) + +int main () { + int err_n = 0; + int err_first = 0; + DECL(I,8) + DECL(U,8) + DECL(I,16) + DECL(U,16) + DECL(I,32) + DECL(U,32) +#ifdef INT64_MAX + DECL(I,64) + DECL(U,64) +#endif + intmax_t imax = INTMAX_C(0); + uintmax_t umax = UINTMAX_C(0); + char str0[256], str1[256]; + + sprintf (str0, "%" PRINTF_INT32_MODIFIER "d", INT32_C(2147483647)); + if (0 != strcmp (str0, "2147483647")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str0)); + if (atoi(PRINTF_INT32_DEC_WIDTH) != (int) strlen(str0)) REPORTERROR (("Something wrong with PRINTF_INT32_DEC_WIDTH : %s\n", PRINTF_INT32_DEC_WIDTH)); + sprintf (str0, "%" PRINTF_INT32_MODIFIER "u", UINT32_C(4294967295)); + if (0 != strcmp (str0, "4294967295")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str0)); + if (atoi(PRINTF_UINT32_DEC_WIDTH) != (int) strlen(str0)) REPORTERROR (("Something wrong with PRINTF_UINT32_DEC_WIDTH : %s\n", PRINTF_UINT32_DEC_WIDTH)); +#ifdef INT64_MAX + sprintf (str1, "%" PRINTF_INT64_MODIFIER "d", INT64_C(9223372036854775807)); + if (0 != strcmp (str1, "9223372036854775807")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str1)); + if (atoi(PRINTF_INT64_DEC_WIDTH) != (int) strlen(str1)) REPORTERROR (("Something wrong with PRINTF_INT64_DEC_WIDTH : %s, %d\n", PRINTF_INT64_DEC_WIDTH, (int) strlen(str1))); + sprintf (str1, "%" PRINTF_INT64_MODIFIER "u", UINT64_C(18446744073709550591)); + if (0 != strcmp (str1, "18446744073709550591")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str1)); + if (atoi(PRINTF_UINT64_DEC_WIDTH) != (int) strlen(str1)) REPORTERROR (("Something wrong with PRINTF_UINT64_DEC_WIDTH : %s, %d\n", PRINTF_UINT64_DEC_WIDTH, (int) strlen(str1))); +#endif + + sprintf (str0, "%d %x\n", 0, ~0); + + sprintf (str1, "%d %x\n", i8, ~0); + if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i8 : %s\n", str1)); + sprintf (str1, "%u %x\n", u8, ~0); + if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with u8 : %s\n", str1)); + sprintf (str1, "%d %x\n", i16, ~0); + if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i16 : %s\n", str1)); + sprintf (str1, "%u %x\n", u16, ~0); + if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with u16 : %s\n", str1)); + sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0); + if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i32 : %s\n", str1)); + sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0); + if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with u32 : %s\n", str1)); +#ifdef INT64_MAX + sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0); + if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i64 : %s\n", str1)); +#endif + sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0); + if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with imax : %s\n", str1)); + sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0); + if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with umax : %s\n", str1)); + + TESTUMAX(8); + TESTUMAX(16); + TESTUMAX(32); +#ifdef INT64_MAX + TESTUMAX(64); +#endif + +#define STR(v) #v +#define Q(v) printf ("sizeof " STR(v) " = %u\n", (unsigned) sizeof (v)); + if (err_n) { + printf ("pstdint.h is not correct. Please use sizes below to correct it:\n"); + } + + Q(int) + Q(unsigned) + Q(long int) + Q(short int) + Q(int8_t) + Q(int16_t) + Q(int32_t) +#ifdef INT64_MAX + Q(int64_t) +#endif + +#if UINT_MAX < X_SIZE_MAX + printf ("UINT_MAX < X_SIZE_MAX\n"); +#else + printf ("UINT_MAX >= X_SIZE_MAX\n"); +#endif + printf ("%" PRINTF_INT64_MODIFIER "u vs %" PRINTF_INT64_MODIFIER "u\n", UINT_MAX, X_SIZE_MAX); + + return EXIT_SUCCESS; +} + +#endif diff --git a/src/sat/satoko/utils/sdbl.h b/src/sat/satoko/utils/sdbl.h index 9f90ba02..a26794c7 100644 --- a/src/sat/satoko/utils/sdbl.h +++ b/src/sat/satoko/utils/sdbl.h @@ -121,8 +121,8 @@ static inline void sdbl_test() { sdbl_t ten100_ = ABC_CONST(0x014c924d692ca61b); printf("%f\n", sdbl2double(ten100_)); - printf("%016lX\n", double2sdbl(1 /0.95)); - printf("%016lX\n", SDBL_CONST1); + //printf("%016lX\n", double2sdbl(1 /0.95)); + //printf("%016lX\n", SDBL_CONST1); printf("%f\n", sdbl2double(SDBL_CONST1)); printf("%f\n", sdbl2double(ABC_CONST(0x000086BCA1AF286B))); |