diff options
author | Miodrag Milanovic <mmicko@gmail.com> | 2021-11-12 12:31:29 +0100 |
---|---|---|
committer | Miodrag Milanovic <mmicko@gmail.com> | 2021-11-12 12:31:29 +0100 |
commit | d2d6bbd9f86f61fc9b5cc7d703e1386bbd6ad6a2 (patch) | |
tree | 071fb2118c158c748ff9969ef250affe7b9a3561 /src/aig | |
parent | 4f5f73d18b137930fb3048c0b385c82fa078db38 (diff) | |
parent | 9b245d9f6910c048e9bbcf95ee5dee46f2f24f2c (diff) | |
download | abc-d2d6bbd9f86f61fc9b5cc7d703e1386bbd6ad6a2.tar.gz abc-d2d6bbd9f86f61fc9b5cc7d703e1386bbd6ad6a2.tar.bz2 abc-d2d6bbd9f86f61fc9b5cc7d703e1386bbd6ad6a2.zip |
Merge remote-tracking branch 'upstream/master' into yosys-experimental
Diffstat (limited to 'src/aig')
54 files changed, 14986 insertions, 301 deletions
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) == |