diff --git a/.github/workflows/build-posix-cmake.yml b/.github/workflows/build-posix-cmake.yml index def198107..5e101cd79 100644 --- a/.github/workflows/build-posix-cmake.yml +++ b/.github/workflows/build-posix-cmake.yml @@ -1,4 +1,8 @@ -on: [push] +name: Build Posix CMake + +on: + push: + pull_request: jobs: diff --git a/.github/workflows/build-posix.yml b/.github/workflows/build-posix.yml index aa97aca20..e26b67b89 100644 --- a/.github/workflows/build-posix.yml +++ b/.github/workflows/build-posix.yml @@ -1,4 +1,8 @@ -on: [push] +name: Build Posix + +on: + push: + pull_request: jobs: diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 21cd1b26d..8e1ac37df 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -1,4 +1,8 @@ -on: [push] +name: Build Windows + +on: + push: + pull_request: jobs: diff --git a/CMakeLists.txt b/CMakeLists.txt index cee9bc72f..ce541b994 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,13 @@ -cmake_minimum_required(VERSION 3.3.0) +cmake_minimum_required(VERSION 3.5.0) include(CMakeParseArguments) include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) +# Default c++ standard used unless otherwise specified in target_compile_features. +set(CMAKE_CXX_STANDARD 17 CACHE STRING "the C++ standard to use for this project") +set(CMAKE_CXX_STANDARD_REQUIRED ON) + function(addprefix var prefix) foreach( s ${ARGN} ) list(APPEND tmp "-I${s}") diff --git a/Makefile b/Makefile index ef92eb3e4..dc909bb63 100644 --- a/Makefile +++ b/Makefile @@ -152,7 +152,7 @@ ifdef ABC_USE_LIBSTDCXX endif $(info $(MSG_PREFIX)Using CFLAGS=$(CFLAGS)) -CXXFLAGS += $(CFLAGS) -std=c++11 +CXXFLAGS += $(CFLAGS) -std=c++17 -fno-exceptions SRC := GARBAGE := core core.* *.stackdump ./tags $(PROG) arch_flags diff --git a/abc.rc b/abc.rc index a3efc0b09..c87e70b4b 100644 --- a/abc.rc +++ b/abc.rc @@ -135,6 +135,8 @@ alias resyn2rs "b; rs -K 6; rw; rs -K 6 -N 2; rf; rs -K 8; b; rs -K 8 -N 2; r alias r2rs "b; rs -K 6; rw; rs -K 6 -N 2; rf; rs -K 8; b; rs -K 8 -N 2; rw; rs -K 10; rwz; rs -K 10 -N 2; b; rs -K 12; rfz; rs -K 12 -N 2; rwz; b" alias compress2rs "b -l; rs -K 6 -l; rw -l; rs -K 6 -N 2 -l; rf -l; rs -K 8 -l; b -l; rs -K 8 -N 2 -l; rw -l; rs -K 10 -l; rwz -l; rs -K 10 -N 2 -l; b -l; rs -K 12 -l; rfz -l; rs -K 12 -N 2 -l; rwz -l; b -l" alias c2rs "b -l; rs -K 6 -l; rw -l; rs -K 6 -N 2 -l; rf -l; rs -K 8 -l; b -l; rs -K 8 -N 2 -l; rw -l; rs -K 10 -l; rwz -l; rs -K 10 -N 2 -l; b -l; rs -K 12 -l; rfz -l; rs -K 12 -N 2 -l; rwz -l; b -l" +alias &resyn2rs "&put; resyn2rs; &get" +alias &compress2rs "&put; compress2rs; &get" # use this script to convert 1-valued and DC-valued flops for an AIG alias fix_aig "logic; undc; strash; zero" diff --git a/abclib.dsp b/abclib.dsp index 06802171f..559d59d2a 100644 --- a/abclib.dsp +++ b/abclib.dsp @@ -1195,6 +1195,10 @@ SOURCE=.\src\bdd\extrab\extraBdd.h # End Source File # Begin Source File +SOURCE=.\src\bdd\extrab\extraLutCas.h +# End Source File +# Begin Source File + SOURCE=.\src\bdd\extrab\extraBddAuto.c # End Source File # Begin Source File @@ -4151,6 +4155,10 @@ SOURCE=.\src\misc\util\utilNam.h # End Source File # Begin Source File +SOURCE=.\src\misc\util\utilPth.c +# End Source File +# Begin Source File + SOURCE=.\src\misc\util\utilSignal.c # End Source File # Begin Source File @@ -5123,6 +5131,10 @@ SOURCE=.\src\aig\gia\giaMinLut2.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaMulFind.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaMuxes.c # End Source File # Begin Source File @@ -5370,14 +5382,6 @@ SOURCE=.\src\aig\miniaig\minilut.h SOURCE=.\src\aig\miniaig\ndr.h # End Source File # End Group -# Begin Group "uap" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\uap\uap.h -# End Source File -# End Group # End Group # Begin Group "bool" diff --git a/readmeaig b/readmeaig index 31e512367..7615b8fcc 100644 --- a/readmeaig +++ b/readmeaig @@ -45,3 +45,27 @@ Using GIA Package in ABC - For each object in the design annotated with the constructed AIG node (pNode), remember its AIG node ID by calling Gia_ObjId(pMan,pNode). - Quit the AIG package using Gia_ManStop(). The above process should not produce memory leaks. + + + + +Using MiniAIG Package + +- Add #include "miniaig.h". +- Start the AIG package using Mini_AigStart(). +- Assign primary inputs using Mini_AigCreatePi(). +- Assign flop outputs using Mini_AigCreatePi(). +(It is important to create all PIs first, before creating flop outputs.) +(Flop control logic, if present, should be elaborated into AND gates. For example, to represent a flop enable, create the driver of enable signal, which can be a PI or an internal node, and then add logic for = MUX( , , ). The output of this logic feeds into the flop. +- Construct AIG in a topological order using Mini_AigAnd(), Mini_AigOr(), etc. +- If constant-0 or constant-1 functions are needed, use 0 or 1. +- Create primary outputs using Mini_AigCreatePo(). +- Create flop inputs using Mini_AigCreatePo(). +(It is important to create all POs first, before creating register inputs.) +- Set the number of flops by calling Mini_AigSetRegNum(). +- The AIG may contain internal nodes without fanout and/or internal nodes fed by constants. +- Dump AIG in internal MiniAIG binary format using Mini_AigDump() and read it into ABC using "&read -m file.mini" +- Dump AIG in standard AIGER format (https://fmv.jku.at/aiger/index.html) using Mini_AigerWrite() and read it into ABC using "&read file.aig" +- For each object in the design represented using MiniAIG, it may be helpful to save the MiniAIG literal returned by Mini_AigAnd(), Mini_AigOr(), etc when constructing that object. +- Quit the AIG package using Mini_AigStop(). +The above process should not produce memory leaks. diff --git a/src/aig/aig/aigShow.c b/src/aig/aig/aigShow.c index e3d89942a..7612d02b1 100644 --- a/src/aig/aig/aigShow.c +++ b/src/aig/aig/aigShow.c @@ -344,7 +344,7 @@ void Aig_ManShow( Aig_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) char FileNameDot[200]; FILE * pFile; // create the file name - sprintf( FileNameDot, "%s", Extra_FileNameGenericAppend(pMan->pName, ".dot") ); + sprintf( FileNameDot, "%s", Extra_FileNameGenericAppend(pMan->pName ? pMan->pName : (char *)"unknown", ".dot") ); // check that the file can be opened if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) { diff --git a/src/aig/aig/aigUtil.c b/src/aig/aig/aigUtil.c index 68be112f1..aad8c250c 100644 --- a/src/aig/aig/aigUtil.c +++ b/src/aig/aig/aigUtil.c @@ -1169,8 +1169,13 @@ void Aig_ManRandomTest1() ***********************************************************************/ unsigned Aig_ManRandom( int fReset ) { +#ifdef _MSC_VER static unsigned int m_z = NUMBER1; static unsigned int m_w = NUMBER2; +#else + static __thread unsigned int m_z = NUMBER1; + static __thread unsigned int m_w = NUMBER2; +#endif if ( fReset ) { m_z = NUMBER1; diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index ca413f31d..79b8b3f08 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -243,7 +243,12 @@ struct Gia_Man_t_ Gia_Dat_t * pUData; // retiming data Vec_Str_t * vStopsF; - Vec_Str_t * vStopsB; + Vec_Str_t * vStopsB; + // iteration with boxes + int iFirstNonPiId; + int iFirstPoId; + int iFirstAndObj; + int iFirstPoObj; }; @@ -1243,7 +1248,16 @@ static inline int Gia_ObjCellId( Gia_Man_t * p, int iLit ) { re for ( i = 0; (i < Gia_ManRegNum(p)) && ((pObjRi) = Gia_ManCo(p, Gia_ManPoNum(p)+i)) && ((pObjRo) = Gia_ManCi(p, Gia_ManPiNum(p)+i)); i++ ) #define Gia_ManForEachRoToRiVec( vRoIds, p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(vRoIds)) && ((pObj) = Gia_ObjRoToRi(p, Gia_ManObj(p, Vec_IntEntry(vRoIds, i)))); i++ ) - + +#define Gia_ManForEachObjWithBoxes( p, pObj, i ) \ + for ( i = p->iFirstAndObj; (i < p->iFirstPoObj) && ((pObj) = Gia_ManObj(p, i)); i++ ) +#define Gia_ManForEachObjReverseWithBoxes( p, pObj, i ) \ + for ( i = p->iFirstPoObj - 1; (i >= p->iFirstAndObj) && ((pObj) = Gia_ManObj(p, i)); i-- ) +#define Gia_ManForEachCiIdWithBoxes( p, Id, i ) \ + for ( i = 0; (i < p->iFirstNonPiId) && ((Id) = Gia_ObjId(p, Gia_ManCi(p, i))); i++ ) +#define Gia_ManForEachCoWithBoxes( p, pObj, i ) \ + for ( i = p->iFirstPoId; (i < Vec_IntSize(p->vCos)) && ((pObj) = Gia_ManCo(p, i)); i++ ) + //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// @@ -1673,6 +1687,7 @@ extern int Gia_SweeperRun( Gia_Man_t * p, Vec_Int_t * vProbeIds, extern float Gia_ManEvaluateSwitching( Gia_Man_t * p ); extern float Gia_ManComputeSwitching( Gia_Man_t * p, int nFrames, int nPref, int fProbOne ); extern Vec_Int_t * Gia_ManComputeSwitchProbs( Gia_Man_t * pGia, int nFrames, int nPref, int fProbOne ); +extern Vec_Int_t * Gia_ManComputeSwitchProbs2( Gia_Man_t * pGia, int nFrames, int nPref, int fProbOne, int nRandPiFactor ); extern Vec_Flt_t * Gia_ManPrintOutputProb( Gia_Man_t * p ); /*=== giaTim.c ===========================================================*/ extern int Gia_ManBoxNum( Gia_Man_t * p ); diff --git a/src/aig/gia/giaClp.c b/src/aig/gia/giaClp.c index 68f9bf565..873cea2eb 100644 --- a/src/aig/gia/giaClp.c +++ b/src/aig/gia/giaClp.c @@ -382,7 +382,7 @@ Gia_Man_t * Gia_ManCollapseTest( Gia_Man_t * p, int fVerbose ) Vec_Ptr_t * vNamesCo = Gia_GetFakeNames( Gia_ManCoNum(p) ); char ** ppNamesCi = (char **)Vec_PtrArray( vNamesCi ); char ** ppNamesCo = (char **)Vec_PtrArray( vNamesCo ); - Dsd_TreePrint( stdout, pManDsd, ppNamesCi, ppNamesCo, 0, -1 ); + Dsd_TreePrint( stdout, pManDsd, ppNamesCi, ppNamesCo, 0, -1, 0 ); Vec_PtrFreeFree( vNamesCi ); Vec_PtrFreeFree( vNamesCo ); } @@ -404,6 +404,43 @@ void Gia_ManCollapseTestTest( Gia_Man_t * p ) Gia_ManStop( pNew ); } +void Gia_ManCheckDsd( Gia_Man_t * p, int OffSet, int fVerbose ) +{ + DdManager * dd; + Dsd_Manager_t * pManDsd; + Vec_Ptr_t * vFuncs; + dd = Cudd_Init( Gia_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + vFuncs = Gia_ManCollapse( p, dd, 10000, 0 ); + Cudd_AutodynDisable( dd ); + if ( vFuncs == NULL ) + { + Extra_StopManager( dd ); + return; + } + pManDsd = Dsd_ManagerStart( dd, Gia_ManCiNum(p), 0 ); + if ( pManDsd == NULL ) + { + Gia_ManCollapseDeref( dd, vFuncs ); + Cudd_Quit( dd ); + return; + } + Dsd_Decompose( pManDsd, (DdNode **)vFuncs->pArray, Gia_ManCoNum(p) ); + if ( fVerbose ) + { + Vec_Ptr_t * vNamesCi = Gia_GetFakeNames( Gia_ManCiNum(p) ); + Vec_Ptr_t * vNamesCo = Gia_GetFakeNames( Gia_ManCoNum(p) ); + char ** ppNamesCi = (char **)Vec_PtrArray( vNamesCi ); + char ** ppNamesCo = (char **)Vec_PtrArray( vNamesCo ); + Dsd_TreePrint( stdout, pManDsd, ppNamesCi, ppNamesCo, 0, -1, OffSet ); + Vec_PtrFreeFree( vNamesCi ); + Vec_PtrFreeFree( vNamesCo ); + } + Dsd_ManagerStop( pManDsd ); + Gia_ManCollapseDeref( dd, vFuncs ); + Extra_StopManager( dd ); +} + #else Gia_Man_t * Gia_ManCollapseTest( Gia_Man_t * p, int fVerbose ) @@ -411,6 +448,10 @@ Gia_Man_t * Gia_ManCollapseTest( Gia_Man_t * p, int fVerbose ) return NULL; } +void Gia_ManCheckDsd( Gia_Man_t * p, int OffSet, int fVerbose ) +{ +} + #endif //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaCof.c b/src/aig/gia/giaCof.c index c6ccb7d1f..d89e25867 100644 --- a/src/aig/gia/giaCof.c +++ b/src/aig/gia/giaCof.c @@ -993,6 +993,97 @@ Gia_Man_t * Gia_ManDupCofAll( Gia_Man_t * p, int nFanLim, int fVerbose ) return pNew; } +/**Function************************************************************* + + Synopsis [Print the matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDsdMatrix( Gia_Man_t * p, int iIn ) +{ + Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, j; + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + assert( Gia_ManPoNum(p) == 1 ); + assert( iIn >= 0 && iIn < Gia_ManPiNum(p) ); + 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_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + for ( i = 0; i < Gia_ManPiNum(p); i++ ) if ( i != iIn ) + for ( j = i+1; j < Gia_ManPiNum(p); j++ ) if ( j != iIn ) + { + int pRes[8], k, n; + int iLit0 = Gia_ManPi(p, iIn)->Value; + int iLit1 = Gia_ManPi(p, i)->Value; + int iLit2 = Gia_ManPi(p, j)->Value; + for ( k = 0; k < 8; k++ ) + { + Gia_ManPi(p, iIn)->Value = k & 1; + Gia_ManPi(p, i)->Value = (k >> 1) & 1; + Gia_ManPi(p, j)->Value = (k >> 2) & 1; + Gia_ManForEachAnd( p, pObj, n ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + pRes[k] = Gia_ObjFanin0Copy(Gia_ManPo(p, 0)); + } + Gia_ManPi(p, iIn)->Value = iLit0; + Gia_ManPi(p, i)->Value = iLit1; + Gia_ManPi(p, j)->Value = iLit2; + for ( k = 0; k < 4; k++ ) + pRes[k] = Gia_ManHashXor( pNew, pRes[2*k], pRes[2*k+1] ); + Vec_IntPush( vRes, Gia_ManHashXor(pNew, Gia_ManHashAnd(pNew, pRes[0], pRes[3]), Gia_ManHashAnd(pNew, pRes[1], pRes[2])) ); + } + Vec_IntForEachEntry( vRes, j, i ) + Gia_ManAppendCo( pNew, j ); + Vec_IntFree( vRes ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +void Gia_ManPrintDsdMatrix( Gia_Man_t * p, int iIn ) +{ + extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); + Gia_Man_t * pNew = Gia_ManDsdMatrix( p, iIn ); int i, j, fFirst = 1, Count = 0; + Gia_Man_t * pSweep = Cec4_ManSimulateTest3( pNew, 0, 0 ); + Gia_ManStop( pNew ); + printf( "%4c : ", ' ' ); + for ( j = 0; j < Gia_ManPiNum(p); j++ ) + printf( "%4d", j ); + printf( "\n" ); + for ( i = 0; i < Gia_ManPiNum(p); i++, printf("\n"), fFirst = 1 ) + for ( j = 0; j < Gia_ManPiNum(p); j++ ) + { + if ( fFirst ) + printf( "%4d : ", i ), fFirst = 0; + if ( i == iIn ) + continue; + if ( j == iIn ) + printf( "%4c", ' ' ); + else + { + if ( j > i ) { + if ( Gia_ObjFaninLit0p(pSweep, Gia_ManPo(pSweep, Count++)) == 0 ) + printf( "%4c", '.' ); + else + printf( "%4c", '+' ); + } + else + printf( "%4c", ' ' ); + } + } + assert( Count == Gia_ManPoNum(pSweep) ); + Gia_ManStop( pSweep ); +} + + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaCut.c b/src/aig/gia/giaCut.c index 19e2d8fc9..47dc5ec7b 100644 --- a/src/aig/gia/giaCut.c +++ b/src/aig/gia/giaCut.c @@ -986,10 +986,127 @@ Vec_Wec_t * Gia_ManExploreCuts( Gia_Man_t * pGia, int nCutSize0, int nCuts0, int Abc_PrintTime( 0, "Time", Abc_Clock() - p->clkStart ); } vCutsSel = Gia_ManFilterCuts( pGia, p->vCuts, nCutSize0, nCuts0 ); - Gia_ManConsiderCuts( pGia, vCutsSel ); + //Gia_ManConsiderCuts( pGia, vCutsSel ); Gia_StoFree( p ); return vCutsSel; } +void Gia_ManExploreCutsTest( Gia_Man_t * pGia, int nCutSize0, int nCuts0, int fVerbose0 ) +{ + Vec_Wec_t * vCutSel = Gia_ManExploreCuts( pGia, nCutSize0, nCuts0, fVerbose0 ); + Vec_WecPrint( vCutSel, 0 ); + Vec_WecFree( vCutSel ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Sto_t * Gia_ManMatchCutsInt( Gia_Man_t * pGia, int nCutSize0, int nCutNum0, int fVerbose0 ) +{ + int nCutSize = nCutSize0; + int nCutNum = nCutNum0; + int fCutMin = 1; + int fTruthMin = 1; + int fVerbose = fVerbose0; + 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 ); + } + return p; +} +void Gia_ManMatchCuts( Vec_Mem_t * vTtMem, Gia_Man_t * pGia, int nCutSize, int nCutNum, int fVerbose ) +{ + Gia_Sto_t * p = Gia_ManMatchCutsInt( pGia, nCutSize, nCutNum, fVerbose ); + Vec_Int_t * vLevel; int i, k, * pCut; + Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); + abctime clkStart = Abc_Clock(); + assert( Abc_Truth6WordNum(nCutSize) == Vec_MemEntrySize(vTtMem) ); + Vec_WecForEachLevel( p->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) + { + Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) if ( pCut[0] > 1 ) + { + word * pTruth = Vec_MemReadEntry( p->vTtMem, Abc_Lit2Var(pCut[pCut[0]+1]) ); + int * pSpot = Vec_MemHashLookup( vTtMem, pTruth ); + if ( *pSpot == -1 ) + continue; + Vec_IntPush( vNodes, i ); + break; + } + } + printf( "Nodes with matching cuts: " ); + Vec_IntPrint( vNodes ); + Vec_IntFree( vNodes ); + Gia_StoFree( p ); + if ( fVerbose ) + Abc_PrintTime( 1, "Cut matching time", Abc_Clock() - clkStart ); +} +Vec_Ptr_t * Gia_ManMatchCutsArray( Vec_Ptr_t * vTtMems, Gia_Man_t * pGia, int nCutSize, int nCutNum, int fVerbose ) +{ + Vec_Ptr_t * vRes = Vec_PtrAlloc( Vec_PtrSize(vTtMems) ); + Gia_Sto_t * p = Gia_ManMatchCutsInt( pGia, nCutSize, nCutNum, fVerbose ); + Vec_Int_t * vLevel, * vTemp; int i, k, c, * pCut; + abctime clkStart = Abc_Clock(); + for ( i = 0; i < Vec_PtrSize(vTtMems); i++ ) + Vec_PtrPush( vRes, Vec_WecAlloc(100) ); + Vec_WecForEachLevel( p->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) + { + Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) if ( pCut[0] > 1 ) + { + Vec_Mem_t * vTtMem; int m; + Vec_PtrForEachEntry( Vec_Mem_t *, vTtMems, vTtMem, m ) + { + word * pTruth = Vec_MemReadEntry( p->vTtMem, Abc_Lit2Var(pCut[pCut[0]+1]) ); + int * pSpot = Vec_MemHashLookup( vTtMem, pTruth ); + if ( *pSpot == -1 ) + continue; + vTemp = Vec_WecPushLevel( (Vec_Wec_t *)Vec_PtrEntry(vRes, m) ); + Vec_IntPush( vTemp, i ); + for ( c = 1; c <= pCut[0]; c++ ) + Vec_IntPush( vTemp, pCut[c] ); + } + } + } + Gia_StoFree( p ); + if ( fVerbose ) { + Vec_Wec_t * vCuts; + printf( "Detected nodes by type: " ); + Vec_PtrForEachEntry( Vec_Wec_t *, vRes, vCuts, i ) + printf( "Type%d = %d ", i, Vec_WecSize(vCuts) ); + Abc_PrintTime( 1, "Cut matching time", Abc_Clock() - clkStart ); + } + return vRes; +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index 92eb2ac89..87f2bb74c 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -5823,6 +5823,349 @@ Gia_Man_t * Gia_ManImplFromBMiter( Gia_Man_t * p, int nPo, int nBInput ) return pNew; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupOdc( Gia_Man_t * p, int iObj, int fVerbose ) +{ + Vec_Int_t * vRoots = Vec_IntAlloc( 1 ); + Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); + Vec_Int_t * vSupp = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj; int i, iRes = 0; + Vec_IntPush( vRoots, iObj ); + Gia_ManStaticFanoutStart( p ); + Gia_ManCollectTfo( p, vRoots, vNodes ); + Gia_ManStaticFanoutStop( p ); + Vec_IntSort(vNodes, 0); + Gia_ManForEachObjVecStart( vNodes, p, pObj, i, 1 ) { + if ( !Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) ) + Vec_IntPushUnique( vSupp, Gia_ObjFaninId0p(p, pObj) ); + if ( !Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) ) + Vec_IntPushUnique( vSupp, Gia_ObjFaninId1p(p, pObj) ); + } + Vec_IntSort(vSupp, 0); + if ( fVerbose ) Vec_IntPrint( vSupp ); + if ( fVerbose ) Vec_IntPrint( vNodes ); + Gia_Man_t * pTemp, * pNew = Gia_ManStart( 100 ); + pNew->pName = Abc_UtilStrsav( "care" ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashStart(pNew); + Gia_ManObj(p, iObj)->Value = 0; + Gia_ManForEachObjVecStart( vNodes, p, pObj, i, 1 ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + Gia_ManObj(p, iObj)->Value = 1; + Gia_ManForEachObjVecStart( vNodes, p, pObj, i, 1 ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + iRes = Gia_ManHashOr( pNew, iRes, Gia_ManHashXor(pNew, pObj->Value, Gia_ObjFanin0Copy(pObj)) ); + Gia_ManAppendCo( pNew, Abc_LitNot(iRes) ); + Vec_IntFree( vRoots ); + Vec_IntFree( vNodes ); + Vec_IntFree( vSupp ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Mark nodes supported by the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManMarkSupported( Gia_Man_t * p, Vec_Int_t * vObjs ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vInner = Vec_IntAlloc( 100 ); + Gia_ManIncrementTravId(p); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + Gia_ObjSetTravIdCurrent(p, pObj); + Vec_IntAppend( vInner, vObjs ); + Gia_ManForEachAnd( p, pObj, i ) { + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + continue; + if ( !Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) || !Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) ) + continue; + Gia_ObjSetTravIdCurrent(p, pObj); + Vec_IntPush( vInner, Gia_ObjId(p, pObj) ); + } + return vInner; +} +Vec_Int_t * Gia_ManMarkPointed( Gia_Man_t * p, Vec_Int_t * vCut, Vec_Int_t * vInner ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vOuts = Vec_IntAlloc( 100 ); + Gia_ManForEachObjVec( vCut, p, pObj, i ) + Gia_ObjSetTravIdPrevious(p, pObj); + Gia_ManForEachAnd( p, pObj, i ) { + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + continue; + if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) ) { + Gia_ObjSetTravIdPrevious(p, Gia_ObjFanin0(pObj)); + Vec_IntPush( vOuts, Gia_ObjFaninId0p(p, pObj) ); + } + if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) ) { + Gia_ObjSetTravIdPrevious(p, Gia_ObjFanin1(pObj)); + Vec_IntPush( vOuts, Gia_ObjFaninId1p(p, pObj) ); + } + } + Gia_ManForEachCo( p, pObj, i ) { + if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) ) { + Gia_ObjSetTravIdPrevious(p, Gia_ObjFanin0(pObj)); + Vec_IntPush( vOuts, Gia_ObjFaninId0p(p, pObj) ); + } + } + Vec_IntSort( vOuts, 0 ); + return vOuts; +} +Gia_Man_t * Gia_ManDupWindow( Gia_Man_t * p, Vec_Int_t * vCut ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vInner = Gia_ManMarkSupported( p, vCut ); + Vec_Int_t * vOuts = Gia_ManMarkPointed( p, vCut, vInner ); + Gia_Man_t * pNew = Gia_ManStart( 100 ); + pNew->pName = Abc_UtilStrsav( "win" ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObjVec( vCut, p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObjVecStart( vInner, p, pObj, i, Vec_IntSize(vCut) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); + printf( "Derived window with %d inputs, %d internal nodes, and %d outputs.\n", Vec_IntSize(vCut), Vec_IntSize(vInner), Vec_IntSize(vOuts) ); + printf( "Outputs: " ); + Vec_IntPrint( vOuts ); + Vec_IntFree( vInner ); + Vec_IntFree( vOuts ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManCollectIntTfos( Gia_Man_t * p, Vec_Int_t * vVarNums ) +{ + Vec_Wec_t * vTfos = Vec_WecStart( Vec_IntSize(vVarNums) ); + Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj; int i, k, Input, iNode; + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vVarNums, Input, i ) + Gia_ObjSetTravIdCurrentId( p, Gia_ManCiIdToId(p, Input) ); + Gia_ManForEachAnd( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0(pObj, i)) || Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId1(pObj, i)) ) + Gia_ObjSetTravIdCurrentId( p, i ), Vec_IntPush( vNodes, i ); + Vec_IntForEachEntry( vVarNums, Input, i ) + { + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrentId( p, Gia_ManCiIdToId(p, Input) ); + Vec_IntForEachEntry( vNodes, iNode, k ) + if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0(Gia_ManObj(p, iNode), iNode)) || Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId1(Gia_ManObj(p, iNode), iNode)) ) + Gia_ObjSetTravIdCurrentId( p, iNode ), Vec_WecPush( vTfos, i, iNode ); + } + Vec_IntFree( vNodes ); + return vTfos; +} +Gia_Man_t * Gia_ManDupCofs( Gia_Man_t * p, Vec_Int_t * vVarNums ) +{ + Vec_Int_t * vOutLits = Vec_IntStartFull( 1 << Vec_IntSize(vVarNums) ); + Vec_Wec_t * vTfos = Gia_ManCollectIntTfos( p, vVarNums ); + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pRoot = Gia_ManCo(p, 0); int i, iLit; + assert( Gia_ManPoNum(p) == 1 && Gia_ManRegNum(p) == 0 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachCiVec( vVarNums, p, pObj, i ) + pObj->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Vec_IntWriteEntry( vOutLits, 0, Gia_ObjFanin0Copy(pRoot) ); + int m, g, x, b = 0; + for ( m = 1; m < Vec_IntSize(vOutLits); m++ ) + { + g = m ^ (m >> 1); x = (b ^ g) == 1 ? 0 : Abc_Base2Log(b ^ g); b = g; + Vec_Int_t * vNode = Vec_WecEntry( vTfos, x ); + Gia_ManPi(p, Vec_IntEntry(vVarNums, x))->Value ^= 1; + Gia_ManForEachObjVec( vNode, p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Vec_IntWriteEntry( vOutLits, g, Gia_ObjFanin0Copy(pRoot) ); + } + assert( Vec_IntFindMin(vOutLits) >= 0 ); + Vec_IntForEachEntry( vOutLits, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + Vec_IntFree( vOutLits ); + Vec_WecFree( vTfos ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManCofPattern( Gia_Man_t * p ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( Gia_ManCoNum(p) ); + Vec_Int_t * vMap = Vec_IntStartFull( 2*Gia_ManObjNum(p) ); + Gia_Obj_t * pObj; int i, iLit, iClass = 0; + assert( Gia_ManCoNum(p) == 1 << Abc_Base2Log(Gia_ManCoNum(p)) ); + Gia_ManForEachPo( p, pObj, i ) + { + iLit = Gia_ObjFaninLit0p(p, pObj); + if ( Vec_IntEntry(vMap, iLit) == -1 ) + Vec_IntWriteEntry( vMap, iLit, iClass++ ); + Vec_IntPush( vRes, Vec_IntEntry(vMap, iLit) ); + } + Vec_IntFree( vMap ); + return vRes; +} +Vec_Int_t * Gia_ManCofClassPattern( Gia_Man_t * p, Vec_Int_t * vVarNums, int fVerbose ) +{ + extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); + Gia_Man_t * pCofs = Gia_ManDupCofs( p, vVarNums ); + Gia_Man_t * pSweep = Cec4_ManSimulateTest3( pCofs, 0, 0 ); + Vec_Int_t * vRes = Gia_ManCofPattern( pSweep ); + assert( Vec_IntSize(vRes) == 1 << Vec_IntSize(vVarNums) ); + Gia_ManStop( pSweep ); + Gia_ManStop( pCofs ); + if ( fVerbose ) + { + int i, Class, nClasses = Vec_IntFindMax(vRes)+1; + printf( "%d -> %d: ", Vec_IntSize(vVarNums), nClasses ); + if ( nClasses <= 36 ) + Vec_IntForEachEntry( vRes, Class, i ) + printf( "%c", (Class < 10 ? (int)'0' : (int)'A'-10) + Class ); + printf( "\n" ); + } + return vRes; +} +Gia_Man_t * Gia_ManDupEncode( Gia_Man_t * p, Vec_Int_t * vVarNums, int fVerbose ) +{ + extern Vec_Int_t * Gia_GenDecoder( Gia_Man_t * p, int * pLits, int nLits ); + Gia_Man_t * pNew, * pTemp; + Vec_Int_t * vCols = Gia_ManCofClassPattern( p, vVarNums, fVerbose ); + Vec_Int_t * vVars = Vec_IntAlloc( 100 ), * vDec; + int i, k, Limit = Vec_IntSize(vCols), Entry; + int nClasses = Vec_IntFindMax(vCols)+1; + int nExtras = Abc_Base2Log(nClasses); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + for ( i = 0; i < Vec_IntSize(vVarNums) + nExtras; i++ ) + Vec_IntPush( vVars, Gia_ManAppendCi(pNew) ); + Gia_ManHashAlloc( pNew ); + vDec = Gia_GenDecoder( pNew, Vec_IntEntryP(vVars, Vec_IntSize(vVarNums)), nExtras ); + Vec_IntForEachEntry( vCols, Entry, i ) + Vec_IntWriteEntry( vCols, i, Vec_IntEntry(vDec, Entry) ); + Vec_IntFree( vDec ); + for ( i = Vec_IntSize(vVarNums) - 1; i >= 0; i--, Limit /= 2 ) + for ( k = 0; k < Limit; k += 2 ) + Vec_IntWriteEntry( vCols, k/2, Gia_ManHashMux(pNew, Vec_IntEntry(vVars, i), Vec_IntEntry(vCols, k+1), Vec_IntEntry(vCols, k)) ); + Gia_ManAppendCo( pNew, Vec_IntEntry(vCols, 0) ); + Vec_IntFree( vCols ); + Vec_IntFree( vVars ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + if ( fVerbose ) + printf( "Generated AIG with %d inputs and %d nodes representing %d PIs with %d columns.\n", + Gia_ManPiNum(pNew), Gia_ManAndNum(pNew), Vec_IntSize(vVarNums), nClasses ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCofClassRand( Gia_Man_t * p, int nVars, int nRands ) +{ + for ( int n = 0; n < nRands; n++ ) + { + Abc_Random(1); + for ( int i = 0; i < n; i++ ) + Abc_Random(0); + Vec_Int_t * vIns = Vec_IntStartNatural( Gia_ManPiNum(p) ); + Vec_IntRandomizeOrder( vIns ); + Vec_IntShrink( vIns, nVars ); + int k, Entry; + printf( "Vars: " ); + Vec_IntForEachEntry( vIns, Entry, k ) + printf( "%d ", Entry ); + printf( " " ); + Vec_Int_t * vTemp = Gia_ManCofClassPattern( p, vIns, 1 ); + Vec_IntFree( vTemp ); + Vec_IntFree( vIns ); + } +} +void Gia_ManCofClassEnum( Gia_Man_t * p, int nVars ) +{ + Vec_Int_t * vIns = Vec_IntAlloc( nVars ); + int m, k, Entry, Count, nMints = 1 << Gia_ManPiNum(p); + for ( m = 0; m < nMints; m++ ) { + for ( Count = k = 0; k < Gia_ManPiNum(p); k++ ) + Count += (m >> k) & 1; + if ( Count != nVars ) + continue; + Vec_IntClear( vIns ); + for ( k = 0; k < Gia_ManPiNum(p); k++ ) + if ( (m >> k) & 1 ) + Vec_IntPush( vIns, k ); + assert( Vec_IntSize(vIns) == Count ); + printf( "Vars: " ); + Vec_IntForEachEntry( vIns, Entry, k ) + printf( "%d ", Entry ); + printf( " " ); + Vec_Int_t * vTemp = Gia_ManCofClassPattern( p, vIns, 1 ); + Vec_IntFree( vTemp ); + } + Vec_IntFree( vIns ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaIf.c b/src/aig/gia/giaIf.c index 7c5e706e8..8b29e79c0 100644 --- a/src/aig/gia/giaIf.c +++ b/src/aig/gia/giaIf.c @@ -1308,12 +1308,25 @@ int Gia_ManFromIfLogicNode( void * pIfMan, Gia_Man_t * pNew, int iObj, Vec_Int_t { if ( Length == 2 ) { - if ( !If_CluCheckExt( NULL, pRes, nLeaves, nLutLeaf, nLutRoot, pLut0, pLut1, &Func0, &Func1 ) ) + if ( ((If_Man_t *)pIfMan)->pPars->fEnableStructN ) { - Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); - Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); - printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj ); - return -1; + if ( !If_CluCheckXXExt( NULL, pRes, nLeaves, nLutLeaf, nLutRoot, pLut0, pLut1, &Func0, &Func1 ) ) + { + Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); + Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); + printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj ); + return -1; + } + } + else + { + if ( !If_CluCheckExt( NULL, pRes, nLeaves, nLutLeaf, nLutRoot, pLut0, pLut1, &Func0, &Func1 ) ) + { + Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); + Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); + printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj ); + return -1; + } } } else @@ -1411,6 +1424,90 @@ int Gia_ManFromIfLogicNode( void * pIfMan, Gia_Man_t * pNew, int iObj, Vec_Int_t return iObjLit3; } +/**Function************************************************************* + + Synopsis [Implements delay-driven decomposition of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFromIfLogicHop( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, Vec_Int_t * vLeaves, Vec_Int_t * vLeavesTemp, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2 ) +{ + word * pTruth = If_CutTruthW(pIfMan, pCutBest); + unsigned char decompArray[92]; + int val; + + assert( pCutBest->nLeaves > pIfMan->pPars->nLutDecSize ); + + unsigned delayProfile = pCutBest->decDelay; + val = acd_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray ); + assert( val == 0 ); + + // convert the LUT-structure into a set of logic nodes in Gia_Man_t + unsigned char bytes_check = decompArray[0]; + assert( bytes_check <= 92 ); + + int byte_p = 2; + unsigned char i, j, k, num_fanins, num_words, num_bytes; + int iObjLits[5]; + int fanin; + word *tt; + + for ( i = 0; i < decompArray[1]; ++i ) + { + num_fanins = decompArray[byte_p++]; + Vec_IntClear( vLeavesTemp ); + for ( j = 0; j < num_fanins; ++j ) + { + fanin = (int)decompArray[byte_p++]; + if ( fanin < If_CutLeaveNum(pCutBest) ) + { + Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, fanin) ); + } + else + { + Vec_IntPush( vLeavesTemp, iObjLits[fanin - If_CutLeaveNum(pCutBest)] ); + } + } + + /* extract the truth table */ + tt = pIfMan->puTempW; + num_words = ( num_fanins <= 6 ) ? 1 : ( 1 << ( num_fanins - 6 ) ); + num_bytes = ( num_fanins <= 3 ) ? 1 : ( 1 << ( Abc_MinInt( (int)num_fanins, 6 ) - 3 ) ); + for ( j = 0; j < num_words; ++j ) + { + tt[j] = 0; + for ( k = 0; k < num_bytes; ++k ) + { + tt[j] |= ( (word)(decompArray[byte_p++]) ) << ( k << 3 ); + } + } + + /* extend truth table if size < 5 */ + assert( num_fanins != 1 ); + if ( num_fanins == 2 ) + { + tt[0] |= tt[0] << 4; + } + while ( num_bytes < 4 ) + { + tt[0] |= tt[0] << ( num_bytes << 3 ); + num_bytes <<= 1; + } + + iObjLits[i] = Gia_ManFromIfLogicCreateLut( pNew, tt, vLeavesTemp, vCover, vMapping, vMapping2 ); + } + + /* check correct read */ + assert( byte_p == decompArray[0] ); + + return iObjLits[i-1]; +} + /**Function************************************************************* Synopsis [Recursively derives the local AIG for the cut.] @@ -1894,7 +1991,7 @@ Gia_Man_t * Gia_ManFromIfLogic( If_Man_t * pIfMan ) if ( !pIfMan->pPars->fUseTtPerm && !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize && !pIfMan->pPars->fEnableCheck75 && !pIfMan->pPars->fEnableCheck75u && !pIfMan->pPars->fEnableCheck07 && !pIfMan->pPars->fUseDsdTune && - !pIfMan->pPars->fUseCofVars && !pIfMan->pPars->fUseAndVars && !pIfMan->pPars->fUseCheck1 && !pIfMan->pPars->fUseCheck2 ) + !pIfMan->pPars->fUseCofVars && !pIfMan->pPars->fUseAndVars && !pIfMan->pPars->fUseCheck1 && !pIfMan->pPars->fUseCheck2 && !pIfMan->pPars->fUserLutDec ) If_CutRotatePins( pIfMan, pCutBest ); // collect leaves of the best cut Vec_IntClear( vLeaves ); @@ -1946,6 +2043,10 @@ Gia_Man_t * Gia_ManFromIfLogic( If_Man_t * pIfMan ) { pIfObj->iCopy = Gia_ManFromIfLogicCofVars( pNew, pIfMan, pCutBest, vLeaves, vLeaves2, vCover, vMapping, vMapping2 ); } + else if ( pIfMan->pPars->fUserLutDec && (int)pCutBest->nLeaves > pIfMan->pPars->nLutDecSize ) + { + pIfObj->iCopy = Gia_ManFromIfLogicHop( pNew, pIfMan, pCutBest, vLeaves, vLeaves2, vCover, vMapping, vMapping2 ); + } else if ( (pIfMan->pPars->fDeriveLuts && pIfMan->pPars->fTruth) || pIfMan->pPars->fUseDsd || pIfMan->pPars->fUseTtPerm || pIfMan->pPars->pFuncCell2 ) { word * pTruth = If_CutTruthW(pIfMan, pCutBest); diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index f2d403ded..8ce1db834 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -2291,6 +2291,85 @@ void Gia_GenSandwich( char ** pFNames, int nFNames, char * pFileName ) printf( "Dumped hierarchical design into file \"%s\"\n", pFileName ); } +/**Function************************************************************* + + Synopsis [Generate hierarchical design.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_GenPutOnTopOne( Gia_Man_t * pNew, Gia_Man_t * p, Vec_Int_t * vLits ) +{ + Gia_Obj_t * pObj; int i; + Gia_ManConst0(p)->Value = 0; + assert( Vec_IntSize(vLits) == Gia_ManCiNum(p) ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Vec_IntEntry(vLits, i); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Vec_IntClear( vLits ); + Gia_ManForEachCo( p, pObj, i ) + Vec_IntPush( vLits, Gia_ObjFanin0Copy(pObj) ); + assert( Vec_IntSize(vLits) == Gia_ManCoNum(p) ); +} +Gia_Man_t * Gia_GenPutOnTop( char ** pFNames, int nFNames ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Man_t * pGias[16] = {0}; + Vec_Int_t * vLits; + int i, iLit, nObjs = 0; + assert( nFNames <= 16 ); + for ( i = 0; i < nFNames; i++ ) + { + FILE * pFile = fopen( pFNames[i], "rb" ); + if ( pFile == NULL ) { + printf( "Cannot open input file \"%s\".\n", pFNames[i] ); + Gia_FreeMany( pGias, nFNames ); + return NULL; + } + fclose( pFile ); + pGias[i] = Gia_AigerRead( pFNames[i], 0, 0, 0 ); + if ( pGias[i] == NULL ) { + printf( "Failed to read an AIG from file \"%s\".\n", pFNames[i] ); + Gia_FreeMany( pGias, nFNames ); + return NULL; + } + nObjs += Gia_ManObjNum(pGias[i]); + } + // start new AIG + pNew = Gia_ManStart( nObjs ); + pNew->pName = Abc_UtilStrsav( "putontop" ); + Gia_ManHashAlloc( pNew ); + // collect inputs + vLits = Vec_IntAlloc( Gia_ManCiNum(pGias[0]) ); + for ( i = 0; i < Gia_ManCiNum(pGias[0]); i++ ) + Vec_IntPush( vLits, Gia_ManAppendCi(pNew) ); + // add parts + for ( i = 0; i < nFNames; i++ ) + { + Gia_Man_t * p = pGias[i]; + while ( Vec_IntSize(vLits) < Gia_ManCiNum(p) ) + Vec_IntPush( vLits, Gia_ManAppendCi(pNew) ); + while ( Vec_IntSize(vLits) > Gia_ManCiNum(p) ) + Gia_ManAppendCo( pNew, Vec_IntPop(vLits) ); + Gia_GenPutOnTopOne( pNew, p, vLits ); + } + // create outputs + Vec_IntForEachEntry( vLits, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + Vec_IntFree( vLits ); + // cleanup + pNew = Gia_ManDupNormalize( pTemp = pNew, 0 ); + Gia_ManStop( pTemp ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaMini.c b/src/aig/gia/giaMini.c index 2fce5d0d4..5f7ca0d57 100644 --- a/src/aig/gia/giaMini.c +++ b/src/aig/gia/giaMini.c @@ -724,6 +724,23 @@ int * Abc_FrameReadMiniLutSwitching( Abc_Frame_t * pAbc ) Vec_IntFree( vSwitching ); return pRes; } +int * Abc_FrameReadMiniLutSwitching2( Abc_Frame_t * pAbc, int fRandPiFactor ) +{ + 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_ManComputeSwitchProbs2( pAbc->pGiaMiniLut, 48, 16, 0, fRandPiFactor ); + 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; diff --git a/src/aig/gia/giaMulFind.c b/src/aig/gia/giaMulFind.c new file mode 100644 index 000000000..0c074094a --- /dev/null +++ b/src/aig/gia/giaMulFind.c @@ -0,0 +1,478 @@ +/**CFile**************************************************************** + + FileName [giaMulFind.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Multiplier detection.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaMulFind.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 [] + +***********************************************************************/ +int Gia_ManMulFindOverlap( Vec_Int_t * p1, Vec_Int_t * p2 ) +{ + int i, k, ObjI, ObjK, Counter = 0; + Vec_IntForEachEntry( p1, ObjI, i ) + Vec_IntForEachEntry( p2, ObjK, k ) + if ( ObjI == ObjK ) + Counter++; + return Counter; +} +void Gia_ManMulFindAssignGroup( Vec_Int_t * vTemp, int iGroup, Vec_Int_t * vMap ) +{ + int k, Obj; + Vec_IntForEachEntry( vTemp, Obj, k ) { + //assert( Vec_IntEntry(vMap, Obj) == -1 || Vec_IntEntry(vMap, Obj) == iGroup ); + Vec_IntWriteEntry(vMap, Obj, iGroup); + } + Vec_IntPush( vTemp, iGroup ); +} +Vec_Int_t * Gia_ManMulFindGroups( Vec_Wec_t * p, int nObjs, int fUseMap ) +{ + Vec_Int_t * vIndex = Vec_IntAlloc( 100 ), * vTemp; + Vec_Int_t * vMap = Vec_IntStartFull( nObjs ); int i, Counter, nGroups = 0; + Vec_Int_t * vUngrouped = Vec_IntStartNatural( Vec_WecSize(p) ); + while ( Vec_IntSize(vUngrouped) ) { + int k, Obj, Item = Vec_IntPop(vUngrouped); + vTemp = Vec_WecEntry(p, Item); + Gia_ManMulFindAssignGroup( vTemp, nGroups, vMap ); + int fChanges = 1; + while ( fChanges ) { + fChanges = 0; + Vec_IntForEachEntry( vUngrouped, Item, i ) { + vTemp = Vec_WecEntry(p, Item); + Counter = 0; + Vec_IntForEachEntry( vTemp, Obj, k ) + if ( Vec_IntEntry(vMap, Obj) >= 0 ) + Counter++; + if ( Counter < 1 ) + continue; + Gia_ManMulFindAssignGroup( vTemp, nGroups, vMap ); + Vec_IntDrop( vUngrouped, i-- ); + fChanges = 1; + } + } + nGroups++; + } + Vec_IntFree( vUngrouped ); + Vec_IntFree( vMap ); + if ( fUseMap ) + Vec_WecForEachLevel( p, vTemp, i ) + Vec_IntPushTwo( vTemp, i, Vec_IntPop(vTemp) ); + Vec_WecSortByLastInt( p, 0 ); + Counter = 0; + Vec_IntPush( vIndex, 0 ); + Vec_WecForEachLevel( p, vTemp, i ) + if ( Vec_IntPop(vTemp) != Counter ) + Vec_IntPush( vIndex, i ), Counter++; + Vec_IntPush( vIndex, Vec_WecSize(p) ); + assert( Vec_WecSize(p) == 0 || Vec_IntSize(vIndex) == nGroups + 1 ); + return vIndex; +} +Vec_Wec_t * Gia_ManMulFindXors( Gia_Man_t * p, Vec_Wec_t * vCuts3, int fVerbose ) +{ + Vec_Wec_t * vXors = Vec_WecAlloc( 10 ); + Vec_Int_t * vIndex = Gia_ManMulFindGroups( vCuts3, Gia_ManObjNum(p), 0 ); + Vec_Int_t * vAll = Vec_IntAlloc( 100 ); + Vec_Bit_t * vSigs[2] = { Vec_BitStart(Gia_ManObjNum(p)), Vec_BitStart(Gia_ManObjNum(p)) }; + Vec_Int_t * vTemp; int g, c, k, Obj, Start; + Vec_IntForEachEntryStop( vIndex, Start, g, Vec_IntSize(vIndex)-1 ) { + Vec_WecForEachLevelStartStop( vCuts3, vTemp, c, Start, Vec_IntEntry(vIndex, g+1) ) + Vec_IntForEachEntry( vTemp, Obj, k ) + if ( !Vec_BitEntry(vSigs[k==0], Obj) ) { + Vec_BitWriteEntry( vSigs[k==0], Obj, 1 ); + Vec_IntPush( vAll, Obj ); + } + Vec_Int_t * vIns = Vec_WecPushLevel( vXors ); + Vec_Int_t * vOuts = Vec_WecPushLevel( vXors ); + Vec_IntForEachEntry( vAll, Obj, k ) { + if ( Vec_BitEntry(vSigs[0], Obj) && !Vec_BitEntry(vSigs[1], Obj) ) + Vec_IntPush( vIns, Obj ); + if ( !Vec_BitEntry(vSigs[0], Obj) && Vec_BitEntry(vSigs[1], Obj) ) + Vec_IntPush( vOuts, Obj ); + Vec_BitWriteEntry( vSigs[0], Obj, 0 ); + Vec_BitWriteEntry( vSigs[1], Obj, 0 ); + } + Vec_IntClear( vAll ); + } + return vXors; +} +Vec_Int_t * Gia_ManFindMulDetectOrder( Vec_Wec_t * vAll, int iStart, int iStop ) +{ + Vec_Int_t * vOrder = Vec_IntAlloc( iStop - iStart ); + Vec_Int_t * vUsed = Vec_IntStart( iStop ), * vTemp; + int i, nMatches = 0, iNext = -1; + Vec_WecForEachLevelStartStop( vAll, vTemp, i, iStart, iStop ) + if ( Vec_IntSize(vTemp) == 2 ) + nMatches++, iNext = i; + if ( nMatches == 1 ) { + while ( Vec_IntSize(vOrder) < iStop - iStart ) { + Vec_IntPush( vOrder, iNext ); + Vec_IntWriteEntry( vUsed, iNext, 1 ); + nMatches = 0; + Vec_WecForEachLevelStartStop( vAll, vTemp, i, iStart, iStop ) { + if ( Vec_IntEntry(vUsed, i) ) + continue; + Vec_Int_t * vLast = Vec_WecEntry(vAll, Vec_IntEntryLast(vOrder)); + if ( Gia_ManMulFindOverlap(vTemp, vLast) == Vec_IntSize(vLast) && Vec_IntSize(vTemp) == Vec_IntSize(vLast) + 2 ) + nMatches++, iNext = i; + } + if ( nMatches != 1 ) + break; + } + } + Vec_IntFree( vUsed ); + if ( Vec_IntSize(vOrder) == 0 ) + Vec_IntFreeP( &vOrder ); + return vOrder; +} +Vec_Wec_t * Gia_ManMulFindAInputs( Gia_Man_t * p, Vec_Wec_t * vXors, int fVerbose ) +{ + Vec_Wec_t * vRes = Vec_WecAlloc( 10 ); + Vec_Wec_t * vAll = Vec_WecAlloc( Vec_WecSize(vXors)/2 ); + Gia_Obj_t * pObj; Vec_Int_t * vIns, * vOuts, * vTemp, * vIndex, * vOrder; int i, k, g, Start, Entry, Entry0, Entry1; + Gia_ManCreateRefs( p ); + Vec_WecForEachLevelDouble( vXors, vIns, vOuts, i ) { + vTemp = Vec_WecPushLevel( vAll ); + Gia_ManForEachObjVec( vIns, p, pObj, k ) + if ( Gia_ObjIsAnd(pObj) + && !Gia_ObjFaninC0(pObj) && Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) >= 4 + && !Gia_ObjFaninC1(pObj) && Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) >= 4 ) + Vec_IntPushTwo( vTemp, Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninId1p(p, pObj) ); + if ( Vec_IntSize(vTemp) == 0 ) + Vec_WecShrink(vAll, Vec_WecSize(vAll)-1); + } + vIndex = Gia_ManMulFindGroups( vAll, Gia_ManObjNum(p), 0 ); + Vec_IntForEachEntryStop( vIndex, Start, g, Vec_IntSize(vIndex)-1 ) { + vOrder = Gia_ManFindMulDetectOrder( vAll, Start, Vec_IntEntry(vIndex, g+1) ); + if ( vOrder == NULL ) + continue; + Vec_Int_t * vIn0 = Vec_WecPushLevel( vRes ); + Vec_Int_t * vIn1 = Vec_WecPushLevel( vRes ); + Vec_Int_t * vOut = Vec_WecPushLevel( vRes ); + vTemp = Vec_WecEntry( vAll, Vec_IntEntry(vOrder, 0) ); + assert( Vec_IntSize(vTemp) == 2 ); + Vec_IntPush( vIn0, Vec_IntEntry(vTemp, 0) ); + Vec_IntPush( vIn1, Vec_IntEntry(vTemp, 1) ); + Vec_IntForEachEntryStart( vOrder, Entry, i, 1 ) { + vTemp = Vec_WecEntry( vAll, Entry ); + Vec_IntForEachEntryDouble( vTemp, Entry0, Entry1, k ) { + if ( Vec_IntFind(vIn0, Entry0) >= 0 && Vec_IntFind(vIn1, Entry1) == -1 ) + Vec_IntPush( vIn1, Entry1 ); + else if ( Vec_IntFind(vIn0, Entry0) == -1 && Vec_IntFind(vIn1, Entry1) >= 0 ) + Vec_IntPush( vIn0, Entry0 ); + else + assert( (Vec_IntFind(vIn0, Entry0) >= 0 && Vec_IntFind(vIn1, Entry1) >= 0) || + (Vec_IntFind(vIn0, Entry1) >= 0 && Vec_IntFind(vIn1, Entry0) >= 0) ); + } + } + Vec_IntReverseOrder( vIn0 ); + Vec_IntReverseOrder( vIn1 ); + vOut = NULL; + } + Vec_IntFree( vIndex ); + Vec_WecFree( vAll ); + return vRes; +} +Vec_Wec_t * Gia_ManMulFindBInputs( Gia_Man_t * p, Vec_Wec_t * vCuts4, Vec_Wec_t * vCuts5, int fVerbose ) +{ + Vec_Wec_t * vRes = Vec_WecAlloc( 10 ); Vec_Int_t * vTemp; int g, c, k, Obj, Start; + Vec_Int_t * vIndex = Gia_ManMulFindGroups( vCuts4, Gia_ManObjNum(p), 0 ); + Vec_IntForEachEntryStop( vIndex, Start, g, Vec_IntSize(vIndex)-1 ) { + Vec_Int_t * vAll = Vec_IntAlloc ( 100 ); + Vec_WecForEachLevelStartStop( vCuts4, vTemp, c, Start, Vec_IntEntry(vIndex, g+1) ) + Vec_IntForEachEntryStart( vTemp, Obj, k, 1 ) + Vec_IntPush( vAll, Obj ); + Vec_IntUniqify( vAll ); + int GroupSize = Vec_IntEntry(vIndex, g+1) - Start; + Vec_Int_t * vCnt = Vec_IntStart( Vec_IntSize(vAll) ); + Vec_WecForEachLevelStartStop( vCuts4, vTemp, c, Start, Vec_IntEntry(vIndex, g+1) ) + Vec_IntForEachEntryStart( vTemp, Obj, k, 1 ) + Vec_IntAddToEntry( vCnt, Vec_IntFind(vAll, Obj), 1 ); + if ( Vec_IntCountEntry(vCnt, 1) != 2 || Vec_IntCountEntry(vCnt, 2) != GroupSize-1 || Vec_IntCountEntry(vCnt, GroupSize) != 2 ) { + printf( "Detection of group %d failed.\n", g ); + continue; + } + Vec_Int_t * vIn1 = Vec_WecPushLevel( vRes ); + Vec_Int_t * vIn2 = Vec_WecPushLevel( vRes ); + Vec_Int_t * vOut = Vec_WecPushLevel( vRes ); + Vec_IntForEachEntry( vAll, Obj, k ) + if ( Vec_IntEntry(vCnt, k) <= 2 ) + Vec_IntPush( vIn1, Obj ); + else + Vec_IntPush( vIn2, Obj ); + Vec_IntSort( vIn1, 0 ); + Vec_IntSort( vIn2, 0 ); + // TODO: check chain in[i] -> in[i+1] + Vec_WecForEachLevel( vCuts5, vTemp, c ) { + Vec_IntShift( vTemp, 1 ); + if ( Gia_ManMulFindOverlap(vTemp, vIn1) >= 2 ) + Vec_IntForEachEntryStart( vTemp, Obj, k, 1 ) + if ( Vec_IntFind(vIn1, Obj) == -1 ) { + Vec_IntPushUnique(vIn2, Obj); + } + Vec_IntShift( vTemp, -1 ); + } + Vec_IntSort( vIn2, 0 ); + vOut = NULL; + } + Vec_IntFree( vIndex ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManMulFindTfo( Gia_Man_t * p, Vec_Int_t * vIn0, Vec_Int_t * vIn1 ) +{ + Vec_Int_t * vTfo = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj; int i, Obj; + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vIn0, Obj, i ) + Gia_ObjSetTravIdCurrentId( p, Obj ); + Vec_IntForEachEntry( vIn1, Obj, i ) + Gia_ObjSetTravIdCurrentId( p, Obj ); + Gia_ManForEachAnd( p, pObj, i ) { + if ( Gia_ObjIsTravIdCurrentId(p, i) ) + continue; + if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0(pObj, i)) && Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId1(pObj, i)) ) + Gia_ObjSetTravIdCurrentId( p, i ), Vec_IntPush( vTfo, i ); + } + return vTfo; +} +Vec_Wrd_t * Gia_ManMulFindSimCone( Gia_Man_t * p, Vec_Int_t * vIn0, Vec_Int_t * vIn1, Vec_Wrd_t * vSim0, Vec_Wrd_t * vSim1, Vec_Int_t * vTfo ) +{ + Vec_Wrd_t * vRes = Vec_WrdAlloc( Vec_IntSize(vTfo) ); + Vec_Wrd_t * vSims = Vec_WrdStart( Gia_ManObjNum(p) ); + Gia_Obj_t * pObj; int i, Obj; + Vec_IntForEachEntry( vIn0, Obj, i ) + Vec_WrdWriteEntry( vSims, Obj, Vec_WrdEntry(vSim0, i) ); + Vec_IntForEachEntry( vIn1, Obj, i ) + Vec_WrdWriteEntry( vSims, Obj, Vec_WrdEntry(vSim1, i) ); + Gia_ManForEachObjVec( vTfo, p, pObj, i ) { + word Sim0 = Vec_WrdEntry(vSims, Gia_ObjFaninId0p(p, pObj) ); + word Sim1 = Vec_WrdEntry(vSims, Gia_ObjFaninId1p(p, pObj) ); + Vec_WrdWriteEntry( vSims, Gia_ObjId(p, pObj), (Gia_ObjFaninC0(pObj) ? ~Sim0 : Sim0) & (Gia_ObjFaninC1(pObj) ? ~Sim1 : Sim1) ); + } + Vec_IntForEachEntry( vTfo, Obj, i ) + Vec_WrdPush( vRes, Vec_WrdEntry(vSims, Obj) ); + Vec_WrdFree( vSims ); + return vRes; +} +int Gia_ManMulFindGetArg( Vec_Wrd_t * vSim, int i, int fSigned ) +{ + int w, Res = 0; word Word = 0; + Vec_WrdForEachEntry( vSim, Word, w ) + if ( (Word >> i) & 1 ) + Res |= (1 << w); + if ( fSigned && ((Word >> i) & 1) ) + Res |= ~0 << Vec_WrdSize(vSim); + return Res; +} +void Gia_ManMulFindSetArg( Vec_Wrd_t * vSim, int i, int iNum ) +{ + int w; word * pWords = Vec_WrdArray(vSim); + for ( w = 0; w < Vec_WrdSize(vSim); w++ ) + if ( (iNum >> w) & 1 ) + pWords[w] |= (word)1 << i; +} +Vec_Wrd_t * Gia_ManMulFindSim( Vec_Wrd_t * vSim0, Vec_Wrd_t * vSim1, int fSigned ) +{ + assert( Vec_WrdSize(vSim0) + Vec_WrdSize(vSim1) <= 30 ); + Vec_Wrd_t * vRes = Vec_WrdStart( Vec_WrdSize(vSim0) + Vec_WrdSize(vSim1) ); + for ( int i = 0; i < 64; i++ ) + { + int a = Gia_ManMulFindGetArg( vSim0, i, fSigned ); + int b = Gia_ManMulFindGetArg( vSim1, i, fSigned ); + Gia_ManMulFindSetArg( vRes, i, a * b ); + } + return vRes; +} +void Gia_ManMulFindOutputs( Gia_Man_t * p, Vec_Wec_t * vTerms, int fVerbose ) +{ + for ( int m = 0; m < Vec_WecSize(vTerms)/3; m++ ) { + Vec_Int_t * vIn0 = Vec_WecEntry(vTerms, 3*m+0); + Vec_Int_t * vIn1 = Vec_WecEntry(vTerms, 3*m+1); + Vec_Int_t * vOut = Vec_WecEntry(vTerms, 3*m+2); + Vec_Wrd_t * vSim0 = Vec_WrdStartRandom( Vec_IntSize(vIn0) ); + Vec_Wrd_t * vSim1 = Vec_WrdStartRandom( Vec_IntSize(vIn1) ); + Vec_Wrd_t * vSimU = Gia_ManMulFindSim( vSim0, vSim1, 0 ); + Vec_Wrd_t * vSimS = Gia_ManMulFindSim( vSim0, vSim1, 1 ); + Vec_Int_t * vTfo = Gia_ManMulFindTfo( p, vIn0, vIn1 ); + Vec_Wrd_t * vSims = Gia_ManMulFindSimCone( p, vIn0, vIn1, vSim0, vSim1, vTfo ); + word Word; int w, iPlace; + assert( Vec_IntSize(vOut) == 0 ); + Vec_WrdForEachEntry( vSimU, Word, w ) { + if ( (iPlace = Vec_WrdFind(vSims, Word)) >= 0 ) + Vec_IntPush( vOut, Abc_Var2Lit(Vec_IntEntry(vTfo, iPlace), 0) ); + else if ( (iPlace = Vec_WrdFind(vSims, ~Word)) >= 0 ) + Vec_IntPush( vOut, Abc_Var2Lit(Vec_IntEntry(vTfo, iPlace), 1) ); + else + break; + } + if ( w == Vec_WrdSize(vSimU) ) + Vec_IntPush(vOut, 0); + else + Vec_IntClear(vOut); + if ( Vec_IntSize(vOut) == 0 ) + { + Vec_IntClear(vOut); + Vec_WrdForEachEntry( vSimS, Word, w ) { + if ( (iPlace = Vec_WrdFind(vSims, Word)) >= 0 ) + Vec_IntPush( vOut, Abc_Var2Lit(Vec_IntEntry(vTfo, iPlace), 0) ); + else if ( (iPlace = Vec_WrdFind(vSims, ~Word)) >= 0 ) + Vec_IntPush( vOut, Abc_Var2Lit(Vec_IntEntry(vTfo, iPlace), 1) ); + else + break; + } + if ( w == Vec_WrdSize(vSimS) ) + Vec_IntPush(vOut, 1); + else + Vec_IntClear(vOut); + } + Vec_WrdFree( vSim0 ); + Vec_WrdFree( vSim1 ); + Vec_WrdFree( vSimU ); + Vec_WrdFree( vSimS ); + Vec_WrdFree( vSims ); + Vec_IntFree( vTfo ); + if ( Vec_IntSize(vOut) ) + continue; + Vec_IntClear(vIn0); + Vec_IntClear(vIn1); + } + Vec_WecRemoveEmpty( vTerms ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Gia_ManMulFindCuts( Gia_Man_t * p, int nCutNum, int fVerbose ) +{ + extern Vec_Mem_t * Dau_CollectNpnFunctions( word * p, int nVars, int fVerbose ); + extern Vec_Ptr_t * Gia_ManMatchCutsArray( Vec_Ptr_t * vTtMems, Gia_Man_t * pGia, int nCutSize, int nCutNum, int fVerbose ); + word pTruths[3] = { ABC_CONST(0x6969696969696969), ABC_CONST(0x35C035C035C035C0), ABC_CONST(0xF335ACC0F335ACC0) }; + Vec_Ptr_t * vTtMems = Vec_PtrAlloc( 3 ); Vec_Mem_t * vTtMem; int i; + for ( i = 0; i < 3; i++ ) + Vec_PtrPush( vTtMems, Dau_CollectNpnFunctions( pTruths+i, i+3, fVerbose ) ); + Vec_Ptr_t * vAll = Gia_ManMatchCutsArray( vTtMems, p, 5, nCutNum, fVerbose ); + Vec_PtrForEachEntry( Vec_Mem_t *, vTtMems, vTtMem, i ) + Vec_MemHashFree( vTtMem ), Vec_MemFree( vTtMem ); + Vec_PtrFree( vTtMems ); + return vAll; +} +Vec_Wec_t * Gia_ManMulFindA( Gia_Man_t * p, Vec_Wec_t * vCuts3, int fVerbose ) +{ + Vec_Wec_t * vXors = Gia_ManMulFindXors( p, vCuts3, fVerbose ); + Vec_Wec_t * vTerms = Gia_ManMulFindAInputs( p, vXors, fVerbose ); + if ( Vec_WecSize(vTerms) ) + Gia_ManMulFindOutputs( p, vTerms, fVerbose ); + Vec_WecFree( vXors ); + return vTerms; +} +Vec_Wec_t * Gia_ManMulFindB( Gia_Man_t * p, Vec_Wec_t * vCuts4, Vec_Wec_t * vCuts5, int fVerbose ) +{ + Vec_Wec_t * vTerms = Vec_WecAlloc( 12 ); + if ( Vec_WecSize(vCuts4) && Vec_WecSize(vCuts5) ) + vTerms = Gia_ManMulFindBInputs( p, vCuts4, vCuts5, fVerbose ); + if ( Vec_WecSize(vTerms) ) + Gia_ManMulFindOutputs( p, vTerms, fVerbose ); + return vTerms; +} +void Gia_ManMulFindPrintSet( Vec_Int_t * vSet, int fLit, int fSkipLast ) +{ + int i, Temp, Limit = Vec_IntSize(vSet) - fSkipLast; + printf( "{" ); + Vec_IntForEachEntryStop( vSet, Temp, i, Limit ) + printf( "%s%d%s", (fLit & Abc_LitIsCompl(Temp)) ? "~":"", fLit ? Abc_Lit2Var(Temp) : Temp, i < Limit-1 ? " ":"" ); + printf( "}" ); +} +void Gia_ManMulFindPrintOne( Vec_Wec_t * vTerms, int m, int fBooth ) +{ + Vec_Int_t * vIn0 = Vec_WecEntry(vTerms, 3*m+0); + Vec_Int_t * vIn1 = Vec_WecEntry(vTerms, 3*m+1); + Vec_Int_t * vOut = Vec_WecEntry(vTerms, 3*m+2); + printf( "%sooth %ssigned : ", fBooth ? "B" : "Non-b", Vec_IntEntryLast(vOut) ? "" : "un" ); + Gia_ManMulFindPrintSet( vIn0, 0, 0 ); + printf( " * " ); + Gia_ManMulFindPrintSet( vIn1, 0, 0 ); + printf( " = " ); + Gia_ManMulFindPrintSet( vOut, 1, 1 ); + printf( "\n" ); +} +void Gia_ManMulFind( Gia_Man_t * p, int nCutNum, int fVerbose ) +{ + Vec_Ptr_t * vAll = Gia_ManMulFindCuts( p, nCutNum, fVerbose ); int m; + Vec_Wec_t * vCuts3 = (Vec_Wec_t *)Vec_PtrEntry(vAll, 0); + Vec_Wec_t * vCuts4 = (Vec_Wec_t *)Vec_PtrEntry(vAll, 1); + Vec_Wec_t * vCuts5 = (Vec_Wec_t *)Vec_PtrEntry(vAll, 2); + Vec_Wec_t * vTermsB = Gia_ManMulFindB( p, vCuts4, vCuts5, fVerbose ); + Vec_Wec_t * vTermsA = Gia_ManMulFindA( p, vCuts3, fVerbose ); + printf( "Detected %d booth and %d non-booth multipliers.\n", Vec_WecSize(vTermsB)/3, Vec_WecSize(vTermsA)/3 ); + for ( m = 0; m < Vec_WecSize(vTermsA)/3; m++ ) + Gia_ManMulFindPrintOne( vTermsA, m, 0 ); + for ( m = 0; m < Vec_WecSize(vTermsB)/3; m++ ) + Gia_ManMulFindPrintOne( vTermsB, m, 1 ); + Vec_WecFree( vTermsB ); + Vec_WecFree( vTermsA ); + Vec_WecFree( vCuts3 ); + Vec_WecFree( vCuts4 ); + Vec_WecFree( vCuts5 ); + Vec_PtrFree( vAll ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/gia/giaNewBdd.h b/src/aig/gia/giaNewBdd.h index 6d75f4d99..5f2b07021 100644 --- a/src/aig/gia/giaNewBdd.h +++ b/src/aig/gia/giaNewBdd.h @@ -21,6 +21,7 @@ #ifndef ABC__aig__gia__giaNewBdd_h #define ABC__aig__gia__giaNewBdd_h +#include #include #include #include @@ -47,6 +48,11 @@ namespace NewBdd { static inline uniq UniqHash(lit Arg0, lit Arg1) { return Arg0 + 4256249 * Arg1; } static inline cac CacHash(lit Arg0, lit Arg1) { return Arg0 + 4256249 * Arg1; } + static inline void fatal_error(const char* message) { + std::cerr << message << std::endl; + std::abort(); + } + class Cache { private: cac nSize; @@ -62,10 +68,10 @@ namespace NewBdd { public: Cache(int nCacheSizeLog, int nCacheMaxLog, int nVerbose): nVerbose(nVerbose) { if(nCacheMaxLog < nCacheSizeLog) - throw std::invalid_argument("nCacheMax must not be smaller than nCacheSize"); + fatal_error("nCacheMax must not be smaller than nCacheSize"); nMax = (cac)1 << nCacheMaxLog; if(!(nMax << 1)) - throw std::length_error("Memout (nCacheMax) in init"); + fatal_error("Memout (nCacheMax) in init"); nSize = (cac)1 << nCacheSizeLog; if(nVerbose) std::cout << "Allocating " << nSize << " cache entries" << std::endl; @@ -242,7 +248,7 @@ namespace NewBdd { inline ref Ref(lit x) const { return vRefs[Lit2Bvar(x)]; } inline double OneCount(lit x) const { if(vOneCounts.empty()) - throw std::logic_error("fCountOnes was not set"); + fatal_error("fCountOnes was not set"); if(LitIsCompl(x)) return std::pow(2.0, nVars) - vOneCounts[Lit2Bvar(x)]; return vOneCounts[Lit2Bvar(x)]; @@ -454,7 +460,7 @@ namespace NewBdd { if(nGbc > 1) fRemoved = Gbc(); if(!Resize() && !fRemoved && (nGbc != 1 || !Gbc())) - throw std::length_error("Memout (node)"); + fatal_error("Memout (node)"); } else break; } @@ -659,29 +665,29 @@ namespace NewBdd { nVerbose = p.nVerbose; // parameter sanity check if(p.nObjsMaxLog < p.nObjsAllocLog) - throw std::invalid_argument("nObjsMax must not be smaller than nObjsAlloc"); + fatal_error("nObjsMax must not be smaller than nObjsAlloc"); if(nVars_ >= (int)VarMax()) - throw std::length_error("Memout (nVars) in init"); + fatal_error("Memout (nVars) in init"); nVars = nVars_; lit nObjsMaxLit = (lit)1 << p.nObjsMaxLog; if(!nObjsMaxLit) - throw std::length_error("Memout (nObjsMax) in init"); + fatal_error("Memout (nObjsMax) in init"); if(nObjsMaxLit > (lit)BvarMax()) nObjsMax = BvarMax(); else nObjsMax = (bvar)nObjsMaxLit; lit nObjsAllocLit = (lit)1 << p.nObjsAllocLog; if(!nObjsAllocLit) - throw std::length_error("Memout (nObjsAlloc) in init"); + fatal_error("Memout (nObjsAlloc) in init"); if(nObjsAllocLit > (lit)BvarMax()) nObjsAlloc = BvarMax(); else nObjsAlloc = (bvar)nObjsAllocLit; if(nObjsAlloc <= (bvar)nVars) - throw std::invalid_argument("nObjsAlloc must be larger than nVars"); + fatal_error("nObjsAlloc must be larger than nVars"); uniq nUniqueSize = (uniq)1 << p.nUniqueSizeLog; if(!nUniqueSize) - throw std::length_error("Memout (nUniqueSize) in init"); + fatal_error("Memout (nUniqueSize) in init"); // allocation if(nVerbose) std::cout << "Allocating " << nObjsAlloc << " nodes and " << nVars << " x " << nUniqueSize << " unique table entries" << std::endl; @@ -703,7 +709,7 @@ namespace NewBdd { } if(p.fCountOnes) { if(nVars > 1023) - throw std::length_error("nVars must be less than 1024 to count ones"); + fatal_error("nVars must be less than 1024 to count ones"); vOneCounts.resize(nObjsAlloc); } // set up cache @@ -780,10 +786,34 @@ namespace NewBdd { for(size_t i = 0; i < vLits.size(); i++) IncRef(vLits[i]); } + void RemoveRefIfUnused() { + if(!nGbc && nReo == BvarMax()) + vRefs.clear(); + } + void TurnOnReo(int nReo_ = 0, std::vector const *vLits = NULL) { + if(nReo_) + nReo = nReo_; + else + nReo = nObjs << 1; + if((lit)nReo > (lit)BvarMax()) + nReo = BvarMax(); + if(vRefs.empty()) { + if(vLits) + SetRef(*vLits); + else + vRefs.resize(nObjsAlloc); + } + } void TurnOffReo() { nReo = BvarMax(); - if(!nGbc) - vRefs.clear(); + } + var GetNumVars() const { + return nVars; + } + void GetOrdering(std::vector &Var2Level_) { + Var2Level_.resize(nVars); + for(var v = 0; v < nVars; v++) + Var2Level_[v] = Var2Level[v]; } bvar CountNodes() { bvar count = 1; diff --git a/src/aig/gia/giaNewTt.h b/src/aig/gia/giaNewTt.h index 494b8636b..e5aaabf37 100644 --- a/src/aig/gia/giaNewTt.h +++ b/src/aig/gia/giaNewTt.h @@ -21,6 +21,7 @@ #ifndef ABC__aig__gia__giaNewTt_h #define ABC__aig__gia__giaNewTt_h +#include #include #include #include @@ -41,6 +42,11 @@ namespace NewTt { static inline ref RefMax() { return std::numeric_limits::max(); } static inline size SizeMax() { return std::numeric_limits::max(); } + static void fatal_error(const char* message) { + std::cerr << message << std::endl; + std::abort(); + } + struct Param { int nObjsAllocLog; int nObjsMaxLog; @@ -48,6 +54,7 @@ namespace NewTt { bool fCountOnes; int nGbc; int nReo; // dummy + std::vector *pVar2Level; // dummy Param() { nObjsAllocLog = 15; nObjsMaxLog = 20; @@ -181,35 +188,35 @@ namespace NewTt { public: Man(int nVars, Param p): nVars(nVars) { if(p.nObjsMaxLog < p.nObjsAllocLog) - throw std::invalid_argument("nObjsMax must not be smaller than nObjsAlloc"); + fatal_error("nObjsMax must not be smaller than nObjsAlloc"); if(nVars >= lww()) nSize = 1ull << (nVars - lww()); else nSize = 1; if(!nSize) - throw std::length_error("Memout (nVars) in init"); + fatal_error("Memout (nVars) in init"); if(!(nSize << p.nObjsMaxLog)) - throw std::length_error("Memout (nObjsMax) in init"); + fatal_error("Memout (nObjsMax) in init"); lit nObjsMaxLit = (lit)1 << p.nObjsMaxLog; if(!nObjsMaxLit) - throw std::length_error("Memout (nObjsMax) in init"); + fatal_error("Memout (nObjsMax) in init"); if(nObjsMaxLit > (lit)BvarMax()) nObjsMax = BvarMax(); else nObjsMax = (bvar)nObjsMaxLit; lit nObjsAllocLit = (lit)1 << p.nObjsAllocLog; if(!nObjsAllocLit) - throw std::length_error("Memout (nObjsAlloc) in init"); + fatal_error("Memout (nObjsAlloc) in init"); if(nObjsAllocLit > (lit)BvarMax()) nObjsAlloc = BvarMax(); else nObjsAlloc = (bvar)nObjsAllocLit; if(nObjsAlloc <= (bvar)nVars) - throw std::invalid_argument("nObjsAlloc must be larger than nVars"); + fatal_error("nObjsAlloc must be larger than nVars"); nTotalSize = nSize << p.nObjsAllocLog; vVals.resize(nTotalSize); if(p.fCountOnes && nVars > 63) - throw std::length_error("nVars must be less than 64 to count ones"); + fatal_error("nVars must be less than 64 to count ones"); nObjs = 1; for(int i = 0; i < 6 && i < nVars; i++) { for(size j = 0; j < nSize; j++) @@ -238,7 +245,7 @@ namespace NewTt { if(nGbc > 1) fRemoved = Gbc(); if(!Resize() && !fRemoved && (nGbc != 1 || !Gbc())) - throw std::length_error("Memout (node)"); + fatal_error("Memout (node)"); } bvar zvar; if(nObjs < nObjsAlloc) @@ -261,10 +268,14 @@ namespace NewTt { for(size_t i = 0; i < vLits.size(); i++) IncRef(vLits[i]); } - void TurnOffReo() { + void RemoveRefIfUnused() { if(!nGbc) vRefs.clear(); } + void TurnOffReo() {} + int GetNumVars() const { + return nVars; + } void PrintNode(lit x) const { bvar a = Lit2Bvar(x); word c = LitIsCompl(x)? one(): 0; diff --git a/src/aig/gia/giaNf.c b/src/aig/gia/giaNf.c index eaaf24e9e..f41d8dd49 100644 --- a/src/aig/gia/giaNf.c +++ b/src/aig/gia/giaNf.c @@ -30,6 +30,12 @@ #include "opt/dau/dau.h" #include "misc/util/utilNam.h" #include "map/scl/sclCon.h" +#include "misc/tim/tim.h" + +#ifdef _MSC_VER +# include +# define __builtin_popcount __popcnt +#endif ABC_NAMESPACE_IMPL_START @@ -82,6 +88,7 @@ struct Nf_Man_t_ { // user data Gia_Man_t * pGia; // derived manager + Tim_Man_t * pManTim; // timing manager Jf_Par_t * pPars; // parameters // matching Vec_Mem_t * vTtMem; // truth tables @@ -223,7 +230,7 @@ void Nf_StoCreateGateAdd( Vec_Mem_t * vTtMem, Vec_Wec_t * vTt2Match, Mio_Cell2_t if ( fPinQuick ) // reduce the number of matches agressively { Vec_IntForEachEntryDouble( vArray, GateId, Entry, i ) - if ( GateId == (int)pCell->Id && Abc_TtBitCount8[Nf_Int2Cfg(Entry).Phase] == Abc_TtBitCount8[Mat.Phase] ) + if ( GateId == (int)pCell->Id && __builtin_popcount( Nf_Int2Cfg(Entry).Phase & 0xff ) == __builtin_popcount( Mat.Phase & 0xff ) ) return; } else // reduce the number of matches less agressively @@ -379,6 +386,7 @@ Nf_Man_t * Nf_StoCreate( Gia_Man_t * pGia, Jf_Par_t * pPars ) p = ABC_CALLOC( Nf_Man_t, 1 ); p->clkStart = Abc_Clock(); p->pGia = pGia; + p->pManTim = (Tim_Man_t *)pGia->pManTime; p->pPars = pPars; p->pNfObjs = ABC_CALLOC( Nf_Obj_t, Gia_ManObjNum(pGia) ); p->iCur = 2; @@ -956,21 +964,42 @@ void Nf_ObjMergeOrder( Nf_Man_t * p, int iObj ) } void Nf_ManComputeCuts( Nf_Man_t * p ) { - Gia_Obj_t * pObj; int i, iFanin; - Gia_ManForEachAnd( p->pGia, pObj, i ) + Gia_Obj_t * pObj; int i, iFanin, arrTime; + float CutFlow = 0, CutFlowAve = 0; int fFirstCi = 0, nCutFlow = 0; + if ( p->pManTim ) + Tim_ManIncrementTravId( p->pManTim ); + Gia_ManForEachObjWithBoxes( p->pGia, pObj, i ) if ( Gia_ObjIsBuf(pObj) ) { iFanin = Gia_ObjFaninId0(pObj, i); Nf_ObjSetCutFlow( p, i, Nf_ObjCutFlow(p, iFanin) ); Nf_ObjSetCutDelay( p, i, Nf_ObjCutDelay(p, iFanin) ); } - else + else if ( Gia_ObjIsAnd(pObj) ) Nf_ObjMergeOrder( p, i ); + else if ( Gia_ObjIsCi(pObj) ) + { + if ( fFirstCi ) { + CutFlowAve = CutFlow / nCutFlow; + CutFlow = 0; + nCutFlow = 0; + fFirstCi = 0; + } + arrTime = Tim_ManGetCiArrival( p->pManTim, Gia_ObjCioId(pObj) ); + Nf_ObjSetCutFlow( p, i, CutFlowAve ); // approximation! + Nf_ObjSetCutDelay( p, i, arrTime ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + iFanin = Gia_ObjFaninId0(pObj, i); + CutFlow += Nf_ObjCutFlow(p, iFanin); + arrTime = Nf_ObjCutDelay(p, iFanin); + Tim_ManSetCoArrival( p->pManTim, Gia_ObjCioId(pObj), arrTime ); + nCutFlow++; + fFirstCi = 1; + } } - - - /**Function************************************************************* Synopsis [] @@ -1382,14 +1411,36 @@ void Nf_ManCutMatch( Nf_Man_t * p, int iObj ) } */ } +static inline Nf_Mat_t * Nf_ObjMatchBest( Nf_Man_t * p, int i, int c ) +{ + Nf_Mat_t * pD = Nf_ObjMatchD(p, i, c); + Nf_Mat_t * pA = Nf_ObjMatchA(p, i, c); + assert( pD->fBest != pA->fBest ); + //assert( Nf_ObjMapRefNum(p, i, c) > 0 ); + if ( pA->fBest ) + return pA; + if ( pD->fBest ) + return pD; + return NULL; +} void Nf_ManComputeMapping( Nf_Man_t * p ) { - Gia_Obj_t * pObj; int i; - Gia_ManForEachAnd( p->pGia, pObj, i ) + Gia_Obj_t * pObj; int i, arrTime; + if ( p->pManTim ) + Tim_ManIncrementTravId( p->pManTim ); + Gia_ManForEachObjWithBoxes( p->pGia, pObj, i ) if ( Gia_ObjIsBuf(pObj) ) Nf_ObjPrepareBuf( p, pObj ); - else + else if ( Gia_ObjIsAnd(pObj) ) Nf_ManCutMatch( p, i ); + else if ( Gia_ObjIsCi(pObj) ) { + arrTime = Tim_ManGetCiArrival( p->pManTim, Gia_ObjCioId(pObj) ); + Nf_ObjPrepareCi( p, i, arrTime ); + } + else if ( Gia_ObjIsCo(pObj) ) { + arrTime = Nf_ObjMatchD( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj) )->D; + Tim_ManSetCoArrival( p->pManTim, Gia_ObjCioId(pObj), arrTime ); + } } @@ -1404,18 +1455,6 @@ void Nf_ManComputeMapping( Nf_Man_t * p ) SeeAlso [] ***********************************************************************/ -static inline Nf_Mat_t * Nf_ObjMatchBest( Nf_Man_t * p, int i, int c ) -{ - Nf_Mat_t * pD = Nf_ObjMatchD(p, i, c); - Nf_Mat_t * pA = Nf_ObjMatchA(p, i, c); - assert( pD->fBest != pA->fBest ); - //assert( Nf_ObjMapRefNum(p, i, c) > 0 ); - if ( pA->fBest ) - return pA; - if ( pD->fBest ) - return pD; - return NULL; -} void Nf_ManSetOutputRequireds( Nf_Man_t * p, int fPropCompl ) { Gia_Obj_t * pObj; @@ -1425,7 +1464,7 @@ void Nf_ManSetOutputRequireds( Nf_Man_t * p, int fPropCompl ) Vec_IntFill( &p->vRequired, nLits, SCL_INFINITY ); // compute delay p->pPars->MapDelay = 0; - Gia_ManForEachCo( p->pGia, pObj, i ) + Gia_ManForEachCoWithBoxes( p->pGia, pObj, i ) { Required = Nf_ObjMatchD( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj) )->D; p->pPars->MapDelay = Abc_MaxInt( p->pPars->MapDelay, Required ); @@ -1445,7 +1484,9 @@ void Nf_ManSetOutputRequireds( Nf_Man_t * p, int fPropCompl ) } //assert( p->pPars->MapDelayTarget == 0 ); // set required times - Gia_ManForEachCo( p->pGia, pObj, i ) + if ( p->pManTim ) + Tim_ManIncrementTravId( p->pManTim ); + Gia_ManForEachCoWithBoxes( p->pGia, pObj, i ) { iObj = Gia_ObjFaninId0p(p->pGia, pObj); fCompl = Gia_ObjFaninC0(pObj); @@ -1470,6 +1511,13 @@ void Nf_ManSetOutputRequireds( Nf_Man_t * p, int fPropCompl ) Nf_ObjUpdateRequired( p, iObj, fCompl, Required ); if ( fPropCompl && iObj > 0 && Nf_ObjMatchBest(p, iObj, fCompl)->fCompl ) Nf_ObjUpdateRequired( p, iObj, !fCompl, Required - p->InvDelayI ); + + if ( p->pManTim == NULL ) + continue; + if ( fPropCompl && iObj > 0 && Nf_ObjMatchBest(p, iObj, fCompl)->fCompl ) + Tim_ManSetCoRequired( p->pManTim, Gia_ObjCioId(pObj), Required - p->InvDelayI ); + else + Tim_ManSetCoRequired( p->pManTim, Gia_ObjCioId(pObj), Required ); //Nf_ObjMapRefInc( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj)); } } @@ -1523,7 +1571,7 @@ int Nf_ManSetMapRefs( Nf_Man_t * p ) float * pFlowRefs = Vec_FltArray( &p->vFlowRefs ); int * pMapRefs = Vec_IntArray( &p->vMapRefs ); int nLits = 2*Gia_ManObjNum(p->pGia); - int i, c, Id, nRefs[2]; + int i, c, Id, nRefs[2], reqTime; Gia_Obj_t * pObj; Nf_Mat_t * pD, * pA, * pM; Nf_Mat_t * pDs[2], * pAs[2], * pMs[2]; @@ -1541,7 +1589,7 @@ int Nf_ManSetMapRefs( Nf_Man_t * p ) p->nInvs = 0; p->pPars->MapAreaF = 0; p->pPars->Area = p->pPars->Edge = 0; - Gia_ManForEachAndReverse( p->pGia, pObj, i ) + Gia_ManForEachObjReverseWithBoxes( p->pGia, pObj, i ) { if ( Gia_ObjIsBuf(pObj) ) { @@ -1558,6 +1606,28 @@ int Nf_ManSetMapRefs( Nf_Man_t * p ) Nf_ObjMapRefInc( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj)); continue; } + if ( Gia_ObjIsCi(pObj) ) + { + if ( Nf_ObjMapRefNum(p, i, 1) ) + { + Nf_ObjMapRefInc( p, i, 0 ); + Nf_ObjUpdateRequired( p, i, 0, Nf_ObjRequired(p, i, 1) - p->InvDelayI ); + p->pPars->MapAreaF += p->InvAreaF; + p->pPars->Edge++; + p->pPars->Area++; + p->nInvs++; + } + reqTime = Abc_MinInt( Nf_ObjRequired(p, i, 0), Nf_ObjRequired(p, i, 1) ); + Tim_ManSetCiRequired( p->pManTim, Gia_ObjCioId(pObj), reqTime ); + continue; + } + if ( Gia_ObjIsCo(pObj) ) + { + reqTime = Tim_ManGetCoRequired( p->pManTim, Gia_ObjCioId(pObj) ); + Nf_ObjUpdateRequired( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj), reqTime ); + Nf_ObjMapRefInc( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj)); + continue; + } // skip if this node is not used for ( c = 0; c < 2; c++ ) nRefs[c] = Nf_ObjMapRefNum(p, i, c); @@ -1660,7 +1730,7 @@ int Nf_ManSetMapRefs( Nf_Man_t * p ) // - required times are propagated correctly // - references are set correctly } - Gia_ManForEachCiId( p->pGia, Id, i ) + Gia_ManForEachCiIdWithBoxes( p->pGia, Id, i ) if ( Nf_ObjMapRefNum(p, Id, 1) ) { Nf_ObjMapRefInc( p, Id, 0 ); @@ -1949,11 +2019,11 @@ void Nf_ManComputeMappingEla( Nf_Man_t * p ) Mio_Cell2_t * pCell; Nf_Mat_t Mb, * pMb = &Mb, * pM; word AreaBef, AreaAft, Gain = 0; - int i, c, iVar, Id, fCompl, k, * pCut; + int i, c, iVar, Id, fCompl, k, * pCut, reqTime; int Required; Nf_ManSetOutputRequireds( p, 1 ); Nf_ManResetMatches( p, p->Iter - p->pPars->nRounds ); - Gia_ManForEachAndReverse( p->pGia, pObj, i ) + Gia_ManForEachObjReverseWithBoxes( p->pGia, pObj, i ) { if ( Gia_ObjIsBuf(pObj) ) { @@ -1962,6 +2032,18 @@ void Nf_ManComputeMappingEla( Nf_Man_t * p ) Nf_ObjUpdateRequired( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj), Nf_ObjRequired(p, i, 0) ); continue; } + if ( Gia_ObjIsCi(pObj) ) + { + reqTime = Abc_MinInt( Nf_ObjRequired(p, i, 0), Nf_ObjRequired(p, i, 1) ); + Tim_ManSetCiRequired( p->pManTim, Gia_ObjCioId(pObj), reqTime ); + continue; + } + if ( Gia_ObjIsCo(pObj) ) + { + reqTime = Tim_ManGetCoRequired( p->pManTim, Gia_ObjCioId(pObj) ); + Nf_ObjUpdateRequired( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj), reqTime ); + continue; + } for ( c = 0; c < 2; c++ ) if ( Nf_ObjMapRefNum(p, i, c) ) { @@ -2012,7 +2094,7 @@ void Nf_ManComputeMappingEla( Nf_Man_t * p ) } } } - Gia_ManForEachCiId( p->pGia, Id, i ) + Gia_ManForEachCiIdWithBoxes( p->pGia, Id, i ) if ( Nf_ObjMapRefNum(p, Id, 1) ) { Required = Nf_ObjRequired( p, i, 1 ); @@ -2360,16 +2442,21 @@ void Nf_ManSetDefaultPars( Jf_Par_t * pPars ) pPars->nCutNumMax = NF_CUT_MAX; pPars->MapDelayTarget = 0; } -Gia_Man_t * Nf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) +Gia_Man_t * Nf_ManPerformMappingInt( Gia_Man_t * pGia, Jf_Par_t * pPars ) { Gia_Man_t * pNew = NULL, * pCls; Nf_Man_t * p; int i, Id; - if ( Gia_ManHasChoices(pGia) ) - pPars->fCoarsen = 0; + if ( Gia_ManHasChoices(pGia) || pGia->pManTime ) + pPars->fCoarsen = 0; pCls = pPars->fCoarsen ? Gia_ManDupMuxes(pGia, pPars->nCoarseLimit) : pGia; p = Nf_StoCreate( pCls, pPars ); if ( p == NULL ) return NULL; +// if ( p->pManTim ) Tim_ManPrint( p->pManTim ); + p->pGia->iFirstNonPiId = p->pManTim ? Tim_ManPiNum(p->pManTim) : Gia_ManCiNum(p->pGia); + p->pGia->iFirstPoId = p->pManTim ? Gia_ManCoNum(p->pGia) - Tim_ManPoNum(p->pManTim) : 0; + p->pGia->iFirstAndObj = 1 + p->pGia->iFirstNonPiId; + p->pGia->iFirstPoObj = Gia_ManObjNum(p->pGia) - Gia_ManCoNum(p->pGia) + p->pGia->iFirstPoId; // if ( pPars->fVeryVerbose ) // Nf_StoPrint( p, pPars->fVeryVerbose ); if ( pPars->fVerbose && pPars->fCoarsen ) @@ -2382,12 +2469,12 @@ Gia_Man_t * Nf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) Nf_ManPrintQuit( p ); if ( Scl_ConIsRunning() ) { - Gia_ManForEachCiId( p->pGia, Id, i ) + Gia_ManForEachCiIdWithBoxes( p->pGia, Id, i ) Nf_ObjPrepareCi( p, Id, Scl_ConGetInArr(i) ); } else { - Gia_ManForEachCiId( p->pGia, Id, i ) + Gia_ManForEachCiIdWithBoxes( p->pGia, Id, i ) // Nf_ObjPrepareCi( p, Id, Scl_Flt2Int(p->pGia->vInArrs ? Abc_MaxFloat(0.0, Vec_FltEntry(p->pGia->vInArrs, i)) : 0.0) ); Nf_ObjPrepareCi( p, Id, Scl_Flt2Int(p->pGia->vInArrs ? Vec_FltEntry(p->pGia->vInArrs, i) : 0.0) ); } @@ -2418,6 +2505,156 @@ Gia_Man_t * Nf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) return pNew; } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCellMappingVerify_rec( Gia_Man_t * p, int iLit ) +{ + int iFanLit, k, Result = 1; + if ( Abc_LitIsCompl(iLit) && Gia_ObjIsTravIdCurrentId(p, Abc_Lit2Var(iLit)) ) + return 1; + if ( !Abc_LitIsCompl(iLit) && Gia_ObjIsTravIdPreviousId(p, Abc_Lit2Var(iLit)) ) + return 1; + if ( Abc_LitIsCompl(iLit) ) + Gia_ObjSetTravIdCurrentId(p, Abc_Lit2Var(iLit)); + else + Gia_ObjSetTravIdPreviousId(p, Abc_Lit2Var(iLit)); + if ( !Gia_ObjIsAndNotBuf(Gia_ManObj(p, Abc_Lit2Var(iLit))) ) + return 1; + if ( !Gia_ObjIsCell(p, iLit) ) + { + Abc_Print( -1, "Gia_ManCellMappingVerify: Internal literal %d does not have mapping.\n", iLit ); + return 0; + } + if ( Gia_ObjIsCellBuf(p, iLit) ) + return Gia_ManCellMappingVerify_rec( p, Gia_ObjFaninLit0p(p, Gia_ManObj(p, Abc_Lit2Var(iLit))) ); + if ( Gia_ObjIsCellInv(p, iLit) ) + return Gia_ManCellMappingVerify_rec( p, Abc_LitNot(iLit) ); + Gia_CellForEachFanin( p, iLit, iFanLit, k ) + if ( Result ) + Result &= Gia_ManCellMappingVerify_rec( p, iFanLit ); + return Result; +} +void Gia_ManCellMappingVerify( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, iLit, Result = 1; + assert( Gia_ManHasCellMapping(p) ); + Gia_ManIncrementTravId( p ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachBuf( p, pObj, i ) + { + if ( !Gia_ObjIsAndNotBuf(Gia_ObjFanin0(pObj)) ) + continue; + iLit = Gia_ObjFaninLit0p(p, pObj); + if ( !Gia_ObjIsCell(p, iLit) ) + { + Abc_Print( -1, "Gia_ManCellMappingVerify: Buffer driver %d does not have mapping.\n", Gia_ObjFaninId0p(p, pObj) ); + Result = 0; + continue; + } + Result &= Gia_ManCellMappingVerify_rec( p, iLit ); + } + Gia_ManForEachCo( p, pObj, i ) + { + if ( !Gia_ObjIsAndNotBuf(Gia_ObjFanin0(pObj)) ) + continue; + iLit = Gia_ObjFaninLit0p(p, pObj); + if ( !Gia_ObjIsCell(p, iLit) ) + { + Abc_Print( -1, "Gia_ManCellMappingVerify: CO driver %d does not have mapping.\n", Gia_ObjFaninId0p(p, pObj) ); + Result = 0; + continue; + } + Result &= Gia_ManCellMappingVerify_rec( p, iLit ); + } +// if ( Result ) +// Abc_Print( 1, "Mapping verified correctly.\n" ); +} + +void Gia_ManTransferCellMapping( Gia_Man_t * p, Gia_Man_t * pGia ) +{ + int iLit, iLitNew, k, iFanLit, iPlace; + if ( !Gia_ManHasCellMapping(pGia) ) + return; + Gia_ManCellMappingVerify( pGia ); + Vec_IntFreeP( &p->vCellMapping ); + p->vCellMapping = Vec_IntAlloc( 4 * Gia_ManObjNum(p) ); + Vec_IntFill( p->vCellMapping, 2 * Gia_ManObjNum(p), 0 ); + Gia_ManForEachCell( pGia, iLit ) + { + Gia_Obj_t * pObj = Gia_ManObj(pGia, Abc_Lit2Var(iLit)); + if ( Gia_ObjValue(pObj) == ~0 ) // handle dangling LUT + continue; + assert( !Abc_LitIsCompl( Gia_ObjValue(pObj) ) ); + iLitNew = Abc_LitNotCond( Gia_ObjValue(pObj), Abc_LitIsCompl(iLit) ); + if ( Gia_ObjIsCellInv(pGia, iLit) ) { + Vec_IntWriteEntry( p->vCellMapping, iLitNew, -1 ); + continue; + } + if ( Gia_ObjIsCellBuf(pGia, iLit) ) { + Vec_IntWriteEntry( p->vCellMapping, iLitNew, -2 ); + continue; + } + Vec_IntWriteEntry( p->vCellMapping, iLitNew, Vec_IntSize(p->vCellMapping) ); + iPlace = Vec_IntSize( p->vCellMapping ); + Vec_IntPush( p->vCellMapping, Gia_ObjCellSize(pGia, iLit) ); + Gia_CellForEachFanin( pGia, iLit, iFanLit, k ) + { + int iFanLitNew = Gia_ObjValue( Gia_ManObj(pGia, Abc_Lit2Var(iFanLit)) ); + if ( iFanLitNew == ~0 ) // handle dangling LUT fanin + Vec_IntAddToEntry( p->vCellMapping, iPlace, -1 ); + else + Vec_IntPush( p->vCellMapping, Abc_LitNotCond(iFanLitNew, Abc_LitIsCompl(iFanLit)) ); + } + Vec_IntPush( p->vCellMapping, Gia_ObjCellId(pGia, iLit) ); + } + Gia_ManCellMappingVerify( p ); +} +Gia_Man_t * Nf_ManPerformMapping( Gia_Man_t * p, Jf_Par_t * pPars ) +{ + Gia_Man_t * pNew; + if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) && Gia_ManIsNormalized(p) ) + { + pNew = Gia_ManDupUnnormalize( p ); + if ( pNew == NULL ) + return NULL; + Gia_ManTransferTiming( pNew, p ); + p = pNew; + // mapping + pNew = Nf_ManPerformMappingInt( p, pPars ); + if ( pNew != p ) + { + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( p ); + } + // normalize + pNew = Gia_ManDupNormalize( p = pNew, 0 ); + Gia_ManTransferCellMapping( pNew, p ); + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( p ); + assert( Gia_ManIsNormalized(pNew) ); + } + else + { + pNew = Nf_ManPerformMappingInt( p, pPars ); + Gia_ManTransferTiming( pNew, p ); + //Gia_ManCellMappingVerify( pNew ); + } + //pNew->MappedDelay = (int)((If_Par_t *)pp)->FinalDelay; + //pNew->MappedArea = (int)((If_Par_t *)pp)->FinalArea; + return pNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaPat2.c b/src/aig/gia/giaPat2.c index 3f928e4dd..b557ac6f8 100644 --- a/src/aig/gia/giaPat2.c +++ b/src/aig/gia/giaPat2.c @@ -184,13 +184,15 @@ static inline int Min_ManAppendCo( Min_Man_t * p, int iLit0 ) ***********************************************************************/ void Min_ManFromGia_rec( Min_Man_t * pNew, Gia_Man_t * p, int iObj ) { - Gia_Obj_t * pObj = Gia_ManObj(p, iObj); + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); int iLit0, iLit1; 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) ); + iLit0 = Gia_ObjFanin0Copy(pObj); + iLit1 = Gia_ObjFanin1Copy(pObj); + pObj->Value = Min_ManAppendObj( pNew, Abc_MinInt(iLit0, iLit1), Abc_MaxInt(iLit0, iLit1) ); } Min_Man_t * Min_ManFromGia( Gia_Man_t * p, Vec_Int_t * vOuts ) { @@ -205,7 +207,7 @@ Min_Man_t * Min_ManFromGia( Gia_Man_t * p, Vec_Int_t * vOuts ) 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) ); + pObj->Value = Min_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } else { @@ -403,8 +405,10 @@ static inline char Min_LitIsImplied2( Min_Man_t * p, int iLit ) 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) ) + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) { Val0 = Min_LitIsImplied1(p, iLit0); + Val1 = Min_LitValL(p, iLit1); + } if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) Val1 = Min_LitIsImplied1(p, iLit1); if ( Min_LitIsXor(iLit, iLit0, iLit1) ) @@ -427,8 +431,10 @@ static inline char Min_LitIsImplied3( Min_Man_t * p, int iLit ) 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) ) + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) { Val0 = Min_LitIsImplied2(p, iLit0); + Val1 = Min_LitValL(p, iLit1); + } if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) Val1 = Min_LitIsImplied2(p, iLit1); if ( Min_LitIsXor(iLit, iLit0, iLit1) ) @@ -451,8 +457,10 @@ static inline char Min_LitIsImplied4( Min_Man_t * p, int iLit ) 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) ) + 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); if ( Min_LitIsXor(iLit, iLit0, iLit1) ) @@ -475,8 +483,10 @@ static inline char Min_LitIsImplied5( Min_Man_t * p, int iLit ) 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) ) + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) { Val0 = Min_LitIsImplied4(p, iLit0); + Val1 = Min_LitValL(p, iLit1); + } if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) Val1 = Min_LitIsImplied4(p, iLit1); if ( Min_LitIsXor(iLit, iLit0, iLit1) ) @@ -1351,6 +1361,74 @@ void Min_ManTest2( Gia_Man_t * p ) Vec_WrdFreeP( &vSimsPi ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_GenerateCexesDumpFile( char * pFileName, Gia_Man_t * p, Vec_Wec_t * vCexes, int fShort ) +{ + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) { + printf( "Cannot open output file name \"%s\".\n", pFileName ); + return; + } + Gia_Obj_t * pObj; + char * pLine = ABC_CALLOC( char, Gia_ManCiNum(p)+3 ); + int i, k, c, iLit, nOuts[2] = {0}, nCexes = Vec_WecSize(vCexes) / Gia_ManCoNum(p); + Gia_ManForEachCo( p, pObj, i ) { + if ( Gia_ObjFaninLit0p(p, Gia_ManCo(p, i)) == 0 ) { + fprintf( pFile, "%d : unsat\n", i ); + nOuts[0]++; + } + else if ( fShort ) { + for ( c = 0; c < nCexes; c++ ) { + Vec_Int_t * vPat = Vec_WecEntry( vCexes, i*nCexes+c ); + fprintf( pFile, "%d :", i ); + if ( Vec_IntSize(vPat) == 0 ) + fprintf( pFile, " not available" ); + else + Vec_IntForEachEntry( vPat, iLit, k ) + fprintf( pFile, " %d", iLit ); + fprintf( pFile, "\n" ); + } + nOuts[1]++; + } + else { + for ( c = 0; c < nCexes; c++ ) { + Vec_Int_t * vPat = Vec_WecEntry( vCexes, i*nCexes+c ); + memset(pLine, '-', Gia_ManCiNum(p) ); + Vec_IntForEachEntry( vPat, iLit, k ) + pLine[Abc_Lit2Var(iLit)-1] = '1' - Abc_LitIsCompl(iLit); + fprintf( pFile, "%d : %s\n", i, pLine ); + } + nOuts[1]++; + } + } + printf( "Information about %d sat, %d unsat, and %d undecided primary outputs was written into file \"%s\".\n", + nOuts[1], nOuts[0], Gia_ManCoNum(p)-nOuts[1]-nOuts[0], pFileName ); + fclose( pFile ); + free( pLine ); +} +void Gia_GenerateCexes( char * pFileName, Gia_Man_t * p, int nMaxTries, int nMinCexes, int fUseSim, int fUseSat, int fShort, int fVerbose, int fVeryVerbose ) +{ + unsigned Start = Abc_Random(1); + Vec_Int_t * vStats[3] = {0}; int i; + Vec_Wec_t * vCexes = Min_ManComputeCexes( p, NULL, nMaxTries, nMinCexes, vStats, fUseSim, fUseSat, fVerbose ); + assert( Vec_WecSize(vCexes) == Gia_ManCoNum(p) * nMinCexes ); + Gia_GenerateCexesDumpFile( pFileName, p, vCexes, fShort ); + for ( i = 0; i < 3; i++ ) + Vec_IntFreeP( &vStats[i] ); + Vec_WecFree( vCexes ); + Start = 0; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaQbf.c b/src/aig/gia/giaQbf.c index 6ccbe4605..1525e7d83 100644 --- a/src/aig/gia/giaQbf.c +++ b/src/aig/gia/giaQbf.c @@ -24,6 +24,7 @@ #include "misc/extra/extra.h" #include "sat/glucose/AbcGlucose.h" #include "misc/util/utilTruth.h" +#include "base/io/ioResub.h" ABC_NAMESPACE_IMPL_START @@ -945,6 +946,301 @@ int Gia_QbfSolve( Gia_Man_t * pGia, int nPars, int nIterLimit, int nConfLimit, i return RetValue; } +/**Function************************************************************* + + Synopsis [Derive the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +sat_solver * Gia_ManGenSolver( Gia_Man_t * p, Vec_Int_t * vInsOuts, int nIns ) +{ + Gia_Obj_t * pObj; int i, nObjs = Gia_ManObjNum(p); + sat_solver * pSat = sat_solver_new(); + sat_solver_setnvars( pSat, 2 * nObjs ); + Gia_ManIncrementTravId(p); + Gia_ManForEachObjVecStart( vInsOuts, p, pObj, i, nIns ) + Gia_ObjSetTravIdCurrent(p, pObj); + Gia_ManForEachAnd( p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj) ) + sat_solver_add_and( pSat, i, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninId1(pObj, i), Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + Gia_ManForEachAnd( p, pObj, i ) + sat_solver_add_and( pSat, nObjs+i, nObjs+Gia_ObjFaninId0(pObj, i), nObjs+Gia_ObjFaninId1(pObj, i), Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + Gia_ManForEachCi( p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj) ) + sat_solver_add_buffer( pSat, nObjs+Gia_ObjId(p, pObj), Gia_ObjId(p, pObj), 0 ); + Gia_ManForEachCo( p, pObj, i ) + if ( Gia_ObjFaninId0p(p, pObj) > 0 ) { + sat_solver_add_buffer( pSat, Gia_ObjId(p, pObj), Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninC0(pObj) ); + sat_solver_add_buffer( pSat, nObjs+Gia_ObjId(p, pObj), nObjs+Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninC0(pObj) ); + sat_solver_add_buffer( pSat, nObjs+Gia_ObjId(p, pObj), Gia_ObjId(p, pObj), 0 ); + } + return pSat; +} +Vec_Int_t * Gia_ManGenCombs( Gia_Man_t * p, Vec_Int_t * vInsOuts, int nIns, int fVerbose ) +{ + int nTimeOut = 600, nConfLimit = 1000000; + int i, iSatVar, Iter, Mask, nSolutions = 0, RetValue = 0; + abctime clkStart = Abc_Clock(); + sat_solver * pSat = Gia_ManGenSolver( p, vInsOuts, nIns ); + Vec_Int_t * vLits = Vec_IntAlloc( 100 ); + Vec_Int_t * vRes = Vec_IntAlloc( 1000 ); + for ( Iter = 0; Iter < 1000000; Iter++ ) + { + int status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, 0, 0, 0 ); + if ( status == l_False ) { RetValue = 1; break; } + if ( status == l_Undef ) { RetValue = 0; break; } + nSolutions++; + // extract SAT assignment + Mask = 0; + Vec_IntClear( vLits ); + Vec_IntForEachEntry( vInsOuts, iSatVar, i ) { + Vec_IntPush( vLits, Abc_Var2Lit(iSatVar, sat_solver_var_value(pSat, iSatVar)) ); + if ( sat_solver_var_value(pSat, iSatVar) ) + Mask |= 1 << (Vec_IntSize(vInsOuts)-1-i); + } + Vec_IntPush( vRes, Mask ); + if ( fVerbose ) + { + printf( "%5d : ", Iter ); + Vec_IntForEachEntry( vInsOuts, iSatVar, i ) { + if ( i == nIns ) printf( " " ); + printf( "%d", (Mask >> (Vec_IntSize(vInsOuts)-1-i)) & 1 ); + } + printf( "\n" ); + } + // add clause + if ( !sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ) ) + { RetValue = 1; break; } + if ( nTimeOut && (Abc_Clock() - clkStart)/CLOCKS_PER_SEC >= nTimeOut ) { RetValue = 0; break; } + } + Vec_IntSort( vRes, 0 ); + Vec_IntFree( vLits ); + sat_solver_delete( pSat ); + if ( RetValue == 0 ) + Vec_IntFreeP( &vRes ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + return vRes; +} +void Gia_ManGenWriteRel( Vec_Int_t * vRes, int nIns, int nOuts, char * pFileName ) +{ + int i, k, Mask, nVars = nIns + nOuts; + Abc_RData_t * p2, * p = Abc_RDataStart( nIns, nOuts, Vec_IntSize(vRes) ); + Vec_IntForEachEntry( vRes, Mask, i ) { + for ( k = 0; k < nVars; k++ ) + if ( (Mask >> (nVars-1-k)) & 1 ) { // the bit is 1 + if ( k < nIns ) + Abc_RDataSetIn( p, k, i ); + else + Abc_RDataSetOut( p, 2*(k-nIns)+1, i ); + } + else { // the bit is zero + if ( k >= nIns ) + Abc_RDataSetOut( p, 2*(k-nIns), i ); + } + } + Abc_WritePla( p, pFileName, 0 ); + p2 = Abc_RData2Rel( p ); + Abc_WritePla( p2, Extra_FileNameGenericAppend(pFileName, "_rel.pla"), 1 ); + Abc_RDataStop( p2 ); + Abc_RDataStop( p ); +} +void Gia_ManGenRel2( Gia_Man_t * pGia, Vec_Int_t * vInsOuts, int nIns, char * pFileName, int fVerbose ) +{ + Vec_Int_t * vRes = Gia_ManGenCombs( pGia, vInsOuts, nIns, fVerbose ); + if ( vRes == NULL ) { + printf( "Enumerating solutions did not succeed.\n" ); + return; + } + Gia_ManGenWriteRel( vRes, nIns, Vec_IntSize(vInsOuts)-nIns, pFileName ); + Vec_IntFree( vRes ); +} + +/**Function************************************************************* + + Synopsis [Derive the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManCollectNodeTfos( Gia_Man_t * p, int * pNodes, int nNodes ) +{ + Vec_Int_t * vTfo = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj; int i; + Gia_ManIncrementTravId( p ); + for ( i = 0; i < nNodes; i++ ) + Gia_ObjSetTravIdCurrentId( p, pNodes[i] ); + Gia_ManForEachAnd( p, pObj, i ) { + if ( Gia_ObjIsTravIdCurrentId(p, i) ) + continue; + if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0(pObj, i)) || Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId1(pObj, i)) ) + Gia_ObjSetTravIdCurrentId( p, i ), Vec_IntPush( vTfo, i ); + } + Gia_ManForEachCo( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0p(p, pObj)) ) + Vec_IntPush( vTfo, Gia_ObjId(p, pObj) ); + return vTfo; +} +Vec_Int_t * Gia_ManCollectNodeTfis( Gia_Man_t * p, Vec_Int_t * vNodes ) +{ + Vec_Int_t * vTfi = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj; int i, Id; + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + if ( Gia_ObjIsCo(pObj) ) + Gia_ObjSetTravIdCurrentId( p, Gia_ObjFaninId0p(p, pObj) ); + Gia_ManForEachAndReverse( p, pObj, i ) { + if ( !Gia_ObjIsTravIdCurrentId(p, i) ) + continue; + Gia_ObjSetTravIdCurrentId(p, Gia_ObjFaninId0(pObj, i)); + Gia_ObjSetTravIdCurrentId(p, Gia_ObjFaninId1(pObj, i)); + } + Gia_ManForEachCiId( p, Id, i ) + if ( Gia_ObjIsTravIdCurrentId(p, Id) ) + Vec_IntPush( vTfi, Id ); + Gia_ManForEachAnd( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrentId(p, i) ) + Vec_IntPush( vTfi, i ); + return vTfi; +} +Gia_Man_t * Gia_ManGenRelMiter( Gia_Man_t * pGia, Vec_Int_t * vInsOuts, int nIns ) +{ + Vec_Int_t * vTfo = Gia_ManCollectNodeTfos( pGia, Vec_IntEntryP(vInsOuts, nIns), Vec_IntSize(vInsOuts)-nIns ); + Vec_Int_t * vTfi = Gia_ManCollectNodeTfis( pGia, vTfo ); + Vec_Int_t * vInLits = Vec_IntAlloc( nIns ); + Vec_Int_t * vOutLits = Vec_IntAlloc( Vec_IntSize(vInsOuts) - nIns ); + Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iLit = 0; + Gia_ManFillValue( pGia ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( pGia->pName ); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachObjVec( vTfi, pGia, pObj, i ) + if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi(pNew); + for ( i = 0; i < Vec_IntSize(vInsOuts)-nIns; i++ ) + Vec_IntPush( vInLits, Gia_ManAppendCi(pNew) ); + Gia_ManForEachObjVec( vTfi, pGia, pObj, i ) + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachObjVec( vTfo, pGia, pObj, i ) + if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + Gia_ManForEachObjVec( vInsOuts, pGia, pObj, i ) + if ( i < nIns ) + Vec_IntPush( vOutLits, pObj->Value ); + else + pObj->Value = Vec_IntEntry( vInLits, i-nIns ); + Gia_ManForEachObjVec( vTfo, pGia, pObj, i ) + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachObjVec( vTfo, pGia, pObj, i ) + if ( Gia_ObjIsCo(pObj) ) + iLit = Gia_ManHashOr( pNew, iLit, Gia_ManHashXor(pNew, Gia_ObjFanin0Copy(pObj), pObj->Value) ); + Gia_ManAppendCo( pNew, iLit ); + Vec_IntForEachEntry( vOutLits, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + Vec_IntFree( vTfo ); + Vec_IntFree( vTfi ); + Vec_IntFree( vInLits ); + Vec_IntFree( vOutLits ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); + return pNew; +} +void Gia_ManPrintRelMinterm( int Mint, int nIns, int nVars ) +{ + for ( int i = 0; i < nVars; i++ ) + printf( "%s%d", i == nIns ? " ":"", (Mint >> (nVars-1-i)) & 1 ); + printf( "\n" ); +} +Vec_Int_t * Gia_ManGenIoCombs( Gia_Man_t * pGia, Vec_Int_t * vInsOuts, int nIns, int fVerbose ) +{ + abctime clkStart = Abc_Clock(); + int nTimeOut = 600, nConfLimit = 1000000; + int i, iNode, iSatVar, Iter, Mask, nSolutions = 0, RetValue = 0; + Gia_Man_t * pMiter = Gia_ManGenRelMiter( pGia, vInsOuts, nIns ); + Cnf_Dat_t * pCnf = (Cnf_Dat_t*)Mf_ManGenerateCnf( pMiter, 8, 0, 0, 0, 0 ); + sat_solver * pSat = (sat_solver*)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + int iLit = Abc_Var2Lit( 1, 0 ); // enumerating the care set (the miter output is 1) + int status = sat_solver_addclause( pSat, &iLit, &iLit + 1 ); assert( status ); + Vec_Int_t * vSatVars = Vec_IntAlloc( Vec_IntSize(vInsOuts) ); + Vec_IntForEachEntry( vInsOuts, iNode, i ) + Vec_IntPush( vSatVars, i < nIns ? 2+i : pCnf->nVars-Vec_IntSize(vInsOuts)+i ); + Vec_Int_t * vLits = Vec_IntAlloc( 100 ); + Vec_Int_t * vRes = Vec_IntAlloc( 1000 ); + for ( Iter = 0; Iter < 1000000; Iter++ ) + { + int status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, 0, 0, 0 ); + if ( status == l_False ) { RetValue = 1; break; } + if ( status == l_Undef ) { RetValue = 0; break; } + nSolutions++; + // extract SAT assignment + Mask = 0; + Vec_IntClear( vLits ); + Vec_IntForEachEntry( vSatVars, iSatVar, i ) { + Vec_IntPush( vLits, Abc_Var2Lit(iSatVar, sat_solver_var_value(pSat, iSatVar)) ); + if ( sat_solver_var_value(pSat, iSatVar) ) + Mask |= 1 << (Vec_IntSize(vInsOuts)-1-i); + } + Vec_IntPush( vRes, Mask ); + if ( 0 ) { + printf( "%5d : ", Iter ); + Gia_ManPrintRelMinterm( Mask, nIns, Vec_IntSize(vSatVars) ); + } + // add clause + if ( !sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ) ) + { RetValue = 1; break; } + if ( nTimeOut && (Abc_Clock() - clkStart)/CLOCKS_PER_SEC >= nTimeOut ) { RetValue = 0; break; } + } + // complement the set of input/output minterms + Vec_Int_t * vBits = Vec_IntStart( 1 << Vec_IntSize(vInsOuts) ); + Vec_IntForEachEntry( vRes, Mask, i ) + Vec_IntWriteEntry( vBits, Mask, 1 ); + Vec_IntClear( vRes ); + Vec_IntForEachEntry( vBits, Mask, i ) + if ( !Mask ) + Vec_IntPush( vRes, i ); + Vec_IntFree( vBits ); + // cleanup + Vec_IntFree( vLits ); + sat_solver_delete( pSat ); + Gia_ManStop( pMiter ); + Cnf_DataFree( pCnf ); + if ( RetValue == 0 ) + Vec_IntFreeP( &vRes ); + return vRes; +} +void Gia_ManGenRel( Gia_Man_t * pGia, Vec_Int_t * vInsOuts, int nIns, char * pFileName, int fVerbose ) +{ + abctime clkStart = Abc_Clock(); + Vec_Int_t * vRes = Gia_ManGenIoCombs( pGia, vInsOuts, nIns, fVerbose ); + if ( vRes == NULL ) { + printf( "Enumerating solutions did not succeed.\n" ); + return; + } + Gia_ManGenWriteRel( vRes, nIns, Vec_IntSize(vInsOuts)-nIns, pFileName ); + if ( fVerbose ) { + printf( "The resulting relation with %d input/output minterms is written into file \"%s\". ", Vec_IntSize(vRes), pFileName ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + if ( 0 ) { + int i, Mint; + Vec_IntForEachEntry( vRes, Mint, i ) + Gia_ManPrintRelMinterm( Mint, nIns, Vec_IntSize(vInsOuts) ); + } + } + Vec_IntFree( vRes ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaResub.c b/src/aig/gia/giaResub.c index 33fd5276d..fc6fd7bf0 100644 --- a/src/aig/gia/giaResub.c +++ b/src/aig/gia/giaResub.c @@ -23,6 +23,7 @@ #include "misc/vec/vecQue.h" #include "misc/vec/vecHsh.h" #include "misc/util/utilTruth.h" +#include "base/io/ioResub.h" ABC_NAMESPACE_IMPL_START @@ -2048,10 +2049,111 @@ Vec_Int_t * Gia_ManDeriveSubset( Gia_Man_t * p, Vec_Wrd_t * vFuncs, Vec_Int_t * return vRes; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManResubFindUsed( Vec_Int_t * vRes, int nDivs, int nNodes, Vec_Int_t * vSupp ) +{ + int i, k, iLit, Counter = 1; + Vec_Int_t * vUsed = Vec_IntStartFull( nDivs ); + Vec_Int_t * vRes2 = Vec_IntDup( vRes ); + Vec_IntWriteEntry( vUsed, 0, 0 ); + assert( Vec_IntSize(vRes) % 2 == 1 ); + Vec_IntSort( vRes2, 0 ); + Vec_IntForEachEntry( vRes2, iLit, k ) + { + int iVar = Abc_Lit2Var(iLit); + if ( iVar > 0 && iVar < nDivs && Vec_IntEntry(vUsed, iVar) == -1 ) { + Vec_IntWriteEntry( vUsed, iVar, Counter++ ); + Vec_IntPush( vSupp, iVar-2 ); + } + } + Vec_IntFree( vRes2 ); + for ( i = nDivs; i < nDivs + nNodes; i++ ) + Vec_IntPush( vUsed, Counter++ ); + return vUsed; +} +Vec_Int_t * Gia_ManResubRemapSolution( Vec_Int_t * vRes, Vec_Int_t * vUsed ) +{ + int i, iLit; + Vec_Int_t * vResNew = Vec_IntAlloc( Vec_IntSize(vRes) ); + Vec_IntForEachEntry( vRes, iLit, i ) + Vec_IntPush( vResNew, Abc_Lit2LitV(Vec_IntArray(vUsed), iLit) ); + return vResNew; +} +void Gia_ManResubRecordSolution( char * pFileName, Vec_Int_t * vRes, int nDivs ) +{ + FILE * pFile = fopen( pFileName, "ab" ); + if ( pFile == NULL ) { + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + return; + } + Vec_Int_t * vSupp = Vec_IntAlloc( 100 ); + Vec_Int_t * vUsed = Gia_ManResubFindUsed( vRes, nDivs, Vec_IntSize(vRes)/2, vSupp ); + Vec_Int_t * vResN = Gia_ManResubRemapSolution( vRes, vUsed ); + + int i, Temp; + fprintf( pFile, "\n.s" ); + Vec_IntForEachEntry( vSupp, Temp, i ) + fprintf( pFile, " %d", Temp ); + fprintf( pFile, "\n.a" ); + Vec_IntForEachEntry( vResN, Temp, i ) + fprintf( pFile, " %d", Temp ); + fprintf( pFile, "\n" ); + fclose( pFile ); + + Vec_IntFree( vUsed ); + Vec_IntFree( vSupp ); + Vec_IntFree( vResN ); +} +Gia_Man_t * Gia_ManResubUnateOne( char * pFileName, int nLimit, int nDivMax, int fWriteSol, int fVerbose ) +{ + Gia_Man_t * pNew = NULL; + Abc_RData_t * p = Abc_ReadPla( pFileName ); + if ( p == NULL ) return NULL; + assert( p->nOuts == 1 ); + Vec_Ptr_t * vDivs = Vec_PtrAlloc( 2+p->nIns ); + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + Vec_PtrPush( vDivs, Vec_WrdEntryP(p->vSimsOut, 0*p->nSimWords) ); + Vec_PtrPush( vDivs, Vec_WrdEntryP(p->vSimsOut, 1*p->nSimWords) ); + int i, k, ArraySize, * pArray; + for ( i = 0; i < p->nIns; i++ ) + Vec_PtrPush( vDivs, Vec_WrdEntryP(p->vSimsIn, i*p->nSimWords) ); + Abc_ResubPrepareManager( p->nSimWords ); + if ( fVerbose ) + printf( "The problem has %d divisors and %d outputs.\n", p->nIns, p->nOuts ); + ArraySize = Abc_ResubComputeFunction( (void **)Vec_PtrArray(vDivs), Vec_PtrSize(vDivs), p->nSimWords, nLimit, nDivMax, 0, 0, 1, fVerbose, &pArray ); + for ( k = 0; k < ArraySize; k++ ) + Vec_IntPush( vRes, pArray[k] ); + if ( ArraySize ) { + //Vec_IntPrint( vRes ); + Vec_Wec_t * vGates = Vec_WecStart(1); + Vec_IntAppend( Vec_WecEntry(vGates, 0), vRes ); + pNew = Gia_ManConstructFromGates( vGates, Vec_PtrSize(vDivs) ); + Vec_WecFree( vGates ); + if ( fVerbose ) + printf( "The solution has %d inputs and %d nodes.\n", Gia_ManCiNum(pNew), Gia_ManAndNum(pNew) ); + } + if ( fWriteSol && ArraySize ) + Gia_ManResubRecordSolution( pFileName, vRes, Vec_PtrSize(vDivs) ); + Abc_ResubPrepareManager( 0 ); + Vec_IntFree( vRes ); + Vec_PtrFree( vDivs ); + Abc_RDataStop( p ); + return pNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// - ABC_NAMESPACE_IMPL_END diff --git a/src/aig/gia/giaResub6.c b/src/aig/gia/giaResub6.c index 3203a6996..85d5bb094 100644 --- a/src/aig/gia/giaResub6.c +++ b/src/aig/gia/giaResub6.c @@ -20,6 +20,7 @@ #include "gia.h" #include "misc/util/utilTruth.h" +#include "base/io/ioResub.h" ABC_NAMESPACE_IMPL_START @@ -45,6 +46,7 @@ struct Res6_Man_t_ Vec_Int_t vSol; // current solution Vec_Int_t vSolBest; // best solution Vec_Int_t vTempBest;// current best solution + Vec_Int_t vSupp; // support }; extern void Dau_DsdPrintFromTruth2( word * pTruth, int nVarsInit ); @@ -95,11 +97,47 @@ static inline void Res6_ManStop( Res6_Man_t * p ) Vec_IntErase( &p->vSol ); Vec_IntErase( &p->vSolBest ); Vec_IntErase( &p->vTempBest ); + Vec_IntErase( &p->vSupp ); ABC_FREE( p->ppLits ); ABC_FREE( p->ppSets ); ABC_FREE( p ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Res6_Man_t * Res6_ManReadPla( char * pFileName ) +{ + int i, n; + Abc_RData_t * pData = Abc_ReadPla( pFileName ); assert( pData->nOuts == 1 ); + Res6_Man_t * p = pData ? Res6_ManStart( 0, pData->nIns, pData->nOuts, pData->nPats ) : NULL; + if ( p == NULL ) return NULL; + assert( pData->nSimWords == p->nWords ); + for ( i = 1; i < p->nDivs; i++ ) + for ( n = 0; n < 2; n++ ) + Abc_TtCopy( p->ppLits[2*i+n], Vec_WrdEntryP(pData->vSimsIn, (i-1)*pData->nSimWords), pData->nSimWords, n ); + for ( i = 0; i < (1 << p->nOuts); i++ ) + Abc_TtCopy( p->ppSets[i], Vec_WrdEntryP(pData->vSimsOut, i*pData->nSimWords), pData->nSimWords, 0 ); + if ( pData->vDivs ) + Vec_IntForEachEntry( pData->vDivs, n, i ) + Vec_IntPush( &p->vSupp, 1+n ); + if ( pData->vSol ) { + Vec_IntForEachEntry( pData->vSol, n, i ) + Vec_IntPush( &p->vSol, n ); + Vec_IntPush( &p->vSol, Vec_IntEntryLast(&p->vSol) ); + } + Abc_RDataStop( pData ); + return p; +} + /**Function************************************************************* Synopsis [] @@ -197,7 +235,7 @@ void Res6_ManWrite( char * pFileName, Res6_Man_t * p ) void Res6_ManPrintProblem( Res6_Man_t * p, int fVerbose ) { int i, nInputs = (p->nIns && p->nIns < 6) ? p->nIns : 6; - printf( "Problem: In = %d Div = %d Out = %d Pattern = %d\n", p->nIns, p->nDivs - p->nIns - 1, p->nOuts, p->nPats ); + printf( "Problem: In = %d Div = %d Out = %d Pat = %d\n", p->nIns, p->nDivs - p->nIns - 1, p->nOuts, p->nPats ); if ( !fVerbose ) return; printf( "%02d : %s\n", 0, "const0" ); @@ -426,6 +464,7 @@ void Res6_ManResubCheck( char * pFileNameRes, char * pFileNameSol, int fVerbose { Res6_Man_t * p = Res6_ManRead( pFileNameRes ); Vec_Int_t * vSol = Res6_ManReadSol( FileNameSol ); + //Vec_IntPrint( vSol ); if ( p == NULL || vSol == NULL ) return; if ( fVerbose ) @@ -440,6 +479,80 @@ void Res6_ManResubCheck( char * pFileNameRes, char * pFileNameSol, int fVerbose } } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res6_FindBestEvalPla( Res6_Man_t * p, Vec_Int_t * vSol ) +{ + int i, n, iObj, iLit0, iLit1, iOffset = 2*(1+Vec_IntSize(&p->vSupp)); + assert( Vec_IntSize(vSol) % 2 == 0 ); + Vec_IntForEachEntry( &p->vSupp, iObj, i ) + for ( n = 0; n < 2; n++ ) + Abc_TtCopy( p->ppLits[2*(1+i)+n], p->ppLits[2*iObj+n], p->nWords, 0 ); + Vec_IntForEachEntryDouble( vSol, iLit0, iLit1, i ) + { + if ( iLit0 > iLit1 ) + { + Abc_TtXor( p->ppLits[iOffset+i+0], p->ppLits[iLit0], p->ppLits[iLit1], p->nWords, 0 ); + Abc_TtXor( p->ppLits[iOffset+i+1], p->ppLits[iLit0], p->ppLits[iLit1], p->nWords, 1 ); + } + else + { + Abc_TtAnd( p->ppLits[iOffset+i+0], p->ppLits[iLit0], p->ppLits[iLit1], p->nWords, 0 ); + Abc_TtOr ( p->ppLits[iOffset+i+1], p->ppLits[iLit0^1], p->ppLits[iLit1^1], p->nWords ); + } + } + return Res6_FindGetCost( p, Vec_IntEntryLast(vSol) ); +} +void Res6_ManResubVerifyPla( Res6_Man_t * p, Vec_Int_t * vSol ) +{ + int Cost = Res6_FindBestEvalPla( p, vSol ); + if ( Cost == 0 ) + printf( "Verification successful.\n" ); + else + printf( "Verification FAILED with %d errors on %d patterns.\n", Cost, p->nPats ); +} +void Res6_PrintSolutionPla( Vec_Int_t * vSol, int nSuppSize, int nDivs ) +{ + int iNode, nNodes = Vec_IntSize(vSol)/2-1; + assert( Vec_IntSize(vSol) % 2 == 0 ); + printf( "Solution: In = %d Div = %d Node = %d Out = %d\n", nSuppSize, nDivs-1, nNodes, 1 ); + for ( iNode = 0; iNode <= nNodes; iNode++ ) + { + int * pLits = Vec_IntEntryP( vSol, 2*iNode ); + printf( "x%-2d = ", 1+nSuppSize+iNode ); + Res6_LitPrint( pLits[0], 1+nSuppSize ); + if ( pLits[0] != pLits[1] ) + { + printf( " %c ", pLits[0] < pLits[1] ? '&' : '^' ); + Res6_LitPrint( pLits[1], 1+nSuppSize ); + } + printf( "\n" ); + } +} +void Res6_ManResubCheckPla( char * pFileName, int fVerbose ) +{ + Res6_Man_t * p = Res6_ManReadPla( pFileName ); + if ( p == NULL ) return; + //Vec_IntPrint( &p->vSupp ); + //Vec_IntPrint( &p->vSol ); + if ( fVerbose ) + Res6_ManPrintProblem( p, 0 ); + if ( fVerbose ) + Res6_PrintSolutionPla( &p->vSol, Vec_IntSize(&p->vSupp), p->nDivs ); + //if ( fVerbose ) + // Res6_PrintSuppSims( vSol, p->ppLits, p->nWords, p->nDivs ); + Res6_ManResubVerifyPla( p, &p->vSol ); + Res6_ManStop( p ); +} //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaShow.c b/src/aig/gia/giaShow.c index c3a211849..6a25cfd89 100644 --- a/src/aig/gia/giaShow.c +++ b/src/aig/gia/giaShow.c @@ -1129,7 +1129,7 @@ void Gia_ManShow( Gia_Man_t * pMan, Vec_Int_t * vBold, int fAdders, int fFadds, char FileNameDot[200]; FILE * pFile; Vec_Int_t * vXors = NULL, * vAdds = fAdders ? Ree_ManComputeCuts( pMan, &vXors, 0 ) : NULL; - sprintf( FileNameDot, "%s", Extra_FileNameGenericAppend(pMan->pName, ".dot") ); + sprintf( FileNameDot, "%s", Extra_FileNameGenericAppend(pMan->pName ? pMan->pName : (char *)"unknown", ".dot") ); // check that the file can be opened if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) { diff --git a/src/aig/gia/giaSimBase.c b/src/aig/gia/giaSimBase.c index 97335d378..87614c490 100644 --- a/src/aig/gia/giaSimBase.c +++ b/src/aig/gia/giaSimBase.c @@ -3625,7 +3625,7 @@ Gia_Man_t * Gia_ManChangeTest3( Gia_Man_t * p ) { extern void Exa6_WriteFile2( char * pFileName, int nVars, int nDivs, int nOuts, Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut ); extern void Exa_ManExactPrint( Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut, int nDivs, int nOuts ); - extern Mini_Aig_t * Exa_ManExactSynthesis6Int( Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut, int nVars, int nDivs, int nOuts, int nNodes, int fOnlyAnd, int fVerbose ); + extern Mini_Aig_t * Exa_ManExactSynthesis6Int( Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut, int nVars, int nDivs, int nOuts, int nNodes, int fOnlyAnd, int fVerbose, char * pFileName ); extern Gia_Man_t * Gia_ManDupMini( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vDivs, Vec_Int_t * vOuts, Mini_Aig_t * pMini ); Gia_Man_t * pNew = NULL; @@ -3639,7 +3639,7 @@ Gia_Man_t * Gia_ManChangeTest3( Gia_Man_t * p ) Gia_ManRelCompute( p, vIns, vDivs, vOuts, &vSimsDiv, &vSimsOut ); Exa_ManExactPrint( vSimsDiv, vSimsOut, 1 + Vec_IntSize(vIns) + Vec_IntSize(vDivs), Vec_IntSize(vOuts) ); //Exa6_WriteFile2( "mul44_i%d_n%d_t%d_s%d.rel", Vec_IntSize(vIns), Vec_IntSize(vDivs), Vec_IntSize(vOuts), nNodes ); - pMini = Exa_ManExactSynthesis6Int( vSimsDiv, vSimsOut, Vec_IntSize(vIns), Vec_IntSize(vDivs), Vec_IntSize(vOuts), nNodes, 1, 1 ); + pMini = Exa_ManExactSynthesis6Int( vSimsDiv, vSimsOut, Vec_IntSize(vIns), Vec_IntSize(vDivs), Vec_IntSize(vOuts), nNodes, 1, 1, NULL ); if ( pMini ) { pNew = Gia_ManDupMini( p, vIns, vDivs, vOuts, pMini ); diff --git a/src/aig/gia/giaStoch.c b/src/aig/gia/giaStoch.c index f7515e835..68e23019e 100644 --- a/src/aig/gia/giaStoch.c +++ b/src/aig/gia/giaStoch.c @@ -1,6 +1,6 @@ /**CFile**************************************************************** - FileName [giaDeep.c] + FileName [giaStoch.c] SystemName [ABC: Logic synthesis and verification system.] @@ -14,7 +14,7 @@ Date [Ver. 1.0. Started - June 20, 2005.] - Revision [$Id: giaDeep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + Revision [$Id: giaStoch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ @@ -22,23 +22,13 @@ #include "base/main/main.h" #include "base/cmd/cmd.h" -#ifdef _MSC_VER +#ifdef WIN32 +#include #define unlink _unlink #else #include #endif -#ifdef ABC_USE_PTHREADS - -#ifdef _WIN32 -#include "../lib/pthread.h" -#else -#include -#endif - -#endif - - ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// @@ -108,7 +98,7 @@ void Gia_StochProcessArray( Vec_Ptr_t * vGias, char * pScript, int TimeSecs, int /**Function************************************************************* - Synopsis [Processing on a many cores.] + Synopsis [Processing on many cores.] Description [] @@ -117,27 +107,6 @@ void Gia_StochProcessArray( Vec_Ptr_t * vGias, char * pScript, int TimeSecs, int SeeAlso [] ***********************************************************************/ -#ifndef ABC_USE_PTHREADS - -void Gia_StochProcess( Vec_Ptr_t * vGias, char * pScript, int nProcs, int TimeSecs, int fVerbose ) -{ - Gia_StochProcessArray( vGias, pScript, TimeSecs, fVerbose ); -} - -#else // pthreads are used - - -#define PAR_THR_MAX 100 -typedef struct Gia_StochThData_t_ -{ - Vec_Ptr_t * vGias; - char * pScript; - int Index; - int Rand; - int nTimeOut; - int fWorking; -} Gia_StochThData_t; - Gia_Man_t * Gia_StochProcessOne( Gia_Man_t * p, char * pScript, int Rand, int TimeSecs ) { Gia_Man_t * pNew; @@ -166,87 +135,68 @@ Gia_Man_t * Gia_StochProcessOne( Gia_Man_t * p, char * pScript, int Rand, int Ti return Gia_ManDup(p); } -void * Gia_StochWorkerThread( void * pArg ) +/**Function************************************************************* + + Synopsis [Generic concurrent processing.] + + Description [User-defined problem-specific data and the way to process it.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +typedef struct StochSynData_t_ { - Gia_StochThData_t * pThData = (Gia_StochThData_t *)pArg; - volatile int * pPlace = &pThData->fWorking; - Gia_Man_t * pGia, * pNew; - while ( 1 ) - { - while ( *pPlace == 0 ); - assert( pThData->fWorking ); - if ( pThData->Index == -1 ) - { - pthread_exit( NULL ); - assert( 0 ); - return NULL; - } - pGia = (Gia_Man_t *)Vec_PtrEntry( pThData->vGias, pThData->Index ); - pNew = Gia_StochProcessOne( pGia, pThData->pScript, pThData->Rand, pThData->nTimeOut ); - Gia_ManStop( pGia ); - Vec_PtrWriteEntry( pThData->vGias, pThData->Index, pNew ); - pThData->fWorking = 0; - } - assert( 0 ); - return NULL; + Gia_Man_t * pIn; + Gia_Man_t * pOut; + char * pScript; + int Rand; + int TimeOut; +} StochSynData_t; + +int Gia_StochProcess1( void * p ) +{ + StochSynData_t * pData = (StochSynData_t *)p; + assert( pData->pIn != NULL ); + assert( pData->pOut == NULL ); + pData->pOut = Gia_StochProcessOne( pData->pIn, pData->pScript, pData->Rand, pData->TimeOut ); + return 1; } void Gia_StochProcess( Vec_Ptr_t * vGias, char * pScript, int nProcs, int TimeSecs, int fVerbose ) { - Gia_StochThData_t ThData[PAR_THR_MAX]; - pthread_t WorkerThread[PAR_THR_MAX]; - int i, k, status; - if ( fVerbose ) - printf( "Running concurrent synthesis with %d processes.\n", nProcs ); - fflush( stdout ); - if ( nProcs < 2 ) - return Gia_StochProcessArray( vGias, pScript, TimeSecs, fVerbose ); - // subtract manager thread - nProcs--; - assert( nProcs >= 1 && nProcs <= PAR_THR_MAX ); - // start threads + if ( nProcs <= 2 ) { + if ( fVerbose ) + printf( "Running non-concurrent synthesis.\n" ), fflush(stdout); + Gia_StochProcessArray( vGias, pScript, TimeSecs, fVerbose ); + return; + } + StochSynData_t * pData = ABC_CALLOC( StochSynData_t, Vec_PtrSize(vGias) ); + Vec_Ptr_t * vData = Vec_PtrAlloc( Vec_PtrSize(vGias) ); + Gia_Man_t * pGia; int i; Abc_Random(1); - for ( i = 0; i < nProcs; i++ ) - { - ThData[i].vGias = vGias; - ThData[i].pScript = pScript; - ThData[i].Index = -1; - ThData[i].Rand = Abc_Random(0) % 0x1000000; - ThData[i].nTimeOut = TimeSecs; - ThData[i].fWorking = 0; - status = pthread_create( WorkerThread + i, NULL, Gia_StochWorkerThread, (void *)(ThData + i) ); assert( status == 0 ); + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) { + pData[i].pIn = pGia; + pData[i].pOut = NULL; + pData[i].pScript = pScript; + pData[i].Rand = Abc_Random(0) % 0x1000000; + pData[i].TimeOut = TimeSecs; + Vec_PtrPush( vData, pData+i ); } - // look at the threads - for ( k = 0; k < Vec_PtrSize(vGias); k++ ) - { - for ( i = 0; i < nProcs; i++ ) - { - if ( ThData[i].fWorking ) - continue; - ThData[i].Index = k; - ThData[i].fWorking = 1; - break; - } - if ( i == nProcs ) - k--; - } - // wait till threads finish - for ( i = 0; i < nProcs; i++ ) - if ( ThData[i].fWorking ) - i = -1; - // stop threads - for ( i = 0; i < nProcs; i++ ) - { - assert( !ThData[i].fWorking ); - // stop - ThData[i].Index = -1; - ThData[i].fWorking = 1; + if ( fVerbose ) + printf( "Running concurrent synthesis with %d processes.\n", nProcs ), fflush(stdout); + Util_ProcessThreads( Gia_StochProcess1, vData, nProcs, TimeSecs, fVerbose ); + // replace old AIGs by new AIGs + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) { + Gia_ManStop( pGia ); + Vec_PtrWriteEntry( vGias, i, pData[i].pOut ); } + Vec_PtrFree( vData ); + ABC_FREE( pData ); } -#endif // pthreads are used - - /**Function************************************************************* Synopsis [] diff --git a/src/aig/gia/giaSupps.c b/src/aig/gia/giaSupps.c index 894e26b7d..558411eda 100644 --- a/src/aig/gia/giaSupps.c +++ b/src/aig/gia/giaSupps.c @@ -20,6 +20,7 @@ #include "aig/gia/gia.h" #include "base/main/mainInt.h" +#include "base/io/ioResub.h" #include "misc/util/utilTruth.h" #include "misc/extra/extra.h" #include "misc/vec/vecHsh.h" @@ -185,6 +186,50 @@ Supp_Man_t * Supp_ManCreate( Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * Supp_ManInit( p ); return p; } +int Supp_DeriveLines2( Supp_Man_t * p ) +{ + assert( Vec_WrdSize(p->vSims) % p->nWords == 0 ); + int n, nDivWords = Abc_Bit6WordNum( Vec_WrdSize(p->vSims) / p->nWords ); + for ( n = 0; n < 2; n++ ) + { + p->vDivs[n] = Vec_WrdStart( 64*p->nWords*nDivWords ); + p->vPats[n] = Vec_WrdStart( 64*p->nWords*nDivWords ); + Abc_TtCopy( Vec_WrdArray(p->vDivs[n]), Vec_WrdArray(p->vSims), Vec_WrdSize(p->vSims), !n ); + Extra_BitMatrixTransposeP( p->vDivs[n], p->nWords, p->vPats[n], nDivWords ); + } + return nDivWords; +} +Supp_Man_t * Supp_ManCreate2( Vec_Wrd_t * vIsfs, Vec_Wrd_t * vSims, Vec_Int_t * vWeights, int nWords, int nIters, int nRounds ) +{ + Supp_Man_t * p = ABC_CALLOC( Supp_Man_t, 1 ); + assert( Vec_WrdSize(vSims)%nWords == 0 ); + p->nIters = nIters; + p->nRounds = nRounds; + p->nWords = nWords; + p->vIsfs = vIsfs; + p->vCands = Vec_IntStartNatural( Vec_WrdSize(vSims)/nWords ); + p->vWeights = NULL; + p->vSims = vSims; + p->vSimsC = NULL; + p->pGia = NULL; + // computed data + p->nDivWords = Supp_DeriveLines2( 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; @@ -214,6 +259,8 @@ void Supp_ManDelete( Supp_Man_t * p ) Vec_IntFreeP( &p->vTemp ); Vec_IntFreeP( &p->vTempSets ); Vec_IntFreeP( &p->vTempPairs ); + if ( p->vSims == NULL ) + Vec_IntFreeP( &p->vCands ); ABC_FREE( p ); } int Supp_ManMemory( Supp_Man_t * p ) @@ -771,6 +818,53 @@ void Supp_DeriveDumpSol( Vec_Int_t * vSet, Vec_Int_t * vRes, int nDivs ) printf( "Dumped solution info file \"%s\".\n", Buffer ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Supp_DeriveDumpProb2( Vec_Wrd_t * vIsfs, Vec_Wrd_t * vDivs, int nWords, Vec_Int_t * vSupp, Vec_Int_t * vRes ) +{ + char Buffer[100]; int i, k, Temp, nDivs = Vec_WrdSize(vDivs)/nWords; + int RetValue = sprintf( Buffer, "%02d.pla", s_Counter ); + FILE * pFile = fopen( Buffer, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open output file.\n" ); +// fprintf( pFile, "resyn %d %d %d %d\n", 0, nDivs, 1, 64*nWords ); + fprintf( pFile, ".i %d\n", nDivs ); + fprintf( pFile, ".o %d\n", 1 ); + fprintf( pFile, ".p %d\n", 64*nWords ); + for ( i = 0; i < 64*nWords; i++ ) { + for ( k = 0; k < nDivs; k++ ) + fprintf( pFile, "%d", Abc_TtGetBit(Vec_WrdEntryP(vDivs, k*nWords), i) ); +// fprintf( pFile, " %d\n", Abc_TtGetBit(Vec_WrdEntryP(vIsfs, 1*nWords), i) ); + if ( Abc_TtGetBit(Vec_WrdEntryP(vIsfs, 0*nWords), i) ) + fprintf( pFile, " 0\n" ); + else if ( Abc_TtGetBit(Vec_WrdEntryP(vIsfs, 1*nWords), i) ) + fprintf( pFile, " 1\n" ); + else + fprintf( pFile, " -\n" ); + } + fprintf( pFile, ".e\n" ); + + fprintf( pFile, "\n.s" ); + Vec_IntForEachEntryStart( vSupp, Temp, i, 2 ) + fprintf( pFile, " %d", Temp ); + fprintf( pFile, "\n.a" ); + Vec_IntForEachEntry( vRes, Temp, i ) + fprintf( pFile, " %d", Temp ); + fprintf( pFile, "\n" ); + fclose ( pFile ); + RetValue = 0; +} + + /**Function************************************************************* Synopsis [] @@ -810,6 +904,7 @@ Vec_Int_t * Supp_ManFindBestSolution( Supp_Man_t * p, Vec_Wec_t * vSols, int fVe } if ( iSolBest > 0 && (CostBest >> 2) < 50 ) { + Vec_Int_t * vDivs2 = Vec_IntAlloc( 100 ); 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 ); @@ -817,13 +912,18 @@ Vec_Int_t * Supp_ManFindBestSolution( Supp_Man_t * p, Vec_Wec_t * vSols, int fVe { Vec_IntClear( *pvDivs ); Vec_IntPushTwo( *pvDivs, -1, -1 ); - Vec_IntForEachEntry( vSet, iObj, i ) + Vec_IntPushTwo( vDivs2, -1, -1 ); + Vec_IntForEachEntry( vSet, iObj, i ) { Vec_IntPush( *pvDivs, Vec_IntEntry(p->vCands, iObj) ); + Vec_IntPush( vDivs2, iObj ); + } } //Supp_DeriveDumpProbC( p->vIsfs, p->vDivsC, p->nWords ); //Supp_DeriveDumpProb( p->vIsfs, p->vDivs[1], p->nWords ); //Supp_DeriveDumpSol( vSet, vRes, Vec_WrdSize(p->vDivs[1])/p->nWords ); - //s_Counter++; + //Supp_DeriveDumpProb2( p->vIsfs, p->vDivs[1], p->nWords, vDivs2, vRes ); + Vec_IntFree( vDivs2 ); + s_Counter++; } return vRes; } @@ -870,7 +970,11 @@ Vec_Int_t * Supp_ManCompute( Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * 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 ); + Supp_Man_t * p; + if ( vCands ) + p = Supp_ManCreate( vIsfs, vCands, vWeights, vSims, vSimsC, nWords, pGia, nIters, nRounds ); + else + p = Supp_ManCreate2( vIsfs, vSims, NULL, nWords, nIters, nRounds ); if ( Supp_SetFuncNum(p, 0) == 0 ) { Supp_ManDelete( p ); @@ -881,7 +985,7 @@ Vec_Int_t * Supp_ManCompute( Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * return vRes; } if ( fVerbose ) - printf( "\nUsing %d divisors with %d words. Problem has %d functions and %d minterm pairs.\n", + printf( "Using %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 ) @@ -962,6 +1066,85 @@ void Supp_ManComputeTest( Gia_Man_t * p ) Vec_IntFree( vRes ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Supp_RecordSolution( char * pFileName, Vec_Int_t * vDivs, Vec_Int_t * vRes ) +{ + FILE * pFile = fopen( pFileName, "ab" ); + if ( pFile == NULL ) { + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + return; + } + int i, Temp; + fprintf( pFile, "\n.s" ); + Vec_IntForEachEntryStart( vDivs, Temp, i, 2 ) + fprintf( pFile, " %d", Temp ); + fprintf( pFile, "\n.a" ); + Vec_IntForEachEntry( vRes, Temp, i ) + fprintf( pFile, " %d", Temp-2 ); + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Supp_GenerateGia( Vec_Int_t * vRes, Vec_Int_t * vDivs ) +{ + int i, nAddOn = 2, nIns = Vec_IntSize(vDivs)-2; + int iLit0, iLit1, iTopLit = Vec_IntEntryLast(vRes); + assert( Vec_IntSize(vRes) > 0 ); + assert( Vec_IntSize(vRes) % 2 == 1 ); + Gia_Man_t * pNew = Gia_ManStart( 100 ); + pNew->pName = Abc_UtilStrsav( "resub" ); + for ( i = 0; i < nIns; i++ ) + Gia_ManAppendCi(pNew); + Vec_IntForEachEntryDouble( vRes, iLit0, iLit1, i ) { + if ( iLit0 < iLit1 ) + Gia_ManAppendAnd( pNew, iLit0-nAddOn, iLit1-nAddOn ); + else if ( iLit0 > iLit1 ) + Gia_ManAppendXor( pNew, iLit0-nAddOn, iLit1-nAddOn ); + else assert( 0 ); + } + Gia_ManAppendCo(pNew, iTopLit-nAddOn); + return pNew; +} +Gia_Man_t * Supp_ManSolveOne( char * pFileName, int nIters, int nRounds, int fWriteSol, int fVerbose ) +{ + //Abc_Random(1); + Abc_RData_t * p = Abc_ReadPla( pFileName ); + if ( p == NULL ) return NULL; + assert( p->nOuts == 1 ); + Vec_Int_t * vDivs = Vec_IntAlloc( 100 ); + Vec_Int_t * vRes = Supp_ManCompute( p->vSimsOut, NULL, NULL, p->vSimsIn, NULL, p->nSimWords, NULL, &vDivs, nIters, nRounds, fVerbose ); + if ( fVerbose && vDivs ) printf( "Divisors: " ), Vec_IntPrint( vDivs ); + if ( fVerbose && vRes ) printf( "Solution: " ), Vec_IntPrint( vRes ); + Gia_Man_t * pNew = vRes ? Supp_GenerateGia( vRes, vDivs ) : NULL; + if ( fWriteSol && vDivs && vRes ) + Supp_RecordSolution( pFileName, vDivs, vRes ); + Vec_IntFreeP( &vRes ); + Vec_IntFreeP( &vDivs ); + Abc_RDataStop( p ); + return pNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaSwitch.c b/src/aig/gia/giaSwitch.c index 4722ef0f5..bf94ad72d 100644 --- a/src/aig/gia/giaSwitch.c +++ b/src/aig/gia/giaSwitch.c @@ -681,6 +681,33 @@ Vec_Int_t * Gia_ManComputeSwitchProbs( Gia_Man_t * pGia, int nFrames, int nPref, // perform the computation of switching activity return Gia_ManSwiSimulate( pGia, pPars ); } +Vec_Int_t * Gia_ManComputeSwitchProbs2( Gia_Man_t * pGia, int nFrames, int nPref, int fProbOne, int nRandPiFactor ) +{ + Gia_ParSwi_t Pars, * pPars = &Pars; + // set the default parameters + Gia_ManSetDefaultParamsSwi( pPars ); + pPars->nRandPiFactor = nRandPiFactor; + // override some of the defaults + pPars->nIters = nFrames; // set number of total timeframes + if ( Abc_FrameReadFlag("seqsimframes") ) + pPars->nIters = atoi( Abc_FrameReadFlag("seqsimframes") ); + pPars->nPref = nPref; // set number of first timeframes to skip + // decide what should be computed + if ( fProbOne ) + { + // if the user asked to compute propability of 1, we do not need transition information + pPars->fProbOne = 1; // enable computing probabiblity of being one + pPars->fProbTrans = 0; // disable computing transition probability + } + else + { + // if the user asked for transition propabability, we do not need to compute probability of 1 + pPars->fProbOne = 0; // disable computing probabiblity of being one + pPars->fProbTrans = 1; // enable computing transition probability + } + // perform the computation of switching activity + return Gia_ManSwiSimulate( pGia, pPars ); +} Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * pAig, int nFrames, int nPref, int fProbOne ) { Vec_Int_t * vSwitching, * vResult; diff --git a/src/aig/gia/giaTranStoch.c b/src/aig/gia/giaTranStoch.c index aa600c0c0..f7b300c0d 100644 --- a/src/aig/gia/giaTranStoch.c +++ b/src/aig/gia/giaTranStoch.c @@ -423,6 +423,10 @@ Gia_Man_t * Gia_ManTranStoch( Gia_Man_t * pGia, int nRestarts, int nHops, int nS if ( nVerbose ) printf( "best: %d\n", Gia_ManAndNum( pBest ) ); Vec_PtrFree( vpStarts ); + ABC_FREE( pBest->pName ); + ABC_FREE( pBest->pSpec ); + pBest->pName = Abc_UtilStrsav( pGia->pName ); + pBest->pSpec = Abc_UtilStrsav( pGia->pSpec ); return pBest; } diff --git a/src/aig/gia/giaUtil.c b/src/aig/gia/giaUtil.c index 69a6e7235..b60b039be 100644 --- a/src/aig/gia/giaUtil.c +++ b/src/aig/gia/giaUtil.c @@ -48,8 +48,13 @@ ABC_NAMESPACE_IMPL_START ***********************************************************************/ unsigned Gia_ManRandom( int fReset ) { +#ifdef _MSC_VER static unsigned int m_z = NUMBER1; static unsigned int m_w = NUMBER2; +#else + static __thread unsigned int m_z = NUMBER1; + static __thread unsigned int m_w = NUMBER2; +#endif if ( fReset ) { m_z = NUMBER1; @@ -3274,6 +3279,194 @@ void Gia_ManTestProblem() } } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_GenDecoder( Gia_Man_t * p, int * pLits, int nLits ) +{ + if ( nLits == 1 ) + { + Vec_Int_t * vRes = Vec_IntAlloc( 2 ); + Vec_IntPush( vRes, Abc_LitNot(pLits[0]) ); + Vec_IntPush( vRes, pLits[0] ); + return vRes; + } + assert( nLits > 1 ); + int nPart1 = nLits / 2; + int nPart2 = nLits - nPart1; + Vec_Int_t * vRes1 = Gia_GenDecoder( p, pLits, nPart1 ); + Vec_Int_t * vRes2 = Gia_GenDecoder( p, pLits+nPart1, nPart2 ); + Vec_Int_t * vRes = Vec_IntAlloc( Vec_IntSize(vRes1) * Vec_IntSize(vRes2) ); + int i, k, Lit1, Lit2; + Vec_IntForEachEntry( vRes2, Lit2, k ) + Vec_IntForEachEntry( vRes1, Lit1, i ) + Vec_IntPush( vRes, Gia_ManHashAnd(p, Lit1, Lit2) ); + Vec_IntFree( vRes1 ); + Vec_IntFree( vRes2 ); + return vRes; +} +Gia_Man_t * Gia_ManGenMux( int nIns, char * pNums ) +{ + Vec_Int_t * vIns = Vec_IntAlloc( nIns ); + Vec_Int_t * vData = Vec_IntAlloc( 1 << nIns ); + Gia_Man_t * p = Gia_ManStart( 4*(1 << nIns) + nIns ), * pTemp; + int i, iStart = 0, nSize = 1 << nIns; + p->pName = Abc_UtilStrsav( "mux" ); + for ( i = 0; i < nIns; i++ ) + Vec_IntPush( vIns, Gia_ManAppendCi(p) ); + for ( i = 0; i < nSize; i++ ) + Vec_IntPush( vData, Gia_ManAppendCi(p) ); + Gia_ManHashAlloc( p ); + for ( i = (int)strlen(pNums)-1; i >= 0; i-- ) + { + int k, b, nBits = (int)(pNums[i] - '0'); + Vec_Int_t * vDec = Gia_GenDecoder( p, Vec_IntEntryP(vIns, iStart), nBits ); + for ( k = 0; k < nSize; k++ ) + Vec_IntWriteEntry( vData, k, Gia_ManHashAnd(p, Vec_IntEntry(vData, k), Vec_IntEntry(vDec, k%Vec_IntSize(vDec))) ); + for ( b = 0; b < nBits; b++, nSize /= 2 ) + for ( k = 0; k < nSize/2; k++ ) + Vec_IntWriteEntry( vData, k, Gia_ManHashOr(p, Vec_IntEntry(vData, 2*k), Vec_IntEntry(vData, 2*k+1)) ); + Vec_IntFree( vDec ); + iStart += nBits; + } + assert( nSize == 1 ); + Gia_ManAppendCo( p, Vec_IntEntry(vData, 0) ); + Vec_IntFree( vIns ); + Vec_IntFree( vData ); + p = Gia_ManCleanup( pTemp = p ); + Gia_ManStop( pTemp ); + return p; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if this window has a topo error (forward path from an output to an input).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManWindowCheckTopoError_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( !Gia_ObjIsAnd(pObj) ) + return 0; + if ( Gia_ObjIsTravIdPrevious(p, pObj) ) + return 1; // there is an error + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 0; // there is no error; visited this node before + Gia_ObjSetTravIdPrevious(p, pObj); + if ( Gia_ManWindowCheckTopoError_rec(p, Gia_ObjFanin0(pObj)) || Gia_ManWindowCheckTopoError_rec(p, Gia_ObjFanin1(pObj)) ) + return 1; + Gia_ObjSetTravIdCurrent(p, pObj); + return 0; +} +int Gia_ManWindowCheckTopoError( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vOuts ) +{ + Gia_Obj_t * pObj; int i, fError = 0; + // outputs should be internal nodes + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + assert(Gia_ObjIsAnd(pObj)); + // mark outputs + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + Gia_ObjSetTravIdCurrent(p, pObj); + // start from inputs and make sure we do not reach any of the outputs + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vIns, p, pObj, i ) + fError |= Gia_ManWindowCheckTopoError_rec(p, pObj); + return fError; +} + +/**Function************************************************************* + + Synopsis [Updates the AIG after multiple windows have been optimized.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManDupInsertWindows_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vMap, Vec_Ptr_t * vvIns, Vec_Ptr_t * vvOuts, Vec_Ptr_t * vWins ) +{ + if ( ~pObj->Value ) + return pObj->Value; + assert( Gia_ObjIsAnd(pObj) ); + if ( Vec_IntEntry(vMap, Gia_ObjId(p, pObj)) == -1 ) // this is a regular node + { + Gia_ManDupInsertWindows_rec( pNew, p, Gia_ObjFanin0(pObj), vMap, vvIns, vvOuts, vWins ); + Gia_ManDupInsertWindows_rec( pNew, p, Gia_ObjFanin1(pObj), vMap, vvIns, vvOuts, vWins ); + return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + // this node is an output of a window + int iWin = Vec_IntEntry(vMap, Gia_ObjId(p, pObj)); + Vec_Int_t * vIns = (Vec_Int_t *)Vec_PtrEntry(vvIns, iWin); + Vec_Int_t * vOuts = (Vec_Int_t *)Vec_PtrEntry(vvOuts, iWin); + Gia_Man_t * pWin = (Gia_Man_t *)Vec_PtrEntry(vWins, iWin); + // build transinvite fanins of window inputs + Gia_Obj_t * pNode; int i; + Gia_ManConst0(pWin)->Value = 0; + Gia_ManForEachObjVec( vIns, p, pNode, i ) + Gia_ManPi(pWin, i)->Value = Gia_ManDupInsertWindows_rec( pNew, p, pNode, vMap, vvIns, vvOuts, vWins ); + // add window nodes + Gia_ManForEachAnd( pWin, pNode, i ) + pNode->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pNode), Gia_ObjFanin1Copy(pNode) ); + // transfer to window outputs + Gia_ManForEachObjVec( vOuts, p, pNode, i ) + pNode->Value = Gia_ObjFanin0Copy(Gia_ManPo(pWin, i)); + assert( ~pObj->Value ); + return pObj->Value; +} +Gia_Man_t * Gia_ManDupInsertWindows( Gia_Man_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t * vvOuts, Vec_Ptr_t * vWins ) +{ + // check consistency of input data + Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, k, iNode; + Vec_PtrForEachEntry( Gia_Man_t *, vWins, pTemp, i ) { + Vec_Int_t * vIns = (Vec_Int_t *)Vec_PtrEntry(vvIns, i); + Vec_Int_t * vOuts = (Vec_Int_t *)Vec_PtrEntry(vvOuts, i); + assert( Vec_IntSize(vIns) == Gia_ManPiNum(pTemp) ); + assert( Vec_IntSize(vOuts) == Gia_ManPoNum(pTemp) ); + assert( !Gia_ManWindowCheckTopoError(p, vIns, vOuts) ); + } + // create mapping of window outputs into window IDs + Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(p) ), * vOuts; + Vec_PtrForEachEntry( Vec_Int_t *, vvOuts, vOuts, i ) + Vec_IntForEachEntry( vOuts, iNode, k ) + Vec_IntWriteEntry( vMap, iNode, i ); + // create the resulting AIG by performing DFS from the POs of the original AIG + // it goes recursively through original nodes and windows until it reaches the PIs of the original AIG + 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_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupInsertWindows_rec( pNew, p, Gia_ObjFanin0(pObj), vMap, vvIns, vvOuts, vWins ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + // cleanup and return + Vec_IntFree( vMap ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + //Gia_ManPrint( pNew ); + return pNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/module.make b/src/aig/gia/module.make index 9e5ae3a57..27240f443 100644 --- a/src/aig/gia/module.make +++ b/src/aig/gia/module.make @@ -56,6 +56,7 @@ SRC += src/aig/gia/giaAig.c \ src/aig/gia/giaMini.c \ src/aig/gia/giaMinLut.c \ src/aig/gia/giaMinLut2.c \ + src/aig/gia/giaMulFind.c \ src/aig/gia/giaMuxes.c \ src/aig/gia/giaNf.c \ src/aig/gia/giaOf.c \ diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index 58131f185..73d218438 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -214,6 +214,7 @@ struct Abc_Ntk_t_ Vec_Ptr_t * vAttrs; // managers of various node attributes (node functionality, global BDDs, etc) Vec_Int_t * vNameIds; // name IDs Vec_Int_t * vFins; // obj/type info + Vec_Int_t * vOrigNodeIds; // original node IDs }; struct Abc_Des_t_ @@ -677,6 +678,7 @@ extern ABC_DLL void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ) extern ABC_DLL int Abc_NtkSopToAig( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk ); extern ABC_DLL Gia_Man_t * Abc_NtkAigToGia( Abc_Ntk_t * p, int fGiaSimple ); +extern ABC_DLL int Abc_NtkMapToSopUsingLibrary( Abc_Ntk_t * pNtk, void* library ); extern ABC_DLL int Abc_NtkMapToSop( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit ); extern ABC_DLL int Abc_NtkToBdd( Abc_Ntk_t * pNtk ); diff --git a/src/base/abc/abcFunc.c b/src/base/abc/abcFunc.c index 805b91daa..68b5688b8 100644 --- a/src/base/abc/abcFunc.c +++ b/src/base/abc/abcFunc.c @@ -33,7 +33,8 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -#define ABC_MAX_CUBES 100000 +#define ABC_MAX_CUBES 1000000 +#define ABC_MAX_CUBES2 10000 static Hop_Obj_t * Abc_ConvertSopToAig( Hop_Man_t * pMan, char * pSop ); @@ -42,11 +43,63 @@ static Hop_Obj_t * Abc_ConvertSopToAig( Hop_Man_t * pMan, char * pSop ); int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase ); static DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot); extern int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ); +extern void Abc_NtkSortCubes( Abc_Ntk_t * pNtk, int fWeight ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// +/**Function************************************************************* + + Synopsis [Converts the node from SOP to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ConvertSopToBdd2Count( char * pSop, int nCubes, int nStep, int iVar, int pRes[3] ) +{ + int i; + for ( i = 0; i < nCubes; i++ ) + if ( pSop[i*nStep+iVar] == '-' ) + pRes[0]++, assert( pRes[1] == 0 && pRes[2] == 0 ); + else if ( pSop[i*nStep+iVar] == '0' ) + pRes[1]++, assert( pRes[2] == 0 ); + else if ( pSop[i*nStep+iVar] == '1' ) + pRes[2]++; + else assert( 0 ); +} +DdNode * Abc_ConvertSopToBdd2_rec( DdManager * dd, char * pSop, DdNode ** pbVars, int nCubes, int nStep, int iVar ) +{ + DdNode * bRes[5] = {NULL}; + int pRes[3] = {0}, i, Start = 0; + if ( nCubes == 0 ) + return Cudd_ReadLogicZero(dd); + if ( iVar == nStep - 3 ) + return Cudd_ReadOne(dd); + Abc_ConvertSopToBdd2Count( pSop, nCubes, nStep, iVar, pRes ); + for ( i = 0; i < 3; Start += pRes[i++] ) + bRes[i] = Abc_ConvertSopToBdd2_rec( dd, pSop + Start*nStep, pbVars, pRes[i], nStep, iVar+1 ), Cudd_Ref( bRes[i] ); + bRes[3] = Cudd_bddIte( dd, pbVars[iVar], bRes[2], bRes[1] ); Cudd_Ref( bRes[3] ); + Cudd_RecursiveDeref( dd, bRes[1] ); + Cudd_RecursiveDeref( dd, bRes[2] ); + bRes[4] = Cudd_bddOr( dd, bRes[0], bRes[3] ); Cudd_Ref( bRes[4] ); + Cudd_RecursiveDeref( dd, bRes[3] ); + Cudd_RecursiveDeref( dd, bRes[0] ); + Cudd_Deref( bRes[4] ); + return bRes[4]; +} +DdNode * Abc_ConvertSopToBdd2( DdManager * dd, char * pSop, DdNode ** pbVars ) +{ + int nCubes = Abc_SopGetCubeNum(pSop); + int nStep = Abc_SopGetVarNum(pSop) + 3; + assert( pSop[nCubes*nStep] == '\0' ); + return Abc_ConvertSopToBdd2_rec( dd, pSop, pbVars, nCubes, nStep, 0 ); +} + /**Function************************************************************* Synopsis [Converts the node from SOP to BDD representation.] @@ -74,6 +127,21 @@ DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop, DdNode ** pbVars ) bSum = Cudd_bddXor( dd, bTemp = bSum, pbVars? pbVars[v] : Cudd_bddIthVar(dd, v) ); Cudd_Ref( bSum ); Cudd_RecursiveDeref( dd, bTemp ); } + } + else if ( Abc_SopGetCubeNum(pSop) > ABC_MAX_CUBES2 ) + { + Cudd_Deref( bSum ); + if ( pbVars ) + bSum = Abc_ConvertSopToBdd2( dd, pSop, pbVars ); + else + { + DdNode ** pbVars = ABC_ALLOC( DdNode *, nVars ); + for ( v = 0; v < nVars; v++ ) + pbVars[v] = Cudd_bddIthVar( dd, v ); + bSum = Abc_ConvertSopToBdd2( dd, pSop, pbVars ); + ABC_FREE( pbVars ); + } + Cudd_Ref( bSum ); } else { @@ -120,10 +188,16 @@ int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk ) Abc_Obj_t * pNode; DdManager * dd, * ddTemp = NULL; Vec_Int_t * vFanins = NULL; - int nFaninsMax, i, k, iVar; + int nFaninsMax, i, k, iVar, nCubesMax = 0; assert( Abc_NtkHasSop(pNtk) ); + // check SOP sizes + Abc_NtkForEachNode( pNtk, pNode, i ) + nCubesMax = Abc_MaxInt( nCubesMax, Abc_SopGetCubeNum((char *)pNode->pData) ); + if ( nCubesMax > ABC_MAX_CUBES2 ) + Abc_NtkSortCubes( pNtk, 0 ); + // start the functionality manager nFaninsMax = Abc_NtkGetFaninMax( pNtk ); if ( nFaninsMax == 0 ) @@ -1108,7 +1182,7 @@ Abc_Obj_t * Abc_ConvertAigToAig( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pObjOld ) /**Function************************************************************* - Synopsis [Unmaps the network.] + Synopsis [Unmaps the network with user provided Mio library.] Description [] @@ -1117,16 +1191,15 @@ Abc_Obj_t * Abc_ConvertAigToAig( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pObjOld ) SeeAlso [] ***********************************************************************/ -int Abc_NtkMapToSop( Abc_Ntk_t * pNtk ) +int Abc_NtkMapToSopUsingLibrary( Abc_Ntk_t * pNtk, void* library) { - extern void * Abc_FrameReadLibGen(); Abc_Obj_t * pNode; char * pSop; int i; assert( Abc_NtkHasMapping(pNtk) ); // update the functionality manager - assert( pNtk->pManFunc == Abc_FrameReadLibGen() ); + assert( pNtk->pManFunc == (void*) library ); pNtk->pManFunc = Mem_FlexStart(); // update the nodes Abc_NtkForEachNode( pNtk, pNode, i ) @@ -1141,6 +1214,23 @@ int Abc_NtkMapToSop( Abc_Ntk_t * pNtk ) return 1; } +/**Function************************************************************* + + Synopsis [Unmaps the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMapToSop( Abc_Ntk_t * pNtk ) +{ + extern void * Abc_FrameReadLibGen(); + return Abc_NtkMapToSopUsingLibrary(pNtk, Abc_FrameReadLibGen()); +} + /**Function************************************************************* Synopsis [Converts SOP functions into BLIF-MV functions.] diff --git a/src/base/abc/abcNtk.c b/src/base/abc/abcNtk.c index 2c8e03b34..3c8fd383e 100644 --- a/src/base/abc/abcNtk.c +++ b/src/base/abc/abcNtk.c @@ -461,6 +461,15 @@ Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ) if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + // move object IDs + if ( pNtk->vOrigNodeIds ) + { + pNtkNew->vOrigNodeIds = Vec_IntStartFull( Abc_NtkObjNumMax(pNtkNew) ); + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->pCopy && Vec_IntEntry(pNtk->vOrigNodeIds, pObj->Id) > 0 ) + Vec_IntWriteEntry( pNtkNew->vOrigNodeIds, pObj->pCopy->Id, Vec_IntEntry(pNtk->vOrigNodeIds, pObj->Id) ); + } + } // duplicate the EXDC Ntk if ( pNtk->pExdc ) @@ -1483,6 +1492,7 @@ void Abc_NtkDelete( Abc_Ntk_t * pNtk ) Vec_IntFreeP( &pNtk->vObjPerm ); Vec_IntFreeP( &pNtk->vTopo ); Vec_IntFreeP( &pNtk->vFins ); + Vec_IntFreeP( &pNtk->vOrigNodeIds ); ABC_FREE( pNtk ); } diff --git a/src/base/abc/abcShow.c b/src/base/abc/abcShow.c index 5bf8fd8a5..cdd53fc20 100644 --- a/src/base/abc/abcShow.c +++ b/src/base/abc/abcShow.c @@ -241,7 +241,7 @@ void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ) // add the root node to the cone (for visualization) Vec_PtrPush( vCutSmall, pNode ); // write the DOT file - Io_WriteDotNtk( pNode->pNtk, vInside, vCutSmall, FileNameDot, 0, 0 ); + Io_WriteDotNtk( pNode->pNtk, vInside, vCutSmall, FileNameDot, 0, 0, 0 ); // stop the cut computation manager Abc_NtkManCutStop( p ); @@ -260,7 +260,7 @@ void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ) SeeAlso [] ***********************************************************************/ -void Abc_NtkShow( Abc_Ntk_t * pNtk0, int fGateNames, int fSeq, int fUseReverse, int fKeepDot ) +void Abc_NtkShow( Abc_Ntk_t * pNtk0, int fGateNames, int fSeq, int fUseReverse, int fKeepDot, int fAigIds ) { FILE * pFile; Abc_Ntk_t * pNtk; @@ -302,7 +302,7 @@ void Abc_NtkShow( Abc_Ntk_t * pNtk0, int fGateNames, int fSeq, int fUseReverse, if ( fSeq ) Io_WriteDotSeq( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse ); else - Io_WriteDotNtk( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse ); + Io_WriteDotNtk( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse, fAigIds ); pNtk->nBarBufs = nBarBufs; Vec_PtrFree( vNodes ); diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 6d6530741..c61e3f437 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -148,9 +148,12 @@ static int Abc_CommandRewrite ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRestructure ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandResubstitute ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandResubUnate ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandResubCore ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandResubCheck ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRr ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCascade ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandLutCas ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandExtract ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandVarMin ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFaultClasses ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -212,6 +215,8 @@ static int Abc_CommandCareSet ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandEspresso ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandGenTF ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandGenAT ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandGenFsm ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCover ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDouble ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -601,8 +606,18 @@ static int Abc_CommandAbc9ProdAdd ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9AddFlop ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9BMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9GenHie ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9PutOnTop ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9BRecover ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9StrEco ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GenCex ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Odc ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GenRel ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GenMux ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Window ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9FunAbs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9DsdInfo ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9FunTrace ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9MulFind ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -928,9 +943,12 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "refactor", Abc_CommandRefactor, 1 ); // Cmd_CommandAdd( pAbc, "Synthesis", "restructure", Abc_CommandRestructure, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "resub", Abc_CommandResubstitute, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "resub_unate", Abc_CommandResubUnate, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "resub_core", Abc_CommandResubCore, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "resub_check", Abc_CommandResubCheck, 0 ); // Cmd_CommandAdd( pAbc, "Synthesis", "rr", Abc_CommandRr, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "cascade", Abc_CommandCascade, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "lutcas", Abc_CommandLutCas, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "extract", Abc_CommandExtract, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "varmin", Abc_CommandVarMin, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "faultclasses", Abc_CommandFaultClasses, 0 ); @@ -993,6 +1011,8 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Various", "cut", Abc_CommandCut, 0 ); Cmd_CommandAdd( pAbc, "Various", "espresso", Abc_CommandEspresso, 1 ); Cmd_CommandAdd( pAbc, "Various", "gen", Abc_CommandGen, 0 ); + Cmd_CommandAdd( pAbc, "Various", "gentf", Abc_CommandGenTF, 0 ); + Cmd_CommandAdd( pAbc, "Various", "genat", Abc_CommandGenAT, 0 ); Cmd_CommandAdd( pAbc, "Various", "genfsm", Abc_CommandGenFsm, 0 ); Cmd_CommandAdd( pAbc, "Various", "cover", Abc_CommandCover, 1 ); Cmd_CommandAdd( pAbc, "Various", "double", Abc_CommandDouble, 1 ); @@ -1386,10 +1406,20 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&addflop", Abc_CommandAbc9AddFlop, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&bmiter", Abc_CommandAbc9BMiter, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&gen_hie", Abc_CommandAbc9GenHie, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&putontop", Abc_CommandAbc9PutOnTop, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&brecover", Abc_CommandAbc9BRecover, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&str_eco", Abc_CommandAbc9StrEco, 0 ); - - Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&gencex", Abc_CommandAbc9GenCex, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&odc", Abc_CommandAbc9Odc, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&genrel", Abc_CommandAbc9GenRel, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&genmux", Abc_CommandAbc9GenMux, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&window", Abc_CommandAbc9Window, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&funabs", Abc_CommandAbc9FunAbs, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&dsdinfo", Abc_CommandAbc9DsdInfo, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&funtrace", Abc_CommandAbc9FunTrace, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&mulfind", Abc_CommandAbc9MulFind, 0 ); + + Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 ); { // extern Mf_ManTruthCount(); // Mf_ManTruthCount(); @@ -3206,7 +3236,8 @@ int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) int fUseReverse; int fFlopDep; int fKeepDot; - extern void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse, int fKeepDot ); + int fAigIds; + extern void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse, int fKeepDot, int fAigIds ); extern void Abc_NtkShowFlopDependency( Abc_Ntk_t * pNtk ); // set defaults @@ -3215,8 +3246,9 @@ int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) fUseReverse = 1; fFlopDep = 0; fKeepDot = 0; + fAigIds = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "rsgfdh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "rsgfdih" ) ) != EOF ) { switch ( c ) { @@ -3235,6 +3267,9 @@ int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'd': fKeepDot ^= 1; break; + case 'i': + fAigIds ^= 1; + break; default: goto usage; } @@ -3249,11 +3284,11 @@ int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( fFlopDep ) Abc_NtkShowFlopDependency( pNtk ); else - Abc_NtkShow( pNtk, fGateNames, fSeq, fUseReverse, fKeepDot ); + Abc_NtkShow( pNtk, fGateNames, fSeq, fUseReverse, fKeepDot, fAigIds ); return 0; usage: - Abc_Print( -2, "usage: show [-srgfdh]\n" ); + Abc_Print( -2, "usage: show [-srgfdih]\n" ); Abc_Print( -2, " visualizes the network structure using DOT and GSVIEW\n" ); #ifdef WIN32 Abc_Print( -2, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); @@ -3264,6 +3299,7 @@ usage: Abc_Print( -2, "\t-g : toggles printing gate names for mapped network [default = %s].\n", fGateNames? "yes": "no" ); Abc_Print( -2, "\t-f : toggles visualizing flop dependency graph [default = %s].\n", fFlopDep? "yes": "no" ); Abc_Print( -2, "\t-d : toggles keeping the .dot file used to produce the .ps file [default = %s].\n", fKeepDot? "yes": "no" ); + Abc_Print( -2, "\t-i : toggles using original AIG object IDs as node labels [default = %s].\n", fAigIds? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -3281,15 +3317,15 @@ usage: ***********************************************************************/ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); - Abc_Obj_t * pNode; - int c, fCompl = 0, fGlobal = 0, fReorder = 1; + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Obj_t * pNode; + int c, fCompl = 0, fGlobal = 0, fReorder = 1, fWidth = 0; extern void Abc_NodeShowBdd( Abc_Obj_t * pNode, int fCompl ); extern void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl, int fReorder ); + extern void Abc_NtkBddDecExplore( Abc_Obj_t * pNode ); // set defaults Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "cgrh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "cgrwh" ) ) != EOF ) { switch ( c ) { @@ -3302,6 +3338,9 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'r': fReorder ^= 1; break; + case 'w': + fWidth ^= 1; + break; case 'h': goto usage; default: @@ -3313,7 +3352,7 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Print( -1, "Empty network.\n" ); return 1; - } + } if ( fGlobal ) { @@ -3328,7 +3367,7 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Print( -1, "Visualizing BDDs can only be done for logic BDD networks (run \"bdd\").\n" ); return 1; - } + } if ( argc > globalUtilOptind + 1 ) { Abc_Print( -1, "Wrong number of auguments.\n" ); @@ -3352,11 +3391,14 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } } - Abc_NodeShowBdd( pNode, fCompl ); + if ( fWidth ) + Abc_NtkBddDecExplore( pNode ); + else + Abc_NodeShowBdd( pNode, fCompl ); return 0; usage: - Abc_Print( -2, "usage: show_bdd [-cgrh] \n" ); + Abc_Print( -2, "usage: show_bdd [-cgrwh] \n" ); Abc_Print( -2, " uses DOT and GSVIEW to visualize the global BDDs of primary outputs\n" ); Abc_Print( -2, " in terms of primary inputs or the local BDD of a node in terms of its fanins\n" ); #ifdef WIN32 @@ -3367,6 +3409,7 @@ usage: Abc_Print( -2, "\t-c : toggle visualizing BDD with complemented edges [default = %s].\n", fCompl? "yes": "no" ); Abc_Print( -2, "\t-g : toggle visualizing the global BDDs of primary outputs [default = %s].\n", fGlobal? "yes": "no" ); Abc_Print( -2, "\t-r : toggles dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" ); + Abc_Print( -2, "\t-w : toggles printing width profile of the node's BDD [default = %s]\n", fWidth? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -5181,18 +5224,14 @@ usage: ***********************************************************************/ int Abc_CommandLutmin( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Abc_Ntk_t * pNtk, * pNtkRes; + extern Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtk, int nLutSize, int fReorder, int fVerbose ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; int c; - int nLutSize; - int fVerbose; - extern Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - // set defaults - nLutSize = 4; - fVerbose = 0; + int nLutSize = 4; + int fReorder = 1; + int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Kvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Krvh" ) ) != EOF ) { switch ( c ) { @@ -5205,6 +5244,9 @@ int Abc_CommandLutmin( Abc_Frame_t * pAbc, int argc, char ** argv ) nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; + case 'r': + fReorder ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -5220,7 +5262,7 @@ int Abc_CommandLutmin( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } // modify the current network - pNtkRes = Abc_NtkLutmin( pNtk, nLutSize, fVerbose ); + pNtkRes = Abc_NtkLutmin( pNtk, nLutSize, fReorder, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "The command has failed.\n" ); @@ -5231,11 +5273,12 @@ int Abc_CommandLutmin( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: lutmin [-K ] [-vh]\n" ); + Abc_Print( -2, "usage: lutmin [-K ] [-rvh]\n" ); Abc_Print( -2, "\t perform FPGA mapping while minimizing the LUT count\n" ); Abc_Print( -2, "\t as described in the paper T. Sasao and A. Mishchenko:\n" ); Abc_Print( -2, "\t \"On the number of LUTs to implement logic functions\".\n" ); Abc_Print( -2, "\t-K : the LUT size to use for the mapping (2 <= num) [default = %d]\n", nLutSize ); + Abc_Print( -2, "\t-r : toggle using BDD variable reordering [default = %s]\n", fReorder? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -8350,6 +8393,182 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandResubUnate( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManResubUnateOne( char * pFileName, int nLimit, int nDivMax, int fWriteSol, int fVerbose ); + Gia_Man_t * pTemp; + int nLimit = 16; + int nDivMax = 50; + int fWriteSol = 0; + int fVerbose = 0, c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "LDsvh" ) ) != EOF ) + { + switch ( c ) + { + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + nLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLimit < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + nDivMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nDivMax < 0 ) + goto usage; + break; + case 's': + fWriteSol ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( -1, "Input file should be given on the command line.\n" ); + return 1; + } + pTemp = Gia_ManResubUnateOne( argv[globalUtilOptind], nLimit, nDivMax, fWriteSol, fVerbose ); + if ( pTemp ) + { + Aig_Man_t * pMan = Gia_ManToAig( pTemp, 0 ); + Abc_Ntk_t * pNtk = Abc_NtkFromAigPhase( pMan ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + Aig_ManStop( pMan ); + Gia_ManStop( pTemp ); + return 0; + } + Abc_Print( 0, "The networks is not generated.\n" ); + return 0; + +usage: + Abc_Print( -2, "usage: resub_unate [-LD ] [-svh] \n" ); + Abc_Print( -2, "\t solves one instance of the resub problem\n" ); + Abc_Print( -2, "\t-L num : the limit on the number of nodes [default = %d]\n", nLimit ); + Abc_Print( -2, "\t-D num : the maximum number of binate divisors to consider [default = %d]\n", nDivMax ); + Abc_Print( -2, "\t-s : toggle saving the result in the input file [default = %s]\n", fWriteSol? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : resub problem file name\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandResubCore( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Supp_ManSolveOne( char * pFileName, int nIters, int nRounds, int fWriteSol, int fVerbose ); + Gia_Man_t * pTemp; + int nIters = 1; + int nRounds = 1; + int fWriteSol = 0; + int fVerbose = 0, c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IRsvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nRounds = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nRounds < 0 ) + goto usage; + break; + case 's': + fWriteSol ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( -1, "Input file should be given on the command line.\n" ); + return 1; + } + pTemp = Supp_ManSolveOne( argv[globalUtilOptind], nIters, nRounds, fWriteSol, fVerbose ); + if ( pTemp ) + { + Aig_Man_t * pMan = Gia_ManToAig( pTemp, 0 ); + Abc_Ntk_t * pNtk = Abc_NtkFromAigPhase( pMan ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + Aig_ManStop( pMan ); + Gia_ManStop( pTemp ); + return 0; + } + Abc_Print( 0, "The networks is not generated.\n" ); + return 0; + +usage: + Abc_Print( -2, "usage: resub_core [-IR ] [-svh] \n" ); + Abc_Print( -2, "\t solves one instance of the resub problem\n" ); + Abc_Print( -2, "\t-I num : the number of iterations [default = %d]\n", nIters ); + Abc_Print( -2, "\t-R num : the number of rounds in each iteration [default = %d]\n", nRounds ); + Abc_Print( -2, "\t-s : toggle saving the result in the input file [default = %s]\n", fWriteSol? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : resub problem file name\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -8364,6 +8583,7 @@ usage: int Abc_CommandResubCheck( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Res6_ManResubCheck( char * pFileNameRes, char * pFileNameSol, int fVerbose ); + extern void Res6_ManResubCheckPla( char * pFileName, int fVerbose ); char * pFileR = NULL, * pFileS = NULL; int fVerbose = 0, c; Extra_UtilGetoptReset(); @@ -8395,7 +8615,10 @@ int Abc_CommandResubCheck( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Incorrect number of command line arguments.\n" ); return 1; } - Res6_ManResubCheck( pFileR, pFileS, fVerbose ); + if ( !strcmp(pFileR + strlen(pFileR) - 3, "pla") ) + Res6_ManResubCheckPla( pFileR, fVerbose ); + else + Res6_ManResubCheck( pFileR, pFileS, fVerbose ); return 0; usage: @@ -8603,6 +8826,81 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; + int c, nLutSize = 6, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Kvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkCoNum(pNtk) != 1 ) + { + Abc_Print( -1, "This command is currently applicable only to single-output networks.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Run command \"strash\" to convert the network into an AIG.\n" ); + return 1; + } + pNtkRes = Abc_NtkLutCascade( pNtk, nLutSize, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "LUT cascade mapping failed.\n" ); + return 1; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: lutcas [-K ] [-vh]\n" ); + Abc_Print( -2, "\t derives single-rail LUT cascade for the primary output function\n" ); + Abc_Print( -2, "\t-K : the number of LUT inputs [default = %d]\n", nLutSize ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -10196,7 +10494,10 @@ usage: Abc_Print( -2, "\tfile1 : (optional) the file with the first network\n"); Abc_Print( -2, "\tfile2 : (optional) the file with the second network\n"); Abc_Print( -2, "\t if no files are given, uses the current network and its spec\n"); - Abc_Print( -2, "\t if one file is given, uses the current network and the file\n"); + Abc_Print( -2, "\t if one file is given, uses the current network and the file\n\n"); + Abc_Print( -2, "\t Please note that, when used without \"-n\", this command tries to match\n" ); + Abc_Print( -2, "\t primary inputs by name and, to achieve this, it will order them alphabetically,\n" ); + Abc_Print( -2, "\t which results in incorrect QBF miters and confusing counter-examples.\n" ); return 1; } @@ -11373,6 +11674,11 @@ int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Converting to SOP is possible only for logic networks.\n" ); return 1; } + if ( fCubeSort && Abc_NtkHasSop(pNtk) ) + { + Abc_NtkSortSops(pNtk); + return 0; + } if ( !fCubeSort && Abc_NtkHasBdd(pNtk) && !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY, 0) ) { Abc_Print( -1, "Converting to SOP has failed.\n" ); @@ -13868,6 +14174,197 @@ usage: return 1; } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandGenTF( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_GenThresh( char * pFileName, int nBits, Vec_Int_t * vNums, int nLutSize, char * pArch ); + int c, nBits = 0, nLutSize = -1, fVerbose = 0, nSum = 0; + char Command[1000], * pFileName = "out.blif", * pArch = NULL; + Vec_Int_t * vNums = NULL; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "WKAvh" ) ) != EOF ) + { + switch ( c ) + { + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + nBits = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nBits < 0 ) + goto usage; + break; + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + case 'A': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-A\" should be followed by a file name.\n" ); + goto usage; + } + pArch = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc == globalUtilOptind ) + goto usage; + if ( nBits == 0 ) + { + Abc_Print( -1, "Bit-width should be specified.\n" ); + return 0; + } + if ( nLutSize != -1 && nLutSize != 4 && nLutSize != 6 ) + { + Abc_Print( -1, "LUT size %d is not supported.\n", nLutSize ); + return 0; + } + if ( pArch ) + { + int Counts[2] = {0}; + for ( c = 0; c < strlen(pArch); c++ ) + if ( pArch[c] == '(' ) + Counts[0]++; + else if ( pArch[c] == ')' ) + Counts[1]++; + else if ( pArch[c] >= '1' && pArch[c] <= '9' ) + nSum += pArch[c] - '0'; + else if ( pArch[c] >= 'A' && pArch[c] <= 'Z' ) + nSum += pArch[c] - 'A' + 10; + else { + Abc_Print( -1, "Architecture description contains a wrong symbol (%c).\n", pArch[c] ); + return 0; + } + if ( Counts[0] != Counts[1] ) + { + Abc_Print( -1, "Mismatching number of opening and closing parentheses (%d and %d).\n", Counts[0], Counts[1] ); + return 0; + } + } + vNums = Vec_IntAlloc( argc ); + for ( c = globalUtilOptind; c < argc; c++ ) + Vec_IntPush( vNums, atoi(argv[c]) ); + if ( Vec_IntSize(vNums) < 3 ) { + Abc_Print( -1, "Expecting that at least two weights and a threshold are specified on the command line.\n" ); + Vec_IntFree( vNums ); + return 0; + } + if ( pArch && nSum != Vec_IntSize(vNums)-1 ) { + Abc_Print( -1, "The architecture assumes %d sum inputs while there are %d weights.\n", nSum, Vec_IntSize(vNums)-1 ); + Vec_IntFree( vNums ); + return 0; + } + printf( "Generating threshold function with %d inputs and bit-width %d.\n", Vec_IntSize(vNums)-1, nBits ); + Abc_GenThresh( pFileName, nBits, vNums, nLutSize, pArch ); + if ( nLutSize == 4 || nLutSize == 6 ) + sprintf(Command, "read %s; strash; if -K %d -am; mfs2 -W 10 -L 10 -M 1000", pFileName, nLutSize ); + else + sprintf(Command, "read %s", pFileName ); + Cmd_CommandExecute( pAbc, Command ); + Vec_IntFree( vNums ); + return 0; + +usage: + Abc_Print( -2, "usage: gentf [-WK num] [-A str] [-vh] ... \n" ); + Abc_Print( -2, "\t generates threshold function\n" ); + Abc_Print( -2, "\t-W num : the bit-width [default = none]\n" ); + Abc_Print( -2, "\t-K num : the LUT size [default = none]\n" ); + Abc_Print( -2, "\t-A str : the circuit architecture [default = none]\n"); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : weights and threshold\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandGenAT( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_GenAT( char * pFileName, Vec_Int_t * vNums ); + extern void Abc_GenATDual( char * pFileName, Vec_Int_t * vNums ); + int c, fDual = 0, fVerbose = 0; + char Command[1000], * pFileName = "out.blif"; + Vec_Int_t * vNums = NULL; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dvh" ) ) != EOF ) + { + switch ( c ) + { + case 'd': + fDual ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc == globalUtilOptind ) + goto usage; + vNums = Vec_IntAlloc( argc ); + for ( c = globalUtilOptind; c < argc; c++ ) + Vec_IntPush( vNums, atoi(argv[c]) ); + if ( fDual ) + Abc_GenATDual( pFileName, vNums ); + else + Abc_GenAT( pFileName, vNums ); + sprintf(Command, "read %s", pFileName ); + Cmd_CommandExecute( pAbc, Command ); + Vec_IntFree( vNums ); + return 0; + +usage: + Abc_Print( -2, "usage: genat [-dvh] ... \n" ); + Abc_Print( -2, "\t generates the adder tree\n" ); + Abc_Print( -2, "\t-d : toggle building dual tree [default = %s]\n", fDual? "yes": "no" ); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : input counts by rank\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -14811,6 +15308,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) } */ //Gia_ManTestProblem(); + //Abc_ReadPlaTest( "resub2.pla" ); return 0; usage: Abc_Print( -2, "usage: test [-CKDNM] [-aovwh] \n" ); @@ -16991,6 +17489,36 @@ usage: Abc_Print( -2, "\t-d : toggle dumping QDIMACS file instead of solving [default = %s]\n", fDumpCnf? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t\n" ); + Abc_Print( -2, "\t Consider specification of the two-input XOR and its implementation in the form of a 4:1 MUX:\n\n" ); + Abc_Print( -2, "\t > # file s.blif\n" ); + Abc_Print( -2, "\t > .model xor2\n" ); + Abc_Print( -2, "\t > .inputs d0 d1 d2 d3 a b\n" ); + Abc_Print( -2, "\t > .outputs F\n" ); + Abc_Print( -2, "\t > .names a b F\n" ); + Abc_Print( -2, "\t > 01 1\n" ); + Abc_Print( -2, "\t > 10 1\n" ); + Abc_Print( -2, "\t > .end\n\n" ); + Abc_Print( -2, "\t > # file i.blif\n" ); + Abc_Print( -2, "\t > .model mux21\n" ); + Abc_Print( -2, "\t > .inputs d0 d1 d2 d3 a b\n" ); + Abc_Print( -2, "\t > .outputs F\n" ); + Abc_Print( -2, "\t > .names d0 d1 d2 d3 a b F\n" ); + Abc_Print( -2, "\t > 1---00 1\n" ); + Abc_Print( -2, "\t > -1--10 1\n" ); + Abc_Print( -2, "\t > --1-01 1\n" ); + Abc_Print( -2, "\t > ---111 1\n" ); + Abc_Print( -2, "\t > .end\n\n" ); + Abc_Print( -2, "\t The following run shows how to assign data inputs to the MUX (the first 4 inputs of the miter) to get the XOR:\n\n" ); + Abc_Print( -2, "\t > abc 51> miter -n i.blif s.blif; st -i; ps\n" ); + Abc_Print( -2, "\t > i_s_miter: i/o = 6/ 1 lat = 0 and = 15 lev = 6\n\n" ); + Abc_Print( -2, "\t > abc 53> qbf -P 4\n" ); + Abc_Print( -2, "\t > Parameters: 0110 Statistics: 0=2 1=2\n" ); + Abc_Print( -2, "\t > Solved after 1 iterations. Total runtime = 0.00 sec\n\n" ); + Abc_Print( -2, "\t > abc 53> &get; &qbf -P 4\n" ); + Abc_Print( -2, "\t > Parameters: 0110 Statistics: 0=2 1=2\n" ); + Abc_Print( -2, "\t > The problem is SAT after 2 iterations. Time = 0.00 sec\n\n" ); + Abc_Print( -2, "\t What we synthesized is the truth table of the XOR gate!\n" ); return 1; } @@ -19545,7 +20073,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) If_ManSetDefaultPars( pPars ); pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut(); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYUZDEWSJqaflepmrsdbgxyuojiktncvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYUZDEWSJqaflepmrsdbgxyzuojiktncvh" ) ) != EOF ) { switch ( c ) { @@ -19816,6 +20344,9 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'v': pPars->fVerbose ^= 1; break; + case 'z': + pPars->fDeriveLuts ^= 1; + break; case 'h': default: goto usage; @@ -19933,6 +20464,11 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheck16; } pPars->fCutMin = 1; + pPars->nLutDecSize = pPars->pLutStruct[0] - '0'; + } + else + { + pPars->fDeriveLuts = 0; } if ( pPars->fUserLutDec || pPars->fUserLut2D ) @@ -20116,7 +20652,7 @@ usage: sprintf(LutSize, "library" ); else sprintf(LutSize, "%d", pPars->nLutSize ); - Abc_Print( -2, "usage: if [-KCFAGRNTXYUZ num] [-DEW float] [-SJ str] [-qarlepmsdbgxyuojiktncvh]\n" ); + Abc_Print( -2, "usage: if [-KCFAGRNTXYUZ num] [-DEW float] [-SJ str] [-qarlepmsdbgxyuojiktnczvh]\n" ); Abc_Print( -2, "\t performs FPGA technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); @@ -20156,6 +20692,7 @@ usage: Abc_Print( -2, "\t-t : toggles optimizing average rather than maximum level [default = %s]\n", pPars->fDoAverage? "yes": "no" ); Abc_Print( -2, "\t-n : toggles computing DSDs of the cut functions [default = %s]\n", pPars->fUseDsd? "yes": "no" ); Abc_Print( -2, "\t-c : toggles computing truth tables in a new way [default = %s]\n", pPars->fUseTtPerm? "yes": "no" ); + Abc_Print( -2, "\t-z : toggles deriving LUTs when mapping into LUT structures [default = %s]\n", pPars->fDeriveLuts? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; @@ -33632,9 +34169,9 @@ int Abc_CommandAbc9Cof( Abc_Frame_t * pAbc, int argc, char ** argv ) extern Gia_Man_t * Gia_ManComputeCofs( Gia_Man_t * p, int nVars ); Gia_Man_t * pTemp; int c, fVerbose = 0; - int iVar = 0, nLimFan = 0, nVars = 0; + int iVar = 0, Const = -1, nLimFan = 0, nVars = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "VLNvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "VCLNvh" ) ) != EOF ) { switch ( c ) { @@ -33649,6 +34186,17 @@ int Abc_CommandAbc9Cof( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( iVar < 0 ) goto usage; break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + Const = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Const < 0 || Const > 1 ) + goto usage; + break; case 'L': if ( globalUtilOptind >= argc ) { @@ -33685,7 +34233,13 @@ int Abc_CommandAbc9Cof( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9Cof(): There is no AIG.\n" ); return 1; } - if ( nVars ) + if ( Const == 0 || Const == 1 ) + { + Abc_Print( 0, "Computing cofactor of var %d with value %d.\n", iVar, Const ); + pTemp = Gia_ManDupCofactorVar( pAbc->pGia, iVar, Const ); + Abc_FrameUpdateGia( pAbc, pTemp ); + } + else if ( nVars ) { Abc_Print( 0, "Cofactoring the last %d inputs.\n", nVars ); pTemp = Gia_ManComputeCofs( pAbc->pGia, nVars ); @@ -33711,9 +34265,10 @@ int Abc_CommandAbc9Cof( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &cof [-VLN num] [-vh]\n" ); + Abc_Print( -2, "usage: &cof [-VCLN num] [-vh]\n" ); Abc_Print( -2, "\t performs cofactoring w.r.t. variable(s)\n" ); Abc_Print( -2, "\t-V num : the zero-based ID of one variable to cofactor [default = %d]\n", iVar ); + Abc_Print( -2, "\t-C num : cofactor one variable with a given constant (0 or 1) [default = unused]\n" ); Abc_Print( -2, "\t-L num : cofactor vars with fanout count higher than this [default = %d]\n", nLimFan ); Abc_Print( -2, "\t-N num : cofactoring the given number of last input variables [default = %d]\n", nVars ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); @@ -37817,11 +38372,12 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) Cec_ParCor_t Pars, * pPars = &Pars; Gia_Man_t * pTemp; int fPartition = 0; + int nFlopIncFreq = 0; int fUseOld = 0, c; Cec_ManCorSetDefaultParams( pPars ); pPars->nProcs = 1; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "FCGXPSpkrecqowvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "FCGXPSZpkrecqowvh" ) ) != EOF ) { switch ( c ) { @@ -37891,6 +38447,17 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nPartSize < 0 ) goto usage; break; + case 'Z': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-Z\" should be followed by an integer.\n" ); + goto usage; + } + nFlopIncFreq = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFlopIncFreq < 0 ) + goto usage; + break; case 'p': fPartition ^= 1; break; @@ -37943,6 +38510,31 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( 0, "The network is combinational.\n" ); return 0; } + if ( nFlopIncFreq ) + { + extern Gia_Man_t * Gia_ManDupStopsAdd( Gia_Man_t * p, Vec_Int_t * vStops ); + extern Gia_Man_t * Gia_ManDupStopsRem( Gia_Man_t * p, Vec_Int_t * vStops ); + extern Vec_Int_t * Gia_ManFindStopFlops( Gia_Man_t * p, int nFlopIncFreq, int fVerbose ); + Vec_Int_t * vStops = Gia_ManFindStopFlops( pAbc->pGia, nFlopIncFreq, pPars->fVerbose ); + if ( vStops ) + { + Gia_Man_t * pUsed = Gia_ManDupStopsAdd( pAbc->pGia, vStops ); + if ( pPars->nPartSize > 0 ) + pTemp = Gia_SignalCorrespondencePart( pUsed, pPars ); + else if ( fUseOld ) + pTemp = Cec_ManScorrCorrespondence( pUsed, pPars ); + else if ( fPartition ) + pTemp = Gia_ManScorrDivideTest( pUsed, pPars ); + else + pTemp = Cec_ManLSCorrespondence( pUsed, pPars ); + Gia_ManStop( pUsed ); + pTemp = Gia_ManDupStopsRem( pUsed = pTemp, vStops ); + Gia_ManStop( pUsed ); + Abc_FrameUpdateGia( pAbc, pTemp ); + Vec_IntFree( vStops ); + return 0; + } + } if ( pPars->nPartSize > 0 ) pTemp = Gia_SignalCorrespondencePart( pAbc->pGia, pPars ); else if ( fUseOld ) @@ -37955,7 +38547,7 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &scorr [-FCGXPS num] [-pkrecqowvh]\n" ); + Abc_Print( -2, "usage: &scorr [-FCGXPSZ num] [-pkrecqowvh]\n" ); Abc_Print( -2, "\t performs signal correpondence computation\n" ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-F num : the number of timeframes in inductive case [default = %d]\n", pPars->nFrames ); @@ -37963,6 +38555,7 @@ usage: Abc_Print( -2, "\t-X num : the number of iterations of little or no improvement [default = %d]\n", pPars->nLimitMax ); Abc_Print( -2, "\t-P num : the number of concurrent processes [default = %d]\n", pPars->nProcs ); Abc_Print( -2, "\t-S num : the number of flops in one partition [default = %d]\n", pPars->nPartSize ); + Abc_Print( -2, "\t-Z num : the average flop include frequency [default = %d]\n", nFlopIncFreq ); Abc_Print( -2, "\t-p : toggle using partitioning for the input AIG [default = %s]\n", fPartition? "yes": "no" ); Abc_Print( -2, "\t-k : toggle using constant correspondence [default = %s]\n", pPars->fConstCorr? "yes": "no" ); Abc_Print( -2, "\t-r : toggle using implication rings during refinement [default = %s]\n", pPars->fUseRings? "yes": "no" ); @@ -38297,7 +38890,7 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) int fCbs = 1, approxLim = 600, subBatchSz = 1, adaRecycle = 500, nMaxNodes = 0; Cec4_ManSetParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "JWRILDCNPMrmdckngxysopwqvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "JWRILDCNPMFrmdckngxysopwqvh" ) ) != EOF ) { switch ( c ) { @@ -38411,6 +39004,15 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nMaxNodes < 0 ) goto usage; break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + pPars->pDumpName = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'r': pPars->fRewriting ^= 1; break; @@ -38452,7 +39054,7 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) break; case 'q': pPars->fBMiterInfo ^= 1; - break; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -38492,7 +39094,7 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &fraig [-JWRILDCNPM ] [-rmdckngxysopwvh]\n" ); + Abc_Print( -2, "usage: &fraig [-JWRILDCNPM ] [-F filename] [-rmdckngxysopwvh]\n" ); Abc_Print( -2, "\t performs combinational SAT sweeping\n" ); Abc_Print( -2, "\t-J num : the solver type [default = %d]\n", pPars->jType ); Abc_Print( -2, "\t-W num : the number of simulation words [default = %d]\n", pPars->nWords ); @@ -38504,6 +39106,7 @@ usage: Abc_Print( -2, "\t-N num : the min number of calls to recycle the solver [default = %d]\n", pPars->nCallsRecycle ); Abc_Print( -2, "\t-P num : the number of pattern generation iterations [default = %d]\n", pPars->nGenIters ); Abc_Print( -2, "\t-M num : the node count limit to call the old sweeper [default = %d]\n", nMaxNodes ); + Abc_Print( -2, "\t-F file: the file name to dump primary output information [default = none]\n" ); Abc_Print( -2, "\t-r : toggle the use of AIG rewriting [default = %s]\n", pPars->fRewriting? "yes": "no" ); Abc_Print( -2, "\t-m : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" ); Abc_Print( -2, "\t-d : toggle using double output miters [default = %s]\n", pPars->fDualOut? "yes": "no" ); @@ -39159,6 +39762,11 @@ int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + if ( pAbc->pGia && pAbc->pGia->nXors ) + { + Abc_Print( 0, "It looks like the current AIG is derived by &st -m. Such AIG contains XOR gates and cannot be verified before &st is applied.\n" ); + return 1; + } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( fMiter ) @@ -40440,7 +41048,7 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) } pPars->pLutLib = (If_LibLut_t *)pAbc->pLibLut; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRDEWSTXYqalepmrsdbgxyofuijkztncvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRDEWSJTXYZqalepmrsdbgxyofuijkztncvwh" ) ) != EOF ) { switch ( c ) { @@ -40592,6 +41200,33 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } break; + case 'J': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by string.\n" ); + goto usage; + } + pPars->pLutStruct = argv[globalUtilOptind]; + pPars->fEnableStructN = 1; + globalUtilOptind++; + if ( strlen(pPars->pLutStruct) != 2 ) + { + Abc_Print( -1, "Command line switch \"-J\" should be followed by a 2-char string (e.g. \"44\" or \"55\").\n" ); + goto usage; + } + break; + case 'Z': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-Z\" should be followed by a positive integer 3, 4, 5, or 6.\n" ); + goto usage; + } + pPars->nLutDecSize = atoi(argv[globalUtilOptind]); + pPars->fUserLutDec = 1; + globalUtilOptind++; + if ( pPars->nLutDecSize < 3 || pPars->nLutDecSize > 6 ) + goto usage; + break; case 'q': pPars->fPreprocess ^= 1; break; @@ -40826,8 +41461,35 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "This feature only works for [6;16]-LUTs.\n" ); return 1; } - pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheck16; + if ( pPars->fEnableStructN ) + { + pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheckXX; + } + else + { + pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheck16; + } pPars->fCutMin = 1; + pPars->nLutDecSize = pPars->pLutStruct[0] - '0'; + } + + if ( pPars->fUserLutDec ) + { + if ( pPars->nLutDecSize == 0 ) + { + Abc_Print( -1, "LUT decomposition size (%d) must be set.\n", pPars->nLutDecSize ); + return 1; + } + if ( pPars->nLutDecSize >= pPars->nLutSize ) + { + Abc_Print( -1, "LUT size (%d) must be greater than the LUT decomposition size (%d).\n", pPars->nLutSize, pPars->nLutDecSize ); + return 1; + } + if ( pPars->nLutSize < 4 || pPars->nLutSize > 11 ) + { + Abc_Print( -1, "This feature only works for [4;11]-LUTs.\n" ); + return 1; + } } if ( pPars->fUse34Spec ) @@ -40855,7 +41517,7 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->pLutLib = NULL; } // modify for delay optimization - if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut ) + if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut || pPars->fUserLutDec ) { pPars->fTruth = 1; pPars->fCutMin = 1; @@ -40972,7 +41634,7 @@ usage: sprintf(LutSize, "library" ); else sprintf(LutSize, "%d", pPars->nLutSize ); - Abc_Print( -2, "usage: &if [-KCFAGRTXY num] [-DEW float] [-S str] [-qarlepmsdbgxyofuijkztnchvw]\n" ); + Abc_Print( -2, "usage: &if [-KCFAGRTXY num] [-DEW float] [-SJ str] [-qarlepmsdbgxyofuijkztnchvw]\n" ); Abc_Print( -2, "\t performs FPGA technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); @@ -40987,6 +41649,8 @@ usage: Abc_Print( -2, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon ); Abc_Print( -2, "\t-W float : sets wire delay between adjects LUTs [default = %f]\n", pPars->WireDelay ); Abc_Print( -2, "\t-S str : string representing the LUT structure [default = %s]\n", pPars->pLutStruct ? pPars->pLutStruct : "not used" ); + Abc_Print( -2, "\t-J str : string representing the LUT structure [default = %s]\n", pPars->pLutStruct ? pPars->pLutStruct : "not used" ); + Abc_Print( -2, "\t-Z num : the number of LUT inputs for delay-driven LUT decomposition [default = not used]\n" ); Abc_Print( -2, "\t-q : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" ); Abc_Print( -2, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" ); Abc_Print( -2, "\t-r : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" ); @@ -43812,12 +44476,15 @@ usage: int Abc_CommandAbc9Unmap( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_ManTestStruct( Gia_Man_t * p ); - int c, fVerbose = 0; + int c, fConvert = 0, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "cvh" ) ) != EOF ) { switch ( c ) { + case 'c': + fConvert ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -43832,16 +44499,21 @@ int Abc_CommandAbc9Unmap( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9Struct(): There is no AIG to map.\n" ); return 1; } - Vec_IntFreeP( &pAbc->pGia->vMapping ); - Vec_IntFreeP( &pAbc->pGia->vPacking ); - Vec_IntFreeP( &pAbc->pGia->vCellMapping ); - Vec_IntFreeP( &pAbc->pGia->vEdge1 ); - Vec_IntFreeP( &pAbc->pGia->vEdge2 ); + if ( fConvert ) + Cmd_CommandExecute( pAbc, "&put; unmap; &get -m" ); + else { + Vec_IntFreeP( &pAbc->pGia->vMapping ); + Vec_IntFreeP( &pAbc->pGia->vPacking ); + Vec_IntFreeP( &pAbc->pGia->vCellMapping ); + Vec_IntFreeP( &pAbc->pGia->vEdge1 ); + Vec_IntFreeP( &pAbc->pGia->vEdge2 ); + } return 0; usage: - Abc_Print( -2, "usage: &unmap [-vh]\n" ); + Abc_Print( -2, "usage: &unmap [-cvh]\n" ); Abc_Print( -2, "\t removes mapping from the current network\n" ); + Abc_Print( -2, "\t-c : toggle converting cell mapping into LUT mapping [default = %s]\n", fConvert? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -48012,7 +48684,38 @@ usage: Abc_Print( -2, "\t-e : toggle dumping QDIMACS file instead of solving (original QBF) [default = %s]\n", fDumpCnf2? "yes": "no" ); Abc_Print( -2, "\t-g : toggle using Glucose 3.0 by Gilles Audemard and Laurent Simon [default = %s]\n", fGlucose? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t-h : print the command usage\n\n"); + Abc_Print( -2, "\t As an example of using this command, consider specification (the three-input AND-gate) and implementation\n"); + Abc_Print( -2, "\t (the circuit with function AND(XOR(x0, x1), x2)). The problem is to check whether the output of the XOR (node n)\n"); + Abc_Print( -2, "\t can be implemented differently, so that these two circuits are equivalent. Obviously this can be done!\n"); + Abc_Print( -2, "\t Simply replace XOR gate by AND gate.\n\n"); + Abc_Print( -2, "\t > # file s2.blif\n"); + Abc_Print( -2, "\t > .model and3\n"); + Abc_Print( -2, "\t > .inputs x0 x1 x2 n\n"); + Abc_Print( -2, "\t > .outputs F\n"); + Abc_Print( -2, "\t > .names m x2 F\n"); + Abc_Print( -2, "\t > 11 1\n"); + Abc_Print( -2, "\t > .names x0 x1 m\n"); + Abc_Print( -2, "\t > 11 1\n"); + Abc_Print( -2, "\t > .end\n\n"); + Abc_Print( -2, "\t > # file i2.blif\n"); + Abc_Print( -2, "\t > .model impl\n"); + Abc_Print( -2, "\t > .inputs x0 x1 x2 n\n"); + Abc_Print( -2, "\t > .outputs F\n"); + Abc_Print( -2, "\t > .names n x2 F\n"); + Abc_Print( -2, "\t > 11 1\n"); + Abc_Print( -2, "\t > #.names x0 x1 n\n"); + Abc_Print( -2, "\t > #01 1\n"); + Abc_Print( -2, "\t > #10 1\n"); + Abc_Print( -2, "\t > .end\n\n"); + Abc_Print( -2, "\t > abc 08> miter -n i2.blif s2.blif; ps\n"); + Abc_Print( -2, "\t > impl_and3_miter : i/o = 4/ 1 lat = 0 and = 6 lev = 4\n"); + Abc_Print( -2, "\t > abc 09> &get; &qbf -P 3\n"); + Abc_Print( -2, "\t > The problem is UNSAT after 1 iterations. Time = 0.00 sec\n\n"); + Abc_Print( -2, "\t UNSAT here means that the ECO solution with the given rectification point *has* a solution.\n\n"); + Abc_Print( -2, "\t For more info, refer to Figure 1 in the following paper A. Q. Dao, N.-Z. Lee, L.-C. Chen, M. P.-H. Lin,\n"); + Abc_Print( -2, "\t J.-H. R. Jiang, A. Mishchenko, and R. Brayton, \"Efficient computation of ECO patch functions\", Proc. DAC'18.\n"); + Abc_Print( -2, "\t https://people.eecs.berkeley.edu/~alanmi/publications/2018/dac18_eco.pdf\n"); return 1; } @@ -52315,9 +53018,9 @@ usage: Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the AIG files for the instance modules\n"); Abc_Print( -2, "\t (the PO count of should not be less than the PI count of )\n"); - return 1;} + return 1; +} -extern Bnd_Man_t* pBnd; /**Function************************************************************* Synopsis [] @@ -52329,6 +53032,67 @@ extern Bnd_Man_t* pBnd; SeeAlso [] ***********************************************************************/ +int Abc_CommandAbc9PutOnTop( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_GenPutOnTop( char ** pFNames, int nFNames ); + Gia_Man_t * pMan = NULL; + int c, fVerbose = 0; + char ** pArgvNew; + int nArgcNew; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew < 1 ) + { + Abc_Print( -1, "Abc_CommandAbc9PutOnTop(): At least one AIG file should be given on the command line.\n" ); + return 0; + } + pMan = Gia_GenPutOnTop( pArgvNew, nArgcNew ); + if ( pMan == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9PutOnTop(): Computing the resulting AIS has failed.\n" ); + return 0; + } + Abc_FrameUpdateGia( pAbc, pMan ); + return 0; +usage: + Abc_Print( -2, "usage: &putontop [-vh] ... \n" ); + Abc_Print( -2, "\t generates an AIG by stacking several AIGs on top of each other\n" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the AIGER files containing the input AIGs\n"); + Abc_Print( -2, "\t the outputs of each AIG are connected to the inputs of the one on top of it\n" ); + Abc_Print( -2, "\t if there are more outputs than inputs, new POs will be created\n" ); + Abc_Print( -2, "\t if there are more inputs than outputs, new PIs are created\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +extern Bnd_Man_t* pBnd; + int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ); @@ -52567,7 +53331,6 @@ usage: SeeAlso [] ***********************************************************************/ - int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ); @@ -52672,6 +53435,811 @@ usage: return 1; } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9GenCex( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_GenerateCexes( char * pFileName, Gia_Man_t * p, int nMaxTries, int nMinCexes, int fUseSim, int fUseSat, int fShort, int fVerbose, int fVeryVerbose ); + char * pFileName = (char *)"cexes.txt"; + int nMinCexes = 1; + int nMaxTries = 10; + int fUseSim = 1; + int fUseSat = 1; + int fShort = 0; + int fVerbose = 0; + int c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CMFstcvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nMinCexes = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMinCexes < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nMaxTries = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMaxTries < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by a file name.\n" ); + goto usage; + } + pFileName = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 's': + fUseSim ^= 1; + break; + case 't': + fUseSat ^= 1; + break; + case 'c': + fShort ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Bmci(): There is no AIG.\n" ); + return 0; + } + Gia_GenerateCexes( pFileName, pAbc->pGia, nMaxTries, nMinCexes, fUseSim, fUseSat, fShort, fVerbose, 0 ); + return 0; + +usage: + Abc_Print( -2, "usage: &gencex [-CM num] [-F file] [-stcvh]\n" ); + Abc_Print( -2, "\t generates satisfying assignments for each output of the miter\n" ); + Abc_Print( -2, "\t-C num : the number of timeframes [default = %d]\n", nMinCexes ); + Abc_Print( -2, "\t-M num : the max simulation runs before using SAT [default = %d]\n", nMaxTries ); + Abc_Print( -2, "\t-F file : the output file name [default = %s]\n", pFileName ); + Abc_Print( -2, "\t-s : toggles using reverse simulation [default = %d]\n", fUseSim ? "yes": "no" ); + Abc_Print( -2, "\t-t : toggles using SAT solving [default = %d]\n", fUseSat ? "yes": "no" ); + Abc_Print( -2, "\t-c : toggles outputing care literals only [default = %d]\n", fShort ? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %d]\n", fVerbose ? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Odc( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManDupOdc( Gia_Man_t * p, int iObj, int fVerbose ); + Gia_Man_t * pTemp; + int c, iNode = -1, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + iNode = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( iNode < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Odc(): There is no AIG.\n" ); + return 0; + } + if ( !Gia_ObjIsAnd( Gia_ManObj(pAbc->pGia, iNode) ) ) + { + Abc_Print( -1, "Abc_CommandAbc9Odc(): Object with ID %d is not an internal node.\n", iNode ); + return 0; + } + pTemp = Gia_ManDupOdc( pAbc->pGia, iNode, fVerbose ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &odc [-N num] [-vh]\n" ); + Abc_Print( -2, "\t generates the complement of the ODC for the node\n" ); + Abc_Print( -2, "\t-N num : the node ID [default = undefined]\n" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %d]\n", fVerbose ? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9GenRel( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManGenRel( Gia_Man_t * pGia, Vec_Int_t * vInsOuts, int nIns, char * pFileName, int fVerbose ); + Vec_Int_t * vInsOuts = NULL; char * pIns = NULL, * pOuts = NULL; + int c, nIns = -1, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IOvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + pIns = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'O': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); + goto usage; + } + pOuts = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9GenRel(): There is no AIG.\n" ); + return 0; + } + if ( argc != globalUtilOptind+1 ) + { + Abc_Print( -1, "Abc_CommandAbc9GenRel(): The output file name should be given as the last entry on the command line.\n" ); + return 0; + } + if ( pIns == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9GenRel(): A comma-separated list of window input node IDs should be given as \"-I list\" on the command line.\n" ); + return 0; + } + if ( pOuts == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9GenRel(): A comma-separated list of window output node IDs should be given as \"-O list\" on the command line.\n" ); + return 0; + } + vInsOuts = Vec_IntAlloc( 16 ); + Vec_IntPush( vInsOuts, atoi(pIns) ); + for ( c = 0; pIns[c]; c++ ) + if ( pIns[c] == ',' ) + Vec_IntPush( vInsOuts, atoi(pIns+c+1) ); + nIns = Vec_IntSize(vInsOuts); + Vec_IntPush( vInsOuts, atoi(pOuts) ); + for ( c = 0; pOuts[c]; c++ ) + if ( pOuts[c] == ',' ) + Vec_IntPush( vInsOuts, atoi(pOuts+c+1) ); + if ( fVerbose ) { + printf( "Deriving relation for %d inputs and %d outputs: ", nIns, Vec_IntSize(vInsOuts)-nIns ); + Vec_IntPrint( vInsOuts ); + } + Gia_ManGenRel( pAbc->pGia, vInsOuts, nIns, argv[globalUtilOptind], fVerbose ); + Vec_IntFree( vInsOuts ); + return 0; + +usage: + Abc_Print( -2, "usage: &genrel [-I n1,n2,...nN] [-O m1,m2,...,mM] [-vh] \n" ); + Abc_Print( -2, "\t generates Boolean relation for the given logic window\n" ); + Abc_Print( -2, "\t-I list : comma-separated list of window inputs [default = undefined]\n" ); + Abc_Print( -2, "\t-O list : comma-separated list of window outputs [default = undefined]\n" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %d]\n", fVerbose ? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the output file name (PLA format extended to represented Boolean relations)\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9GenMux( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManGenMux( int nIns, char * pNums ); + Gia_Man_t * pTemp = NULL; + int c, nIns = 0, fVerbose = 0; + char * pNums = NULL; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Kvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nIns = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIns < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc == globalUtilOptind && nIns > 0 ) + { + if ( nIns == 2 ) + pNums = "11"; + else if ( nIns == 3 ) + pNums = "111"; + else if ( nIns == 4 ) + pNums = "112"; + else if ( nIns == 5 ) + pNums = "113"; + else if ( nIns == 6 ) + pNums = "123"; + else if ( nIns == 7 ) + pNums = "1123"; + else if ( nIns == 8 ) + pNums = "1124"; + else if ( nIns == 9 ) + pNums = "1134"; + else if ( nIns == 10 ) + pNums = "1135"; + else if ( nIns == 11 ) + pNums = "1235"; + else if ( nIns == 12 ) + pNums = "1245"; + else if ( nIns == 13 ) + pNums = "1246"; + else if ( nIns == 14 ) + pNums = "1247"; + else if ( nIns == 15 ) + pNums = "1248"; + else if ( nIns == 16 ) + pNums = "1348"; + else + { + Abc_Print( -1, "Abc_CommandAbc9GenMux(): The number of controls should not be in the range: 2 <= n <= 16.\n" ); + return 0; + } + } + else if ( argc == globalUtilOptind+1 ) + { + int nIns2 = 0; + pNums = argv[globalUtilOptind]; + for ( c = 0; pNums[c]; c++ ) + nIns2 += (int)(pNums[c] - '0'); + if ( nIns > 0 && nIns2 > 0 && nIns != nIns2 ) + { + Abc_Print( -1, "Abc_CommandAbc9GenMux(): The number of inputs does not match.\n" ); + return 0; + } + nIns = nIns2; + } + else + { + Abc_Print( -1, "Abc_CommandAbc9GenMux(): The number of controls or the control input groups should be given on the command line.\n" ); + return 0; + } + pTemp = Gia_ManGenMux( nIns, pNums ); + Abc_FrameUpdateGia( pAbc, pTemp ); + Abc_Print( 1, "Generated a %d:1 MUX with the following groups: %s\n", 1<] [-vh] \n" ); + Abc_Print( -2, "\t generates the multiplexer\n" ); + Abc_Print( -2, "\t-K num : the number of control inputs [default = undefined]\n" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose ? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\tstring : the sizes of control input groups\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Window( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManDupWindow( Gia_Man_t * p, Vec_Int_t * vCut ); + Gia_Man_t * pNew = NULL; + Vec_Int_t * vCut = NULL; + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Window(): There is no AIG.\n" ); + return 0; + } + if ( argc == globalUtilOptind ) + { + int nCutSize = 6, nCuts = 30; + extern void Gia_ManExploreCutsTest( Gia_Man_t * pGia, int nCutSize, int nCuts, int fVerbose ); + printf( "Here are %d the most frequently appearing %d-cuts:\n", nCutSize, nCuts ); + Gia_ManExploreCutsTest( pAbc->pGia, nCutSize, nCuts, fVerbose ); + return 0; + } + if ( argc-globalUtilOptind < 1 ) + { + Abc_Print( -1, "Abc_CommandAbc9Window(): The window should have at least one support variable.\n" ); + return 0; + } + vCut = Vec_IntAlloc( 100 ); + for ( c = globalUtilOptind; c < argc; c++ ) + Vec_IntPush( vCut, atoi(argv[c]) ); + pNew = Gia_ManDupWindow( pAbc->pGia, vCut ); + Abc_FrameUpdateGia( pAbc, pNew ); + Vec_IntFree( vCut ); + return 0; + +usage: + Abc_Print( -2, "usage: &window [-vh] ... \n" ); + Abc_Print( -2, "\t generates a logic window supported by the given nodes\n" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose ? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the list of window inputs\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9FunAbs( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManDupEncode( Gia_Man_t * p, Vec_Int_t * vVarNums, int fVerbose ); + extern Vec_Int_t * Gia_ManCofClassPattern( Gia_Man_t * p, Vec_Int_t * vVarNums, int fVerbose ); + extern void Gia_ManCofClassRand( Gia_Man_t * p, int nVars, int nRands ); + extern void Gia_ManCofClassEnum( Gia_Man_t * p, int nVars ); + Gia_Man_t * pNew = NULL; + Vec_Int_t * vVars = NULL; + int c, nVars = 6, nRands = 0, fEnum = 0, fPrint = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KRepvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 0 ) + goto usage; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nRands = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nRands < 0 ) + goto usage; + break; + case 'e': + fEnum ^= 1; + break; + case 'p': + fPrint ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9FunAbs(): There is no AIG.\n" ); + return 0; + } + if ( Gia_ManPoNum(pAbc->pGia) != 1 || Gia_ManRegNum(pAbc->pGia) != 0 ) { + Abc_Print( -1, "Abc_CommandAbc9FunAbs(): Works only for comb AIGs with one output.\n" ); + return 0; + } + if ( nVars >= Gia_ManPiNum(pAbc->pGia) ) { + Abc_Print( -1, "Abc_CommandAbc9FunAbs(): The number of variables (%d) should be less the PI count (%d).\n", nVars, Gia_ManPiNum(pAbc->pGia) ); + return 0; + } + if ( nRands ) { + Gia_ManCofClassRand( pAbc->pGia, nVars, nRands ); + return 0; + } + if ( fEnum ) { + Gia_ManCofClassEnum( pAbc->pGia, nVars ); + return 0; + } + if ( argc == globalUtilOptind ) { + vVars = Vec_IntStartNatural( nVars ); + printf( "Abstracting the first %d variables of the AIG.\n", nVars ); + } + else { + vVars = Vec_IntAlloc( argc ); + for ( c = globalUtilOptind; c < argc; c++ ) + Vec_IntPush( vVars, atoi(argv[c]) ); + printf( "Abstracting variables: " ); + Vec_IntPrint( vVars ); + } + if ( fPrint ) { + Vec_Int_t * vTemp = Gia_ManCofClassPattern( pAbc->pGia, vVars, 1 ); + Vec_IntFree( vTemp ); + } + else { + pNew = Gia_ManDupEncode( pAbc->pGia, vVars, fVerbose ); + Abc_FrameUpdateGia( pAbc, pNew ); + } + Vec_IntFree( vVars ); + return 0; + +usage: + Abc_Print( -2, "usage: &funabs [-KR num] [-epvh] ... \n" ); + Abc_Print( -2, "\t generates an abstraction of the function\n" ); + Abc_Print( -2, "\t-K num : the number of primary inputs [default = %d]\n", nVars ); + Abc_Print( -2, "\t-R num : the number of random K-set to try [default = %d]\n", nRands ); + Abc_Print( -2, "\t-e : toggles enumerating bound sets of the given size [default = %s]\n", fEnum ? "yes": "no" ); + Abc_Print( -2, "\t-p : toggles printing statistics only [default = %s]\n", fPrint ? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose ? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the index list of primary inputs to be abstrated\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9DsdInfo( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManPrintDsdMatrix( Gia_Man_t * p, int iIn ); + extern void Gia_ManCheckDsd( Gia_Man_t * p, int OffSet, int fVerbose ); + int c, iIn = -1, fDsd = 0, fAll = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Vdavh" ) ) != EOF ) + { + switch ( c ) + { + case 'V': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-V\" should be followed by an integer.\n" ); + goto usage; + } + iIn = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( iIn < 0 ) + goto usage; + break; + case 'd': + fDsd ^= 1; + break; + case 'a': + fAll ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9DsdInfo(): There is no AIG.\n" ); + return 0; + } + if ( fDsd ) + { + if ( iIn == -1 ) { + Gia_ManCheckDsd( pAbc->pGia, 0, 1 ); + if ( fAll ) { + for ( iIn = 0; iIn < Gia_ManPiNum(pAbc->pGia); iIn++ ) + for ( c = 0; c < 2; c++ ) { + Gia_Man_t * pTemp = Gia_ManDupCofactorVar( pAbc->pGia, iIn, c ); + printf( "%s %2d = %d:\n", c ? " " : "Var", iIn, c ); + Gia_ManCheckDsd( pTemp, 12, 1 ); + Gia_ManStop( pTemp ); + } + } + return 0; + } + for ( c = 0; c < 2; c++ ) { + Gia_Man_t * pTemp = Gia_ManDupCofactorVar( pAbc->pGia, iIn, c ); + printf( "Var %2d Cof %d:\n", iIn, c ); + Gia_ManCheckDsd( pTemp, 0, 1 ); + if ( fAll ) { + for ( int iIn = 0; iIn < Gia_ManPiNum(pAbc->pGia); iIn++ ) + for ( int c = 0; c < 2; c++ ) { + Gia_Man_t * pTemp2 = Gia_ManDupCofactorVar( pTemp, iIn, c ); + printf( "%s %2d = %d:\n", c ? " " : "Var", iIn, c ); + Gia_ManCheckDsd( pTemp2, 12, 1 ); + Gia_ManStop( pTemp2 ); + } + } + Gia_ManStop( pTemp ); + } + return 0; + } + if ( iIn < 0 || iIn >= Gia_ManPiNum(pAbc->pGia) ) + { + Abc_Print( -1, "Abc_CommandAbc9DsdInfo(): The input variable is not specified.\n" ); + return 0; + } + Gia_ManPrintDsdMatrix( pAbc->pGia, iIn ); + return 0; + +usage: + Abc_Print( -2, "usage: &dsdinfo [-V num] [-dvh]\n" ); + Abc_Print( -2, "\t computes and displays information related to DSD\n" ); + Abc_Print( -2, "\t-V num : the zero-based index of the input variable [default = %d]\n", iIn ); + Abc_Print( -2, "\t-d : toggles showing DSD structure [default = %s]\n", fDsd ? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose ? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9FunTrace( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Vec_Mem_t * Dau_CollectNpnFunctions( word * p, int nVars, int fVerbose ); + extern void Gia_ManMatchCuts( Vec_Mem_t * vTtMem, Gia_Man_t * pGia, int nCutSize, int nCutNum, int fVerbose ); + int c, nVars, nVars2, nCutNum = 8, fVerbose = 0; word * pTruth = NULL; + char * pStr = NULL; Vec_Mem_t * vTtMem = NULL; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Cvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCutNum = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutNum < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9FunTrace(): There is no AIG.\n" ); + return 0; + } + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( -1, "Abc_CommandAbc9FunTrace(): Truth table in hex notation should be given on the command line.\n" ); + return 0; + } + pStr = argv[globalUtilOptind]; + if ( pStr[0] == '0' && pStr[1] == 'x' ) + pStr += 2; + nVars = Abc_Base2Log(strlen(pStr)*4); + if ( (1 << nVars) != strlen(pStr)*4 ) + { + Abc_Print( -1, "Abc_CommandAbc9FunTrace(): String \"%s\" does not look like a truth table of a %d-var function.\n", pStr, nVars ); + return 0; + } + pTruth = ABC_CALLOC( word, Abc_Truth6WordNum(nVars+1) ); + nVars2 = Abc_TtReadHex( pTruth, pStr ); + if ( nVars != nVars2 ) + { + ABC_FREE( pTruth ); + Abc_Print( -1, "Abc_CommandAbc9FunTrace(): String \"%s\" does not look like a truth table of a %d-var function.\n", pStr, nVars ); + return 0; + } + //Abc_TtPrintHexRev( stdout, pTruth, nVars ); printf( "\n" ); + vTtMem = Dau_CollectNpnFunctions( pTruth, nVars, fVerbose ); + Gia_ManMatchCuts( vTtMem, pAbc->pGia, nVars, nCutNum, fVerbose ); + Vec_MemHashFree( vTtMem ); + Vec_MemFree( vTtMem ); + return 0; + +usage: + Abc_Print( -2, "usage: &funtrace [-C num] [-vh] \n" ); + Abc_Print( -2, "\t traces the presence of the function in the current AIG\n" ); + Abc_Print( -2, "\t-C num : the number of cuts to compute at each node [default = %d]\n", nCutNum ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose ? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : truth table in the hexadecimal notation\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9MulFind( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManMulFind( Gia_Man_t * p, int nCutNum, int fVerbose ); + int c, nCutNum = 8, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Cvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCutNum = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutNum < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9MulFind(): There is no AIG.\n" ); + return 0; + } + Gia_ManMulFind( pAbc->pGia, nCutNum, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: &mulfind [-C num] [-vh]\n" ); + Abc_Print( -2, "\t detects multipliers in the given AIG\n" ); + Abc_Print( -2, "\t-C num : the number of cuts to compute at each node [default = %d]\n", nCutNum ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose ? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + /**Function************************************************************* Synopsis [] @@ -52758,7 +54326,7 @@ int Abc_CommandAbc9Test( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_ManStop( pTemp ); return 0; } - Abc_FrameUpdateGia( pAbc, Gia_ManPerformNewResub(pAbc->pGia, 100, 6, 1, 1) ); + //Abc_FrameUpdateGia( pAbc, pNew ); // printf( "AIG in \"%s\" has the sum of output support sizes equal to %d.\n", pAbc->pGia->pSpec, Gia_ManSumTotalOfSupportSizes(pAbc->pGia) ); return 0; usage: diff --git a/src/base/abci/abcCas.c b/src/base/abci/abcCas.c index 6615bff0a..b81d813d6 100644 --- a/src/base/abci/abcCas.c +++ b/src/base/abci/abcCas.c @@ -19,9 +19,12 @@ ***********************************************************************/ #include "base/abc/abc.h" +#include "bool/kit/kit.h" +#include "aig/miniaig/miniaig.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" +#include "bdd/extrab/extraLutCas.h" #endif ABC_NAMESPACE_IMPL_START @@ -116,9 +119,153 @@ Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVer #else Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose ) { return NULL; } +word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int fVerbose ) { return NULL; } #endif + +/* + The decomposed structure of the LUT cascade is represented as an array of 64-bit integers (words). + The first word in the record is the number of LUT info blocks in the record, which follow one by one. + Each LUT info block contains the following: + - the number of words in this block + - the number of fanins + - the list of fanins + - the variable ID of the output (can be one of the fanin variables) + - truth tables (one word for 6 vars or less; more words as needed for more than 6 vars) + For a 6-input node, the LUT info block takes 10 words (block size, fanin count, 6 fanins, output ID, truth table). + For a 4-input node, the LUT info block takes 8 words (block size, fanin count, 4 fanins, output ID, truth table). + If the LUT cascade contains a 6-LUT followed by a 4-LUT, the record contains 1+10+8=19 words. +*/ + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word * Abc_LutCascadeGenTest() +{ + word * pLuts = ABC_CALLOC( word, 20 ); int i; + // node count + pLuts[0] = 2; + // first node + pLuts[1+0] = 10; + pLuts[1+1] = 6; + for ( i = 0; i < 6; i++ ) + pLuts[1+2+i] = i; + pLuts[1+8] = 0; + pLuts[1+9] = ABC_CONST(0x8000000000000000); + // second node + pLuts[11+0] = 8; + pLuts[11+1] = 4; + for ( i = 0; i < 4; i++ ) + pLuts[11+2+i] = i ? i + 5 : 0; + pLuts[11+6] = 1; + pLuts[11+7] = ABC_CONST(0xFFFEFFFEFFFEFFFE); + return pLuts; +} +void Abc_LutCascadePrint( word * pLuts ) +{ + int n, i, k; + printf( "Single-rail LUT cascade has %d nodes:\n", (int)pLuts[0] ); + for ( n = 0, i = 1; n < pLuts[0]; n++, i += pLuts[i] ) + { + word nIns = pLuts[i+1]; + word * pIns = pLuts+i+2; + word * pT = pLuts+i+2+nIns+1; + printf( "LUT%d : ", n ); + printf( "%02d = F( ", (int)pIns[nIns] ); + for ( k = 0; k < nIns; k++ ) + printf( "%02d ", (int)pIns[k] ); + for ( ; k < 8; k++ ) + printf( " " ); + printf( ") " ); + Extra_PrintHex2( stdout, (unsigned *)pT, nIns ); + printf( "\n" ); + } +} +word * Abc_LutCascadeTest( Mini_Aig_t * p, int nLutSize, int fVerbose ) +{ + word * pLuts = Abc_LutCascadeGenTest(); + Abc_LutCascadePrint( pLuts ); + return pLuts; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkLutCascadeDeriveSop( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeNew, word * pT, int nIns, Vec_Int_t * vCover ) +{ + int RetValue = Kit_TruthIsop( (unsigned *)pT, nIns, vCover, 1 ); + assert( RetValue == 0 || RetValue == 1 ); + if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) ) { + assert( RetValue == 0 ); + pNodeNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, nIns, NULL ); + return (Vec_IntSize(vCover) == 0) ? Abc_NtkCreateNodeConst0(pNtkNew) : Abc_NtkCreateNodeConst1(pNtkNew); + } + else { + char * pSop = Abc_SopCreateFromIsop( (Mem_Flex_t *)pNtkNew->pManFunc, nIns, vCover ); + if ( RetValue ) Abc_SopComplement( (char *)pSop ); + pNodeNew->pData = pSop; + return pNodeNew; + } +} +Abc_Ntk_t * Abc_NtkLutCascadeFromLuts( word * pLuts, Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ) +{ + Abc_Ntk_t * pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + Vec_Int_t * vCover = Vec_IntAlloc( 1000 ); word n, i, k, iLastLut = -1; + assert( Abc_NtkCoNum(pNtk) == 1 ); + for ( n = 0, i = 1; n < pLuts[0]; n++, i += pLuts[i] ) + { + word nIns = pLuts[i+1]; + word * pIns = pLuts+i+2; + word * pT = pLuts+i+2+nIns+1; + Abc_Obj_t * pNodeNew = Abc_NtkCreateNode( pNtkNew ); + for ( k = 0; k < nIns; k++ ) + Abc_ObjAddFanin( pNodeNew, Abc_NtkCi(pNtk, pIns[k])->pCopy ); + Abc_NtkCi(pNtk, pIns[nIns])->pCopy = Abc_NtkLutCascadeDeriveSop( pNtkNew, pNodeNew, pT, nIns, vCover ); + iLastLut = pIns[nIns]; + } + Vec_IntFree( vCover ); + Abc_ObjAddFanin( Abc_NtkCo(pNtk, 0)->pCopy, Abc_NtkCi(pNtk, iLastLut)->pCopy ); + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkLutCascadeFromLuts: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} +Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ) +{ + extern Gia_Man_t * Abc_NtkStrashToGia( Abc_Ntk_t * pNtk ); + extern Mini_Aig_t * Gia_ManToMiniAig( Gia_Man_t * pGia ); + extern word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int fVerbose ); + Gia_Man_t * pGia = Abc_NtkStrashToGia( pNtk ); + Mini_Aig_t * pM = Gia_ManToMiniAig( pGia ); + word * pLuts = Abc_LutCascade( pM, nLutSize, fVerbose ); + Abc_Ntk_t * pNew = pLuts ? Abc_NtkLutCascadeFromLuts( pLuts, pNtk, nLutSize, fVerbose ) : NULL; + ABC_FREE( pLuts ); + Mini_AigStop( pM ); + Gia_ManStop( pGia ); + return pNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abcDsd.c b/src/base/abci/abcDsd.c index 27d86ae89..6820f1806 100644 --- a/src/base/abci/abcDsd.c +++ b/src/base/abci/abcDsd.c @@ -143,7 +143,7 @@ Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, int fVerbose, int fPrint, int ppNamesCi = Abc_NtkCollectCioNames( pNtk, 0 ); ppNamesCo = Abc_NtkCollectCioNames( pNtk, 1 ); if ( fVerbose ) - Dsd_TreePrint( stdout, pManDsd, ppNamesCi, ppNamesCo, fShort, -1 ); + Dsd_TreePrint( stdout, pManDsd, ppNamesCi, ppNamesCo, fShort, -1, 0 ); else Dsd_TreePrint2( stdout, pManDsd, ppNamesCi, ppNamesCo, -1 ); ABC_FREE( ppNamesCi ); diff --git a/src/base/abci/abcGen.c b/src/base/abci/abcGen.c index 7ffa90625..4441db166 100644 --- a/src/base/abci/abcGen.c +++ b/src/base/abci/abcGen.c @@ -42,6 +42,32 @@ ABC_NAMESPACE_IMPL_START SeeAlso [] ***********************************************************************/ +void Abc_WriteHalfAdder( FILE * pFile ) +{ + int fNaive = 0; + fprintf( pFile, ".model HA\n" ); + fprintf( pFile, ".inputs a b\n" ); + fprintf( pFile, ".outputs s cout\n" ); + if ( fNaive ) + { + fprintf( pFile, ".names a b s\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".names a b cout\n" ); + fprintf( pFile, "11 1\n" ); + } + else + { + fprintf( pFile, ".names a b cout\n" ); + fprintf( pFile, "11 1\n" ); + fprintf( pFile, ".names a b and1_\n" ); + fprintf( pFile, "00 1\n" ); + fprintf( pFile, ".names cout and1_ s\n" ); + fprintf( pFile, "00 1\n" ); + } + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); +} void Abc_WriteFullAdder( FILE * pFile ) { int fNaive = 0; @@ -50,6 +76,7 @@ void Abc_WriteFullAdder( FILE * pFile ) fprintf( pFile, ".outputs s cout\n" ); if ( fNaive ) { +/* fprintf( pFile, ".names a b k\n" ); fprintf( pFile, "10 1\n" ); fprintf( pFile, "01 1\n" ); @@ -60,6 +87,19 @@ void Abc_WriteFullAdder( FILE * pFile ) fprintf( pFile, "11- 1\n" ); fprintf( pFile, "1-1 1\n" ); fprintf( pFile, "-11 1\n" ); +*/ + fprintf( pFile, ".names a b s0\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".names a b c0\n" ); + fprintf( pFile, "11 1\n" ); + fprintf( pFile, ".names s0 cin s\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".names s0 cin c1\n" ); + fprintf( pFile, "11 1\n" ); + fprintf( pFile, ".names c0 c1 cout\n" ); + fprintf( pFile, "00 0\n" ); } else { @@ -1205,6 +1245,679 @@ void Abc_GenGraph( char * pFileName, int nPis ) ABC_FREE( pTruth ); } +/**Function************************************************************* + + Synopsis [Threshold function generation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_GenComp63a4( FILE * pFile ) +{ + fprintf( pFile, ".model C63a\n" ); + fprintf( pFile, ".inputs x0 x1 x2 x3 x4 x5\n" ); + fprintf( pFile, ".outputs z0 z1 z2\n" ); + fprintf( pFile, ".names x1 x2 x3 x0 n10\n" ); + fprintf( pFile, "--00 1\n" ); + fprintf( pFile, "-0-0 1\n" ); + fprintf( pFile, "0--0 1\n" ); + fprintf( pFile, "000- 1\n" ); + fprintf( pFile, ".names x4 x5 n13 n10 z0\n" ); + fprintf( pFile, "--00 1\n" ); + fprintf( pFile, "-1-0 1\n" ); + fprintf( pFile, "1--0 1\n" ); + fprintf( pFile, "111- 1\n" ); + fprintf( pFile, ".names x1 x2 x3 x0 n13\n" ); + fprintf( pFile, "-110 1\n" ); + fprintf( pFile, "1-10 1\n" ); + fprintf( pFile, "11-0 1\n" ); + fprintf( pFile, "-001 1\n" ); + fprintf( pFile, "0-01 1\n" ); + fprintf( pFile, "00-1 1\n" ); + fprintf( pFile, ".names x4 x5 n13 n16 z1\n" ); + fprintf( pFile, "1-00 1\n" ); + fprintf( pFile, "0-10 1\n" ); + fprintf( pFile, "-101 1\n" ); + fprintf( pFile, "-011 1\n" ); + fprintf( pFile, ".names x1 x2 x3 x4 n16\n" ); + fprintf( pFile, "1000 1\n" ); + fprintf( pFile, "0100 1\n" ); + fprintf( pFile, "0010 1\n" ); + fprintf( pFile, "1110 1\n" ); + fprintf( pFile, "0001 1\n" ); + fprintf( pFile, "1101 1\n" ); + fprintf( pFile, "1011 1\n" ); + fprintf( pFile, "0111 1\n" ); + fprintf( pFile, ".names x5 n16 z2\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".end\n\n" ); +} +void Abc_GenComp63a6( FILE * pFile ) +{ + fprintf( pFile, ".model C63a\n" ); + fprintf( pFile, ".inputs x0 x1 x2 x3 x4 x5\n" ); + fprintf( pFile, ".outputs z0 z1 z2\n" ); + fprintf( pFile, ".names x1 x2 x3 x4 x5 x0 z0\n" ); + fprintf( pFile, "---111 1\n" ); + fprintf( pFile, "--1-11 1\n" ); + fprintf( pFile, "--11-1 1\n" ); + fprintf( pFile, "-1--11 1\n" ); + fprintf( pFile, "-1-1-1 1\n" ); + fprintf( pFile, "-11--1 1\n" ); + fprintf( pFile, "-1111- 1\n" ); + fprintf( pFile, "1---11 1\n" ); + fprintf( pFile, "1--1-1 1\n" ); + fprintf( pFile, "1-1--1 1\n" ); + fprintf( pFile, "1-111- 1\n" ); + fprintf( pFile, "11---1 1\n" ); + fprintf( pFile, "11-11- 1\n" ); + fprintf( pFile, "111-1- 1\n" ); + fprintf( pFile, "1111-- 1\n" ); + fprintf( pFile, ".names x1 x2 x3 x4 x5 x0 z1\n" ); + fprintf( pFile, "-00001 1\n" ); + fprintf( pFile, "-00110 1\n" ); + fprintf( pFile, "-01010 1\n" ); + fprintf( pFile, "-01100 1\n" ); + fprintf( pFile, "-10010 1\n" ); + fprintf( pFile, "-10100 1\n" ); + fprintf( pFile, "-11000 1\n" ); + fprintf( pFile, "-11111 1\n" ); + fprintf( pFile, "0-0001 1\n" ); + fprintf( pFile, "0-0110 1\n" ); + fprintf( pFile, "0-1010 1\n" ); + fprintf( pFile, "0-1100 1\n" ); + fprintf( pFile, "00-001 1\n" ); + fprintf( pFile, "00-110 1\n" ); + fprintf( pFile, "000-01 1\n" ); + fprintf( pFile, "0000-1 1\n" ); + fprintf( pFile, "1-0010 1\n" ); + fprintf( pFile, "1-0100 1\n" ); + fprintf( pFile, "1-1000 1\n" ); + fprintf( pFile, "1-1111 1\n" ); + fprintf( pFile, "11-000 1\n" ); + fprintf( pFile, "11-111 1\n" ); + fprintf( pFile, "111-11 1\n" ); + fprintf( pFile, "1111-1 1\n" ); + fprintf( pFile, ".names x1 x2 x3 x4 x5 z2\n" ); + fprintf( pFile, "00001 1\n" ); + fprintf( pFile, "00010 1\n" ); + fprintf( pFile, "00100 1\n" ); + fprintf( pFile, "00111 1\n" ); + fprintf( pFile, "01000 1\n" ); + fprintf( pFile, "01011 1\n" ); + fprintf( pFile, "01101 1\n" ); + fprintf( pFile, "01110 1\n" ); + fprintf( pFile, "10000 1\n" ); + fprintf( pFile, "10011 1\n" ); + fprintf( pFile, "10101 1\n" ); + fprintf( pFile, "10110 1\n" ); + fprintf( pFile, "11001 1\n" ); + fprintf( pFile, "11010 1\n" ); + fprintf( pFile, "11100 1\n" ); + fprintf( pFile, "11111 1\n" ); + fprintf( pFile, ".end\n\n" ); +} +void Abc_GenAdder4( FILE * pFile, int nBits, int nLutSize ) +{ + int i, n; + fprintf( pFile, ".model A%02d_4x\n", nBits ); + for ( n = 0; n < 4; n++ ) { + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nBits; i++ ) + fprintf( pFile, " %c%02d", 'a'+n, i ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, ".outputs" ); + for ( i = 0; i < nBits; i++ ) + fprintf( pFile, " s%02d", i ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".names v00\n" ); + fprintf( pFile, ".names w00\n" ); + for ( i = 0; i < nBits; i++ ) { + fprintf( pFile, ".subckt C63a" ); + fprintf( pFile, " x0=w%02d", i ); + fprintf( pFile, " x1=v%02d", i ); + fprintf( pFile, " x2=a%02d", i ); + fprintf( pFile, " x3=b%02d", i ); + fprintf( pFile, " x4=c%02d", i ); + fprintf( pFile, " x5=d%02d", i ); + fprintf( pFile, " z0=w%02d", i+1 ); + fprintf( pFile, " z1=v%02d", i+1 ); + fprintf( pFile, " z2=s%02d", i ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, ".end\n\n" ); + if ( nLutSize == 4 ) + Abc_GenComp63a4( pFile ); + else if ( nLutSize == 6 ) + Abc_GenComp63a6( pFile ); + else assert( 0 ); +} +void Abc_WriteAdder2( FILE * pFile, int nVars ) +{ + int i; + assert( nVars > 0 ); + fprintf( pFile, ".model A%02d\n", nVars ); + fprintf( pFile, ".inputs c\n" ); + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " a%02d", i ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " b%02d", i ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".outputs" ); + for ( i = 0; i <= nVars; i++ ) + fprintf( pFile, " s%02d", i ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".names c t00\n1 1\n" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, ".subckt FA a=a%02d b=b%02d cin=t%02d s=s%02d cout=t%02d\n", i, i, i, i, i+1 ); + fprintf( pFile, ".names t%02d s%02d\n1 1\n", nVars, nVars ); + fprintf( pFile, ".end\n\n" ); + Abc_WriteFullAdder( pFile ); +} +void Abc_GenAdder4test( FILE * pFile, int nBits ) +{ + int i, n; + fprintf( pFile, ".model A%02d_4x\n", nBits ); + for ( n = 0; n < 4; n++ ) { + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nBits; i++ ) + fprintf( pFile, " %c%02d", 'a'+n, i ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, ".outputs" ); + for ( i = 0; i < nBits; i++ ) + fprintf( pFile, " o%02d", i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".names zero\n" ); + fprintf( pFile, ".subckt A%02d c=zero", nBits ); + fprintf( pFile, " \\\n" ); + for ( i = 0; i < nBits; i++ ) + fprintf( pFile, " a%0d=a%02d", i, i ); + fprintf( pFile, " \\\n" ); + for ( i = 0; i < nBits; i++ ) + fprintf( pFile, " b%0d=b%02d", i, i ); + fprintf( pFile, " \\\n" ); + for ( i = 0; i <= nBits; i++ ) + fprintf( pFile, " s%0d=t%02d", i, i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".subckt A%02d c=zero", nBits ); + fprintf( pFile, " \\\n" ); + for ( i = 0; i < nBits; i++ ) + fprintf( pFile, " a%0d=c%02d", i, i ); + fprintf( pFile, " \\\n" ); + for ( i = 0; i < nBits; i++ ) + fprintf( pFile, " b%0d=t%02d", i, i ); + fprintf( pFile, " \\\n" ); + for ( i = 0; i <= nBits; i++ ) + fprintf( pFile, " s%0d=u%02d", i, i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".subckt A%02d c=zero", nBits ); + fprintf( pFile, " \\\n" ); + for ( i = 0; i < nBits; i++ ) + fprintf( pFile, " a%0d=d%02d", i, i ); + fprintf( pFile, " \\\n" ); + for ( i = 0; i < nBits; i++ ) + fprintf( pFile, " b%0d=u%02d", i, i ); + fprintf( pFile, " \\\n" ); + for ( i = 0; i <= nBits; i++ ) + fprintf( pFile, " s%0d=o%02d", i, i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".end\n\n" ); + Abc_WriteAdder( pFile, nBits ); +} +void Abc_WriteWeight( FILE * pFile, int Num, int nBits, int Weight ) +{ + int i; + fprintf( pFile, ".model W%02d\n", Num ); + fprintf( pFile, ".inputs i\n" ); + fprintf( pFile, ".outputs" ); + for ( i = 0; i < nBits; i++ ) + fprintf( pFile, " o%02d", i ); + fprintf( pFile, "\n" ); + for ( i = 0; i < nBits; i++ ) + if ( (Weight >> i) & 1 ) + fprintf( pFile, ".names i o%02d\n1 1\n", i ); + else + fprintf( pFile, ".names o%02d\n", i ); + fprintf( pFile, ".end\n\n" ); +} + +Vec_Int_t * Abc_GenTreeFindGroups( char * pTree, int iPos ) +{ + Vec_Int_t * vRes = NULL; + int Counter = 1; + assert( pTree[iPos] == '(' ); + while ( pTree[++iPos] ) { + if ( pTree[iPos] == '(' ) { + if ( Counter++ == 1 ) { + if ( vRes == NULL ) + vRes = Vec_IntAlloc( 4 ); + Vec_IntPush( vRes, iPos ); + } + } + if ( pTree[iPos] == ')' ) + Counter--; + if ( Counter == 0 ) + return vRes; + } + assert( 0 ); + return NULL; +} +int Abc_GenTree_rec( FILE * pFile, int nBits, char * pTree, int iPos, int * pSig, int * pUsed ) +{ + Vec_Int_t * vGroups = Abc_GenTreeFindGroups( pTree, iPos ); + if ( vGroups == NULL ) + return atoi(pTree+iPos+1); + int i, g, Group; + Vec_IntForEachEntry( vGroups, Group, g ) { + Group = Abc_GenTree_rec( pFile, nBits, pTree, Group, pSig, pUsed ); + Vec_IntWriteEntry( vGroups, g, Group ); + } + if ( Vec_IntSize(vGroups) == 3 ) + Vec_IntPush(vGroups, 0); + if ( Vec_IntSize(vGroups) == 4 ) + fprintf( pFile, ".subckt A%02d_4x", nBits ), *pUsed = 1; + else if ( Vec_IntSize(vGroups) == 2 ) + fprintf( pFile, ".subckt A%02d c=zero", nBits ); + else assert( 0 ); + Vec_IntForEachEntry( vGroups, Group, g ) { + fprintf( pFile, " \\\n" ); + for ( i = 0; i < nBits; i++ ) + fprintf( pFile, " %c%02d=%02d_%02d", 'a'+g, i, Group, i ); + } + fprintf( pFile, " \\\n" ); + for ( i = 0; i < nBits; i++ ) + fprintf( pFile, " s%02d=%02d_%02d", i, *pSig, i ); + fprintf( pFile, "\n\n" ); + return (*pSig)++; +} +void Abc_GenThreshAdder( FILE * pFile, int nBits, int A, int B, int S, int fOne ) +{ + if ( A > B ) ABC_SWAP( int, A, B ); int i; + fprintf( pFile, ".subckt A%02d c=%s", nBits, fOne ? "one" : "zero" ); + fprintf( pFile, " \\\n" ); + for ( i = 0; i < nBits; i++ ) + fprintf( pFile, " a%02d=%02d_%02d", i, A, i ); + fprintf( pFile, " \\\n" ); + for ( i = 0; i < nBits; i++ ) + fprintf( pFile, " b%02d=%02d_%02d", i, B, i ); + fprintf( pFile, " \\\n" ); + for ( i = 0; i <= nBits; i++ ) + fprintf( pFile, " s%02d=%02d_%02d", i, S, i ); + fprintf( pFile, "\n" ); +} +void Abc_GenThresh( char * pFileName, int nBits, Vec_Int_t * vNums, int nLutSize, char * pArch ) +{ + FILE * pFile = fopen( pFileName, "w" ); + int c, i, k, Temp, iPrev = 1, nNums = 1, nSigs = 1, fUsed = 0; + fprintf( pFile, "# %d-bit threshold function with %d variables generated by ABC on %s\n", + nBits, Vec_IntSize(vNums)-1, Extra_TimeStamp() ); + fprintf( pFile, "# Weights:" ); + Vec_IntForEachEntryStop( vNums, Temp, i, Vec_IntSize(vNums)-1 ) + fprintf( pFile, " %d", Temp ); + fprintf( pFile, "\n# Threshold: %d\n", Vec_IntEntryLast(vNums) ); + fprintf( pFile, ".model TF%d_%d\n", Vec_IntSize(vNums)-1, nBits ); + fprintf( pFile, ".inputs" ); + for ( i = 0; i < Vec_IntSize(vNums)-1; i++ ) + fprintf( pFile, " x%02d", i ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".outputs F\n" ); + for ( i = 0; i < nBits; i++ ) + fprintf( pFile, ".names %02d_%02d\n", 0, i ); + fprintf( pFile, ".names zero\n" ); + fprintf( pFile, ".names one\n 1\n" ); + Vec_IntForEachEntry( vNums, Temp, k ) { + fprintf( pFile, ".subckt W%02d", k ); + if ( k < Vec_IntSize(vNums)-1 ) + fprintf( pFile, " i=x%02d", k ); + else + fprintf( pFile, " i=one" ); + for ( i = 0; i < nBits; i++ ) + fprintf( pFile, " o%02d=%02d_%02d", i, nSigs, i ); + fprintf( pFile, "\n" ); + nSigs++; + } + fprintf( pFile, "\n" ); + if ( pArch == NULL ) + { + Vec_IntForEachEntryStart( vNums, Temp, k, 1 ) { + Abc_GenThreshAdder( pFile, nBits, iPrev, k+1, nSigs, k == Vec_IntSize(vNums)-1 ); + iPrev = nSigs++; + } + fprintf( pFile, ".names %02d_%02d F\n0 1\n", iPrev, nBits-1 ); + } + else + { + Vec_Str_t * vArch = Vec_StrAlloc( 100 ); + for ( c = 0; c < strlen(pArch); c++ ) { + if ( pArch[c] == '(' || pArch[c] == ')' ) { + Vec_StrPush( vArch, pArch[c] ); + continue; + } + Temp = pArch[c] >= '0' && pArch[c] <= '9' ? pArch[c] - '0' : pArch[c] - 'A' + 10; + assert( Temp > 0 ); + if ( Temp == 1 ) { + if ( nNums + Temp == Vec_IntSize(vNums) ) + Abc_GenThreshAdder( pFile, nBits, nNums, nNums+1, iPrev = nSigs++, 1 ); + else + iPrev = nNums++; + } + else { + int kLast = 0; + assert( nNums + Temp <= Vec_IntSize(vNums) ); + if ( nNums + Temp == Vec_IntSize(vNums) ) + kLast = Temp++; + iPrev = nNums++; + for ( k = 1; k < Temp; k++ ) { + Abc_GenThreshAdder( pFile, nBits, iPrev, nNums++, nSigs, k == kLast ); + iPrev = nSigs++; + } + fprintf( pFile, "\n" ); + } + Vec_StrPrintF( vArch, "(%d)", iPrev ); + } + Vec_StrPush( vArch, '\0' ); + Temp = Abc_GenTree_rec( pFile, nBits, Vec_StrArray(vArch), 0, &nSigs, &fUsed ); + fprintf( pFile, ".names %02d_%02d F\n0 1\n", Temp, nBits-1 ); + Vec_StrFree( vArch ); + } + fprintf( pFile, ".end\n\n" ); + Vec_IntForEachEntry( vNums, Temp, k ) + Abc_WriteWeight( pFile, k, nBits, k == Vec_IntSize(vNums)-1 ? ~Temp : Temp ); + Abc_WriteAdder2( pFile, nBits ); + if ( fUsed ) + Abc_GenAdder4( pFile, nBits, nLutSize == 4 ? 4 : 6 ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Adder tree generation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +// Based on the paper: E. Demenkov, A. Kojevnikov, A. Kulikov, and G. Yaroslavtsev, +// "New upper bounds on the Boolean circuit complexity of symmetric functions". +// Information Processing Letters, Vol 110(7), March 2010, Pages 264-267. +// https://grigory.us/files/publications/2010_upper_bounds_symmetric_ipl.pdf + +void Abc_WriteMDFA( FILE * pFile ) +{ + fprintf( pFile, ".model MDFA\n" ); + fprintf( pFile, ".inputs z x1 y1 x2 y2\n" ); + fprintf( pFile, ".outputs s c1 c2\n" ); + fprintf( pFile, ".names x1 z g1\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".names y1 g1 g2\n" ); + fprintf( pFile, "00 0\n" ); + fprintf( pFile, ".names y1 z g3\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".names g2 g3 g4\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".names x2 g3 g5\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".names g3 y2 g6\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".names g5 y2 g7\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, ".names g2 g7 g8\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".names g6 s\n" ); + fprintf( pFile, "1 1\n" ); + fprintf( pFile, ".names g4 c1\n" ); + fprintf( pFile, "1 1\n" ); + fprintf( pFile, ".names g8 c2\n" ); + fprintf( pFile, "1 1\n" ); + fprintf( pFile, ".end\n" ); +} + +void Abc_GenAT( char * pFileName, Vec_Int_t * vNums ) +{ + word Sum = 0; int i, k, Num, nBits = 0; + Vec_IntForEachEntry( vNums, Num, i ) + Sum += ((word)1 << i) * Num; + while ( Sum ) + nBits++, Sum >>= 1; + + Vec_Int_t * vTemp; int nFAs = 0, nHAs = 0, nItem = 0; + Vec_Wec_t * vItems = Vec_WecStart( nBits ); + Vec_IntForEachEntry( vNums, Num, i ) + for ( k = 0; k < Num; k++ ) + Vec_WecPush( vItems, i, nItem++ ); + + FILE * pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# %d-bit %d-input adder tree generated by ABC on %s\n", nBits, nItem, Extra_TimeStamp() ); + fprintf( pFile, "# Profile:" ); + Vec_IntForEachEntry( vNums, Num, i ) + fprintf( pFile, " %d", Num ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".model AT%d_%d\n", nItem, nBits ); + Vec_WecForEachLevel( vItems, vTemp, i ) { + if ( Vec_IntSize(vTemp) == 0 ) + continue; + fprintf( pFile, ".inputs" ); + Vec_IntForEachEntry( vTemp, Num, k ) + fprintf( pFile, " %02d", Num ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, ".outputs" ); + for ( k = 0; k < nBits; k++ ) + fprintf( pFile, " o%02d", k ); + fprintf( pFile, "\n\n" ); + + assert( nItem == Vec_IntSum(vNums) ); + Vec_WecForEachLevel( vItems, vTemp, i ) { + fprintf( pFile, "# Rank %d:\n", i ); + Vec_IntForEachEntry( vTemp, Num, k ) { + if ( Vec_IntSize(vTemp) < 2 ) + continue; + while ( Vec_IntSize(vTemp) > 2 ) { + int i1 = Vec_IntPop(vTemp); + int i2 = Vec_IntPop(vTemp); + int i3 = Vec_IntPop(vTemp); + int i4 = nItem++; + int i5 = nItem++; + fprintf( pFile, ".subckt FA a=%02d b=%02d cin=%02d s=%02d cout=%02d\n", i3, i2, i1, i4, i5 ); nFAs++; + Vec_IntPush( vTemp, i4 ); + if ( i+1 < Vec_WecSize(vItems) ) + Vec_WecPush( vItems, i+1, i5 ); + } + if ( Vec_IntSize(vTemp) == 2 ) { + int i1 = Vec_IntPop(vTemp); + int i2 = Vec_IntPop(vTemp); + int i4 = nItem++; + int i5 = nItem++; + fprintf( pFile, ".subckt HA a=%02d b=%02d s=%02d cout=%02d\n", i2, i1, i4, i5 ); nHAs++; + Vec_IntPush( vTemp, i4 ); + if ( i+1 < Vec_WecSize(vItems) ) + Vec_WecPush( vItems, i+1, i5 ); + } + assert( Vec_IntSize(vTemp) == 1 ); + } + } + Vec_WecForEachLevel( vItems, vTemp, i ) + if ( Vec_IntSize(vTemp) == 0 ) + fprintf( pFile, ".names o%02d\n", i ); + else if ( Vec_IntSize(vTemp) == 1 ) + fprintf( pFile, ".names %02d o%02d\n1 1\n", Vec_IntEntry(vTemp, 0), i ); + else assert( 0 ); + fprintf( pFile, ".end\n\n" ); + Abc_WriteHalfAdder( pFile ); + Abc_WriteFullAdder( pFile ); + printf( "Created %d-bit %d-input AT with %d FAs and %d HAs.\n", nBits, Vec_IntSum(vNums), nFAs, nHAs ); + fclose( pFile ); + Vec_WecFree( vItems ); +} +void Abc_GenATDual( char * pFileName, Vec_Int_t * vNums ) +{ + word Sum = 0; int i, k, Num, nBits = 0, Iter = 0, fUsed = 0; + Vec_IntForEachEntry( vNums, Num, i ) + Sum += ((word)1 << i) * Num; + while ( Sum ) + nBits++, Sum >>= 1; + + Vec_Int_t * vTemp; int nFAs = 0, nHAs = 0, nXors = 0, nItem = 1; + Vec_Wec_t * vItems = Vec_WecStart( nBits ); + Vec_IntForEachEntry( vNums, Num, i ) + for ( k = 0; k < Num; k++ ) + Vec_WecPush( vItems, i, nItem++ ); + + FILE * pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# %d-bit %d-input adder tree generated by ABC on %s\n", nBits, Vec_IntSum(vNums), Extra_TimeStamp() ); + fprintf( pFile, "# Profile:" ); + Vec_IntForEachEntry( vNums, Num, i ) + fprintf( pFile, " %d", Num ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".model AT%d_%d\n", nItem, nBits ); + Vec_WecForEachLevel( vItems, vTemp, i ) { + if ( Vec_IntSize(vTemp) == 0 ) + continue; + fprintf( pFile, ".inputs" ); + Vec_IntForEachEntry( vTemp, Num, k ) + fprintf( pFile, " %02d", Num ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, ".outputs" ); + for ( k = 0; k < nBits; k++ ) + fprintf( pFile, " o%02d", k ); + fprintf( pFile, "\n\n" ); + + fprintf( pFile, ".names %02d\n", 0 ); + while ( Vec_WecMaxLevelSize(vItems) > 2 ) + { + fprintf( pFile, "# Iter %d:\n", Iter++ ); + Vec_Wec_t * vItems2 = Vec_WecStart( nBits ); + Vec_WecForEachLevel( vItems, vTemp, i ) { + while ( Vec_IntSize(vTemp) > 3 ) { + int i0 = Vec_IntEntry(vTemp, 0); Vec_IntDrop(vTemp, 0); + int i1 = Vec_IntEntry(vTemp, 0); Vec_IntDrop(vTemp, 0); + int i2 = Vec_IntEntry(vTemp, 0); Vec_IntDrop(vTemp, 0); + int i3 = Vec_IntEntry(vTemp, 0); Vec_IntDrop(vTemp, 0); + int i4 = (Vec_IntSize(vTemp) > 0 && Vec_IntEntryLast(vTemp) > 0) ? Vec_IntPop(vTemp) : 0; + assert( (i0 < 0) == (i1 < 0) ); + assert( (i2 < 0) == (i3 < 0) ); + if ( i1 > 0 ) + fprintf( pFile, ".names %02d %02d %02d\n01 1\n10 1\n", i0, i1, nItem ), i1 = nItem++, nXors++; + else + i1 = -i1, i0 = -i0; + if ( i3 > 0 ) + fprintf( pFile, ".names %02d %02d %02d\n01 1\n10 1\n", i2, i3, nItem ), i3 = nItem++, nXors++; + else + i3 = -i3, i2 = -i2; + int o0 = nItem++; + int o1 = nItem++; + int o2 = nItem++; + fprintf( pFile, ".subckt MDFA z=%02d x1=%02d y1=%02d x2=%02d y2=%02d s=%02d c1=%02d c2=%02d\n", i4, i0, i1, i2, i3, o0, o1, o2 ); nFAs += 2, fUsed = 1; + Vec_WecPush( vItems2, i, o0 ); + if ( i+1 < Vec_WecSize(vItems2) ) { + Vec_WecPush( vItems2, i+1, -o1 ); + Vec_WecPush( vItems2, i+1, -o2 ); + } + } + if ( Vec_IntSize(vTemp) == 3 ) { + int i2 = Vec_IntPop(vTemp); + int i1 = Vec_IntPop(vTemp); + int i0 = Vec_IntPop(vTemp); + assert( (i0 < 0) == (i1 < 0) ); + assert( i2 > 0 ); + if ( i1 < 0 ) + fprintf( pFile, ".names %02d %02d %02d\n01 1\n10 1\n", -i0, -i1, nItem ), i0 = -i0, i1 = nItem++, nXors++; + int o0 = nItem++; + int o1 = nItem++; + fprintf( pFile, ".subckt FA a=%02d b=%02d cin=%02d s=%02d cout=%02d\n", i0, i1, i2, o0, o1 ); nFAs++; + Vec_WecPush( vItems2, i, o0 ); + if ( i+1 < Vec_WecSize(vItems2) ) + Vec_WecPush( vItems2, i+1, o1 ); + } + if ( Vec_IntSize(vTemp) == 2 ) { + int i1 = Vec_IntPop(vTemp); + int i0 = Vec_IntPop(vTemp); + assert( (i0 < 0) == (i1 < 0) ); + if ( i1 < 0 ) { + Vec_IntInsert( Vec_WecEntry(vItems2, i), 0, i1 ); + Vec_IntInsert( Vec_WecEntry(vItems2, i), 0, i0 ); + } + else { + Vec_WecPush( vItems2, i, i0 ); + Vec_WecPush( vItems2, i, i1 ); + } + } + if ( Vec_IntSize(vTemp) == 1 ) { + int i0 = Vec_IntPop(vTemp); + assert( i0 > 0 ); + Vec_WecPush( vItems2, i, i0 ); + } + assert( Vec_IntSize(vTemp) == 0 ); + } + Vec_WecFree( vItems ); + vItems = vItems2; + } + Vec_WecForEachLevel( vItems, vTemp, i ) { + if ( Vec_IntSize(vTemp) == 2 ) { + int i1 = Vec_IntPop(vTemp); + int i0 = Vec_IntPop(vTemp); + assert( (i0 < 0) == (i1 < 0) ); + if ( i1 < 0 ) + fprintf( pFile, ".names %02d %02d %02d\n01 1\n10 1\n", -i0, -i1, nItem ), i0 = -i0, i1 = nItem++, nXors++; + Vec_IntPush( vTemp, i0 ); + Vec_IntPush( vTemp, i1 ); + } + if ( Vec_IntSize(vTemp) == 1 ) { + int i0 = Vec_IntPop(vTemp); + assert( i0 > 0 ); + Vec_IntPush( vTemp, i0 ); + Vec_IntPush( vTemp, 0 ); + } + if ( Vec_IntSize(vTemp) == 0 ) { + Vec_IntPush( vTemp, 0 ); + Vec_IntPush( vTemp, 0 ); + } + assert( Vec_IntSize(vTemp) == 2 ); + } + int cin = 0; + Vec_WecForEachLevel( vItems, vTemp, i ) { + int i1 = Vec_IntPop(vTemp); + int i0 = Vec_IntPop(vTemp); + assert( i0 >= 0 && i1 >= 0 ); + fprintf( pFile, ".subckt FA a=%02d b=%02d cin=%02d s=o%02d cout=%02d\n", i0, i1, cin, i, nItem ); nFAs++; + cin = nItem++; + } + fprintf( pFile, ".end\n\n" ); + Abc_WriteFullAdder( pFile ); + if ( fUsed ) + Abc_WriteMDFA( pFile ); + printf( "Created %d-bit %d-input AT with %d FAs, %d HAs, and %d XORs.\n", nBits, Vec_IntSum(vNums), nFAs, nHAs, nXors ); + fclose( pFile ); + Vec_WecFree( vItems ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c index 8c4ac1448..6c71c9ec2 100644 --- a/src/base/abci/abcIf.c +++ b/src/base/abci/abcIf.c @@ -465,10 +465,14 @@ void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCut { val = acd_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray ); } - else + else if ( pIfMan->pPars->fUserLut2D ) { val = acd2_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray ); } + else + { + val = acdXX_decompose( pTruth, pIfMan->pPars->nLutDecSize, pCutBest->nLeaves, decompArray ); + } assert( val == 0 ); // convert the LUT-structure into a set of logic nodes in Abc_Ntk_t @@ -593,7 +597,7 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i ) Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) ); } - else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D ) + else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D || pIfMan->pPars->fDeriveLuts ) { If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i ) Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover); @@ -651,7 +655,7 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t extern Hop_Obj_t * Abc_RecToHop3( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj ); pNodeNew->pData = Abc_RecToHop3( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj ); } - else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D ) + else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D || pIfMan->pPars->fDeriveLuts ) { extern void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj, Vec_Int_t * vMemory, Abc_Obj_t * pNodeTop ); Abc_DecRecordToHop( pNtkNew, pIfMan, pCutBest, pIfObj, vCover, pNodeNew ); diff --git a/src/base/abci/abcLutmin.c b/src/base/abci/abcLutmin.c index 11605eb14..883a56904 100644 --- a/src/base/abci/abcLutmin.c +++ b/src/base/abci/abcLutmin.c @@ -574,6 +574,49 @@ Abc_Obj_t * Abc_NtkBddFindCofactor( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int return pNodeTop; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBddDecExploreOne( DdManager * dd, DdNode * bFunc, int iOrder ) +{ + DdManager * ddNew = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + int i, * pProfile = ABC_CALLOC( int, dd->size + 100 ); + Cudd_AutodynEnable( ddNew, CUDD_REORDER_SYMM_SIFT ); + Vec_Int_t * vPerm = Vec_IntStartNatural( dd->size ); if ( iOrder ) Vec_IntRandomizeOrder( vPerm ); + DdNode * bFuncNew = Extra_TransferPermute( dd, ddNew, bFunc, Vec_IntArray(vPerm) ); Cudd_Ref(bFuncNew); + if ( iOrder ) Cudd_ReduceHeap( ddNew, CUDD_REORDER_SYMM_SIFT, 1 ); + Vec_IntFree( vPerm ); + DdNode * aFuncNew = Cudd_BddToAdd( ddNew, bFuncNew ); Cudd_Ref( aFuncNew ); + Extra_ProfileWidth( ddNew, aFuncNew, pProfile, -1 ); + if ( iOrder ) + printf( "Random order %d:\n", iOrder ); + else + printf( "Natural order:\n" ); + for ( i = 0; i <= dd->size; i++ ) + printf( " %d=%d(%d)[%d]", i, pProfile[i], i-Abc_Base2Log(pProfile[i]), ddNew->perm[i] ); + printf( "\n" ); + Cudd_RecursiveDeref( ddNew, aFuncNew ); + Cudd_RecursiveDeref( ddNew, bFuncNew ); + Cudd_Quit( ddNew ); +} +void Abc_NtkBddDecExplore( Abc_Obj_t * pNode ) +{ + DdManager * dd = (DdManager *)pNode->pNtk->pManFunc; + DdNode * bFunc = (DdNode *)pNode->pData; + int i; Abc_Random(1); + if ( Abc_ObjIsNode(pNode) ) + for ( i = 0; i < 16; i++ ) + Abc_NtkBddDecExploreOne( dd, bFunc, i ); +} + /**Function************************************************************* Synopsis [Decompose the function once.] @@ -612,14 +655,14 @@ Abc_Obj_t * Abc_NtkBddDecompose( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int nLu vCofs = Abc_NtkBddCofactors( dd, (DdNode *)pNode->pData, nLutSize ); vUniq = Vec_PtrDup( vCofs ); Vec_PtrUniqify( vUniq, (int (*)(const void *, const void *))Vec_PtrSortCompare ); - // only perform decomposition with it is support reduring with two less vars + // only perform decomposition which it is support reducing with two less vars if( Vec_PtrSize(vUniq) > (1 << (nLutSize-2)) ) { Vec_PtrFree( vCofs ); vCofs = Abc_NtkBddCofactors( dd, (DdNode *)pNode->pData, 2 ); if ( fVerbose ) - printf( "Decomposing %d-input node %d using cofactoring with %d cofactors.\n", - Abc_ObjFaninNum(pNode), Abc_ObjId(pNode), Vec_PtrSize(vCofs) ); + printf( "Decomposing %d-input node %d using cofactoring with %d cofactors (myu = %d).\n", + Abc_ObjFaninNum(pNode), Abc_ObjId(pNode), Vec_PtrSize(vCofs), Vec_PtrSize(vUniq) ); // implement the cofactors pCofs[0] = Abc_ObjFanin(pNode, 0)->pCopy; pCofs[1] = Abc_ObjFanin(pNode, 1)->pCopy; @@ -688,13 +731,13 @@ void Abc_NtkLutminConstruct( Abc_Ntk_t * pNtkClp, Abc_Ntk_t * pNtkDec, int nLutS SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkLutminInt( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ) +Abc_Ntk_t * Abc_NtkLutminInt( Abc_Ntk_t * pNtk, int nLutSize, int fReorder, int fVerbose ) { extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ); Abc_Ntk_t * pNtkDec; // minimize BDDs -// Abc_NtkBddReorder( pNtk, fVerbose ); - Abc_NtkBddReorder( pNtk, 0 ); + if ( fReorder ) + Abc_NtkBddReorder( pNtk, 0 ); // decompose one output at a time pNtkDec = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); // make sure the new manager has enough inputs @@ -719,7 +762,7 @@ Abc_Ntk_t * Abc_NtkLutminInt( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ) SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtkInit, int nLutSize, int fVerbose ) +Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtkInit, int nLutSize, int fReorder, int fVerbose ) { extern int Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); Abc_Ntk_t * pNtkNew, * pTemp; @@ -740,7 +783,7 @@ Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtkInit, int nLutSize, int fVerbose ) else pNtkNew = Abc_NtkStrash( pNtkInit, 0, 1, 0 ); // collapse the network - pNtkNew = Abc_NtkCollapse( pTemp = pNtkNew, 10000, 0, 1, 0, 0, 0 ); + pNtkNew = Abc_NtkCollapse( pTemp = pNtkNew, 10000, 0, fReorder, 0, 0, 0 ); Abc_NtkDelete( pTemp ); if ( pNtkNew == NULL ) return NULL; @@ -755,7 +798,7 @@ Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtkInit, int nLutSize, int fVerbose ) if ( fVerbose ) printf( "Decomposing network with %d nodes and %d max fanin count for K = %d.\n", Abc_NtkNodeNum(pNtkNew), Abc_NtkGetFaninMax(pNtkNew), nLutSize ); - pNtkNew = Abc_NtkLutminInt( pTemp = pNtkNew, nLutSize, fVerbose ); + pNtkNew = Abc_NtkLutminInt( pTemp = pNtkNew, nLutSize, fReorder, fVerbose ); Abc_NtkDelete( pTemp ); } // fix the problem with complemented and duplicated CO edges @@ -773,7 +816,8 @@ Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtkInit, int nLutSize, int fVerbose ) #else -Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtkInit, int nLutSize, int fVerbose ) { return NULL; } +Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtkInit, int nLutSize, int fReorder, int fVerbose ) { return NULL; } +void Abc_NtkBddDecExplore( Abc_Obj_t * pNode ) {} #endif diff --git a/src/base/abci/abcMap.c b/src/base/abci/abcMap.c index 8f5e4ee2e..0c84a04b8 100644 --- a/src/base/abci/abcMap.c +++ b/src/base/abci/abcMap.c @@ -24,6 +24,7 @@ #include "map/mapper/mapper.h" #include "misc/util/utilNam.h" #include "map/scl/sclCon.h" +#include "map/scl/sclLib.h" ABC_NAMESPACE_IMPL_START @@ -275,6 +276,7 @@ Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, f Map_ManSetAreaRecovery( pMan, fRecovery ); Map_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) ); Map_ManSetDelayTarget( pMan, (float)DelayTarget ); + Map_ManCreateAigIds( pMan, Abc_NtkObjNumMax(pNtk) ); // set arrival and requireds if ( Scl_ConIsRunning() && Scl_ConHasInArrs() ) @@ -297,6 +299,7 @@ Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, f pNode->pCopy = (Abc_Obj_t *)pNodeMap; if ( pSwitching ) Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] ); + Map_NodeSetAigId( pNodeMap, pNode->Id ); } // load the AIG into the mapper @@ -327,6 +330,7 @@ Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, f Map_NodeSetNextE( (Map_Node_t *)pPrev->pCopy, (Map_Node_t *)pFanin->pCopy ); Map_NodeSetRepr( (Map_Node_t *)pFanin->pCopy, (Map_Node_t *)pNode->pCopy ); } + Map_NodeSetAigId( pNodeMap, pNode->Id ); } assert( Map_ManReadBufNum(pMan) == pNtk->nBarBufs ); Vec_PtrFree( vNodes ); @@ -419,6 +423,7 @@ Abc_Obj_t * Abc_NodeFromMapPhase_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap uPhaseBest = Map_CutReadPhaseBest( pCutBest, fPhase ); nLeaves = Map_CutReadLeavesNum( pCutBest ); ppLeaves = Map_CutReadLeaves( pCutBest ); + //Vec_Ptr_t * vAnds = Map_CutInternalNodes( pNodeMap, pCutBest ); // collect the PI nodes for ( i = 0; i < nLeaves; i++ ) @@ -430,6 +435,7 @@ Abc_Obj_t * Abc_NodeFromMapPhase_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap // implement the supergate pNodeNew = Abc_NodeFromMapSuper_rec( pNtkNew, pNodeMap, pSuperBest, pNodePIs, nLeaves ); + Vec_IntWriteEntry( pNtkNew->vOrigNodeIds, pNodeNew->Id, Abc_Var2Lit( Map_NodeReadAigId(pNodeMap), fPhase ) ); Map_NodeSetData( pNodeMap, fPhase, (char *)pNodeNew ); return pNodeNew; } @@ -461,6 +467,7 @@ Abc_Obj_t * Abc_NodeFromMap_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int // add the inverter pNodeInv = Abc_NtkCreateNode( pNtkNew ); + Vec_IntWriteEntry( pNtkNew->vOrigNodeIds, pNodeInv->Id, Abc_Var2Lit( Map_NodeReadAigId(pNodeMap), fPhase ) ); Abc_ObjAddFanin( pNodeInv, pNodeNew ); pNodeInv->pData = Mio_LibraryReadInv((Mio_Library_t *)Abc_FrameReadLibGen()); @@ -477,6 +484,7 @@ Abc_Ntk_t * Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk, int fUseBuffs ) assert( Map_ManReadBufNum(pMan) == pNtk->nBarBufs ); // create the new network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_MAP ); + pNtkNew->vOrigNodeIds = Vec_IntStartFull( 2 * Abc_NtkObjNumMax(pNtk) ); // make the mapper point to the new network Map_ManCleanData( pMan ); Abc_NtkForEachCi( pNtk, pNode, i ) diff --git a/src/base/abci/abcQbf.c b/src/base/abci/abcQbf.c index 5ddd25f1c..f60de5684 100644 --- a/src/base/abci/abcQbf.c +++ b/src/base/abci/abcQbf.c @@ -203,7 +203,7 @@ clkV = Abc_Clock() - clkV; int nZeros = Vec_IntCountZero( vPiValues ); printf( "Parameters: " ); Abc_NtkVectorPrintPars( vPiValues, nPars ); - printf( " Statistics: 0=%d 1=%d\n", nZeros, Vec_IntSize(vPiValues) - nZeros ); + printf( " Statistics: 0=%d 1=%d\n", nZeros, nPars - nZeros ); printf( "Solved after %d iterations. ", nIters ); } else if ( nIters == nItersMax ) diff --git a/src/base/abci/abcResub.c b/src/base/abci/abcResub.c index 85f8a4b4c..803b88e91 100644 --- a/src/base/abci/abcResub.c +++ b/src/base/abci/abcResub.c @@ -558,6 +558,44 @@ void Abc_ManResubPrintDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLe printf( "\n" ); } +/**Function************************************************************* + + Synopsis [Dumps one resub instance.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubDumpInstance( Vec_Ptr_t * vDivs, int nLeaves, int nDivs, int nWords ) +{ + Abc_Obj_t * pRoot = (Abc_Obj_t *)Vec_PtrEntryLast(vDivs); + char pFileName[1000]; + sprintf( pFileName, "%s_%05d.pla", pRoot->pNtk->pName, pRoot->Id ); + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) { + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + return; + } + fprintf( pFile, "// Resub instance generated for node %d in network \"%s\" on %s\n", pRoot->Id, pRoot->pNtk->pName, Extra_TimeStamp() ); + fprintf( pFile, ".i %d\n", nDivs ); + fprintf( pFile, ".o %d\n", 1 ); + fprintf( pFile, ".p %d\n", 1 << nLeaves ); + Abc_Obj_t * pObj; int i, n; + for ( n = 0; n < (1 << nLeaves); n++ ) { + Vec_PtrForEachEntryStop( Abc_Obj_t *, vDivs, pObj, i, nDivs ) { + fprintf( pFile, "%d", Abc_InfoHasBit((unsigned *)pObj->pData, n) ); + if ( i == nLeaves-1 ) + fprintf( pFile, " " ); + } + fprintf( pFile, " %d\n", Abc_InfoHasBit((unsigned *)pRoot->pData, n) ); + } + fprintf( pFile, ".e\n" ); + fclose( pFile ); + printf( "Finished dumping file \"%s\" with %d divisors and %d patterns.\n", pFileName, nDivs, (1 << nLeaves) ); +} /**Function************************************************************* @@ -1929,6 +1967,9 @@ p->timeRes1 += Abc_Clock() - clk; // get the one level divisors Abc_ManResubDivsS( p, Required ); +// if ( Vec_PtrSize(vLeaves) >= 6 ) +// Abc_ManResubDumpInstance( p->vDivs, Vec_PtrSize(vLeaves), p->nDivs, p->nWords ); + // consider one node if ( (pGraph = Abc_ManResubDivs1( p, Required )) ) { diff --git a/src/base/acb/acbFunc.c b/src/base/acb/acbFunc.c index 3c0bb5f06..539b91abf 100644 --- a/src/base/acb/acbFunc.c +++ b/src/base/acb/acbFunc.c @@ -159,7 +159,7 @@ char * pLibStr2[25] = { }; void Acb_IntallLibrary( int f2Ins ) { - extern Mio_Library_t * Mio_LibraryReadBuffer( char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int fVerbose ); + extern Mio_Library_t * Mio_LibraryReadBuffer( char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int nFaninLimit, int fVerbose ); Mio_Library_t * pLib; int i; // create library string @@ -169,7 +169,7 @@ void Acb_IntallLibrary( int f2Ins ) Vec_StrAppend( vLibStr, ppLibStr[i] ); Vec_StrPush( vLibStr, '\0' ); // create library - pLib = Mio_LibraryReadBuffer( Vec_StrArray(vLibStr), 0, NULL, 0 ); + pLib = Mio_LibraryReadBuffer( Vec_StrArray(vLibStr), 0, NULL, 0, 0 ); Mio_LibrarySetName( pLib, Abc_UtilStrsav("iccad17.genlib") ); Mio_UpdateGenlib( pLib ); Vec_StrFree( vLibStr ); diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c index 5b6919f76..20d0f0c38 100644 --- a/src/base/cmd/cmd.c +++ b/src/base/cmd/cmd.c @@ -436,7 +436,7 @@ int CmdCommandAbcrc( Abc_Frame_t * pAbc, int argc, char **argv ) ******************************************************************************/ int CmdCommandHistory( Abc_Frame_t * pAbc, int argc, char **argv ) { - char * pName; + char * pName, * pStr = NULL; int i, c; int nPrints = 20; Extra_UtilGetoptReset(); @@ -453,11 +453,19 @@ int CmdCommandHistory( Abc_Frame_t * pAbc, int argc, char **argv ) if ( argc > globalUtilOptind + 1 ) goto usage; // get the number from the command line - if ( argc == globalUtilOptind + 1 ) - nPrints = atoi(argv[globalUtilOptind]); + pStr = argc == globalUtilOptind+1 ? argv[globalUtilOptind] : NULL; + if ( pStr && pStr[0] >= '1' && pStr[0] <= '9' ) + nPrints = atoi(pStr), pStr = NULL; // print the commands - Vec_PtrForEachEntryStart( char *, pAbc->aHistory, pName, i, Abc_MaxInt(0, Vec_PtrSize(pAbc->aHistory)-nPrints) ) - fprintf( pAbc->Out, "%2d : %s\n", Vec_PtrSize(pAbc->aHistory)-i, pName ); + if ( pStr == NULL ) { + Vec_PtrForEachEntryStart( char *, pAbc->aHistory, pName, i, Abc_MaxInt(0, Vec_PtrSize(pAbc->aHistory)-nPrints) ) + fprintf( pAbc->Out, "%2d : %s\n", Vec_PtrSize(pAbc->aHistory)-i, pName ); + } + else { + Vec_PtrForEachEntry( char *, pAbc->aHistory, pName, i ) + if ( strstr(pName, pStr) ) + fprintf( pAbc->Out, "%2d : %s\n", Vec_PtrSize(pAbc->aHistory)-i, pName ); + } return 0; usage: diff --git a/src/base/cmd/cmdHist.c b/src/base/cmd/cmdHist.c index 109c8e682..2360f0ad4 100644 --- a/src/base/cmd/cmdHist.c +++ b/src/base/cmd/cmdHist.c @@ -49,8 +49,8 @@ ABC_NAMESPACE_IMPL_START ***********************************************************************/ void Cmd_HistoryAddCommand( Abc_Frame_t * p, const char * command ) { - int nLastLooked = 10; // do not add history if the same entry appears among the last entries - int nLastSaved = 1000; // when saving a file, save no more than this number of last entries + int nLastLooked = 10; // do not add history if the same entry appears among the last entries + int nLastSaved = 10000; // when saving a file, save no more than this number of last entries char Buffer[ABC_MAX_STR]; int Len; if ( p->fBatchMode ) diff --git a/src/base/exor/exor.h b/src/base/exor/exor.h index 5a7275579..7a25f96b6 100644 --- a/src/base/exor/exor.h +++ b/src/base/exor/exor.h @@ -54,38 +54,34 @@ ABC_NAMESPACE_HEADER_START /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// -// the number of bits per integer (can be 16, 32, 64 - tested for 32) -#define BPI 32 -#define BPIMASK 31 -#define LOGBPI 5 +enum { + // the number of bits per integer + BPI = 32, + BPIMASK = 31, + LOGBPI = 5, -// the maximum number of input variables -#define MAXVARS 1000 + // the maximum number of input variables + MAXVARS = 1000, -// the number of cubes that are allocated additionally -#define ADDITIONAL_CUBES 33 + // the number of cubes that are allocated additionally + ADDITIONAL_CUBES = 33, -// the factor showing how many cube pairs will be allocated -#define CUBE_PAIR_FACTOR 20 -// the following number of cube pairs are allocated: -// nCubesAlloc/CUBE_PAIR_FACTOR + // the factor showing how many cube pairs will be allocated + CUBE_PAIR_FACTOR = 20, + // the following number of cube pairs are allocated: + // nCubesAlloc/CUBE_PAIR_FACTOR -#if BPI == 64 -#define DIFFERENT 0x5555555555555555 -#define BIT_COUNT(w) (BitCount[(w)&0xffff] + BitCount[((w)>>16)&0xffff] + BitCount[((w)>>32)&0xffff] + BitCount[(w)>>48]) -#elif BPI == 32 -#define DIFFERENT 0x55555555 -#define BIT_COUNT(w) (BitCount[(w)&0xffff] + BitCount[(w)>>16]) -#else -#define DIFFERENT 0x5555 -#define BIT_COUNT(w) (BitCount[(w)]) -#endif + DIFFERENT = 0x55555555, +}; +extern unsigned char BitCount[]; -#define VarWord(element) ((element)>>LOGBPI) -#define VarBit(element) ((element)&BPIMASK) +static inline int BIT_COUNT(int w) { return BitCount[(w)&0xffff] + BitCount[(w)>>16]; } -#define TICKS_TO_SECONDS(time) ((float)(time)/(float)(CLOCKS_PER_SEC)) +static inline int VarWord(int element) { return element>>LOGBPI; } +static inline int VarBit(int element) { return element&BPIMASK; } + +static inline float TICKS_TO_SECONDS(abctime time) { return (float)time/(float)CLOCKS_PER_SEC; } //////////////////////////////////////////////////////////////////////// /// CUBE COVER and CUBE typedefs /// diff --git a/src/base/exor/exorBits.c b/src/base/exor/exorBits.c index 41560e650..e1d8e556e 100644 --- a/src/base/exor/exorBits.c +++ b/src/base/exor/exorBits.c @@ -40,6 +40,11 @@ #include "exor.h" +#ifdef _MSC_VER +# include +# define __builtin_popcount __popcnt +#endif + ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// @@ -80,18 +85,6 @@ void ExorVar( Cube * pC, int Var, varvalue Val ); /// STATIC VARIABLES /// //////////////////////////////////////////////////////////////////////// -// the bit count for the first 256 integer numbers -static unsigned char BitCount8[256] = { - 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 -}; - static int SparseNumbers[163] = { 0,1,4,5,16,17,20,21,64,65,68,69,80,81,84,85,256,257,260, 261,272,273,276,277,320,321,324,325,336,337,340,1024,1025, @@ -158,7 +151,7 @@ void PrepareBitSetModule() nLimit = FULL16BITS; for ( i = 0; i < nLimit; i++ ) { - BitCount[i] = BitCount8[ i & 0xff ] + BitCount8[ i>>8 ]; + BitCount[i] = __builtin_popcount( i & 0xffff ); BitGroupNumbers[i] = MARKNUMBER; } // prepare bit groups diff --git a/src/base/io/io.c b/src/base/io/io.c index 5bb80dba6..8f805d639 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -1387,7 +1387,15 @@ usage: fprintf( pAbc->Err, "\t-x : toggle reading Exclusive SOP rather than SOP [default = %s]\n", fSkipPrepro? "yes":"no" ); fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); - fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n\n" ); + fprintf( pAbc->Err, "\t Please note that the PLA parser is somewhat slow for large SOPs.\n" ); + fprintf( pAbc->Err, "\t On the other hand, BLIF parser reads a 3M SOP and converts it into a 7.5K AIG in 1 sec:\n" ); + fprintf( pAbc->Err, "\t abc 16> read test.blif; ps; bdd -s; ps; muxes; strash; ps\n" ); + fprintf( pAbc->Err, "\t test : i/o = 25/ 1 lat = 0 nd = 1 edge = 25 cube = 2910537 lev = 1\n" ); + fprintf( pAbc->Err, "\t test : i/o = 25/ 1 lat = 0 nd = 1 edge = 25 bdd = 2937 lev = 1\n" ); + fprintf( pAbc->Err, "\t test : i/o = 25/ 1 lat = 0 and = 7514 lev = 48\n" ); + fprintf( pAbc->Err, "\t abc 19> time\n" ); + fprintf( pAbc->Err, "\t elapse: 1.05 seconds, total: 1.05 seconds\n" ); return 1; } diff --git a/src/base/io/ioAbc.h b/src/base/io/ioAbc.h index 9758f1963..9a0d82098 100644 --- a/src/base/io/ioAbc.h +++ b/src/base/io/ioAbc.h @@ -121,7 +121,7 @@ extern void Io_WriteBook( Abc_Ntk_t * pNtk, char * FileName ); extern int Io_WriteCnf( Abc_Ntk_t * pNtk, char * FileName, int fAllPrimes ); /*=== abcWriteDot.c ===========================================================*/ extern void Io_WriteDot( Abc_Ntk_t * pNtk, char * FileName ); -extern void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ); +extern void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse, int fAigIds ); extern void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ); /*=== abcWriteEqn.c ===========================================================*/ extern void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ); diff --git a/src/base/io/ioReadBlifMv.c b/src/base/io/ioReadBlifMv.c index c8c14581a..77ae18415 100644 --- a/src/base/io/ioReadBlifMv.c +++ b/src/base/io/ioReadBlifMv.c @@ -1411,14 +1411,14 @@ static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine ) Last = k+Last+1; break; } -/* + if ( k == nEquals ) { sprintf( p->pMan->sError, "Line %d: Cannot find PI \"%s\" of the model \"%s\" as a formal input of the subcircuit.", Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) ); return 0; } -*/ + if ( pName2 == NULL ) { Abc_Obj_t * pNode = Abc_NtkCreateNodeConst0( p->pNtk ); diff --git a/src/base/io/ioResub.h b/src/base/io/ioResub.h new file mode 100644 index 000000000..bd5175fbe --- /dev/null +++ b/src/base/io/ioResub.h @@ -0,0 +1,344 @@ +/**CFile**************************************************************** + + FileName [ioResub.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioResub.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__base__io__ioResub_h +#define ABC__base__io__ioResub_h + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Abc_RData_t_ Abc_RData_t; +struct Abc_RData_t_ +{ + int nIns; // the number of inputs + int nOuts; // the number of outputs + int nPats; // the number of patterns + int nSimWords; // the number of words needed to store the patterns + Vec_Wrd_t * vSimsIn; // input simulation signatures + Vec_Wrd_t * vSimsOut; // output simulation signatures + Vec_Int_t * vDivs; // divisors + Vec_Int_t * vSol; // solution +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Abc_RDataGetIn ( Abc_RData_t * p, int i, int b ) { return Abc_InfoHasBit((unsigned *)Vec_WrdEntryP(p->vSimsIn, i*p->nSimWords), b); } +static inline int Abc_RDataGetOut( Abc_RData_t * p, int i, int b ) { return Abc_InfoHasBit((unsigned *)Vec_WrdEntryP(p->vSimsOut, i*p->nSimWords), b); } + +static inline void Abc_RDataSetIn ( Abc_RData_t * p, int i, int b ) { Abc_InfoSetBit((unsigned *)Vec_WrdEntryP(p->vSimsIn, i*p->nSimWords), b); } +static inline void Abc_RDataSetOut( Abc_RData_t * p, int i, int b ) { Abc_InfoSetBit((unsigned *)Vec_WrdEntryP(p->vSimsOut, i*p->nSimWords), b); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + +/**Function************************************************************* + + Synopsis [File interface to read/write resub data.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Abc_RData_t * Abc_RDataStart( int nIns, int nOuts, int nPats ) +{ + Abc_RData_t * p = ABC_CALLOC( Abc_RData_t, 1 ); + p->nIns = nIns; + p->nOuts = nOuts; + p->nPats = nPats; + p->nSimWords = Abc_Bit6WordNum(nPats); + p->vSimsIn = Vec_WrdStart( p->nIns * p->nSimWords ); + p->vSimsOut = Vec_WrdStart( 2*p->nOuts * p->nSimWords ); + p->vDivs = Vec_IntAlloc( 16 ); + p->vSol = Vec_IntAlloc( 16 ); + return p; +} +static inline void Abc_RDataStop( Abc_RData_t * p ) +{ + Vec_IntFree( p->vSol ); + Vec_IntFree( p->vDivs ); + Vec_WrdFree( p->vSimsIn ); + Vec_WrdFree( p->vSimsOut ); + ABC_FREE( p ); +} +static inline int Abc_ReadPlaResubParams( char * pFileName, int * pnIns, int * pnOuts, int * pnPats ) +{ + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return 0; + } + int nLineSize = 1000000, iLine = 0; + char * pBuffer = ABC_ALLOC( char, nLineSize ); + *pnIns = *pnOuts = *pnPats = 0; + while ( fgets( pBuffer, nLineSize, pFile ) != NULL ) { + iLine += (pBuffer[0] == '0' || pBuffer[0] == '1' || pBuffer[0] == '-'); + if ( pBuffer[0] != '.' ) + continue; + if ( pBuffer[1] == 'i' ) + *pnIns = atoi(pBuffer+2); + else if ( pBuffer[1] == 'o' ) + *pnOuts = atoi(pBuffer+2); + else if ( pBuffer[1] == 'p' ) + *pnPats = atoi(pBuffer+2); + else if ( pBuffer[1] == 'e' ) + break; + } + if ( *pnPats == 0 ) + *pnPats = iLine; + else if ( *pnPats != iLine ) + printf( "The number of lines in the file (%d) does not match the number listed in .p (%d).\n", iLine, *pnPats ); + fclose(pFile); + free( pBuffer ); + return 1; +} +static inline int Abc_ReadPlaResubData( Abc_RData_t * p, char * pFileName ) +{ + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return 0; + } + int i, iLine = 0, nDashes = 0, MaxLineSize = p->nIns+p->nOuts+10000; + char * pTemp, * pBuffer = ABC_ALLOC( char, MaxLineSize ); + while ( fgets( pBuffer, MaxLineSize, pFile ) != NULL ) { + if ( pBuffer[0] == '0' || pBuffer[0] == '1' || pBuffer[0] == '-' ) { + for ( pTemp = pBuffer, i = 0; *pTemp; pTemp++ ) { + if ( i < p->nIns ) { // input part + nDashes += (*pTemp == '-'); + if ( *pTemp == '1' ) + Abc_InfoSetBit( (unsigned *)Vec_WrdEntryP(p->vSimsIn, i*p->nSimWords), iLine ); + } + else { // output part + if ( *pTemp == '0' ) + Abc_InfoSetBit( (unsigned *)Vec_WrdEntryP(p->vSimsOut, (2*(i-p->nIns)+0)*p->nSimWords), iLine ); + else if ( *pTemp == '1' ) + Abc_InfoSetBit( (unsigned *)Vec_WrdEntryP(p->vSimsOut, (2*(i-p->nIns)+1)*p->nSimWords), iLine ); + //else if ( *pTemp == '-' ) { + // Abc_InfoSetBit( (unsigned *)Vec_WrdEntryP(p->vSimsOut, (2*(i-p->nIns)+0)*p->nSimWords), iLine ); + // Abc_InfoSetBit( (unsigned *)Vec_WrdEntryP(p->vSimsOut, (2*(i-p->nIns)+1)*p->nSimWords), iLine ); + //} + } + i += (*pTemp == '0' || *pTemp == '1' || *pTemp == '-'); + } + assert( i == p->nIns + p->nOuts ); + iLine++; + } + if ( pBuffer[0] == '.' && (pBuffer[1] == 's' || pBuffer[1] == 'a') ) { + Vec_Int_t * vArray = pBuffer[1] == 'a' ? p->vSol : p->vDivs; + if ( Vec_IntSize(vArray) > 0 ) + continue; + char * pTemp = strtok( pBuffer+2, " \r\n\t" ); + do Vec_IntPush( vArray, atoi(pTemp) ); + while ( (pTemp = strtok( NULL, " \r\n\t" )) ); + } + } + if ( nDashes ) + printf( "Several (%d) don't-care literals in the input part are replaced by zeros \"%s\" \n", nDashes, pFileName ); + assert ( iLine == p->nPats ); + ABC_FREE(pBuffer); + fclose(pFile); + return 1; +} +static inline Abc_RData_t * Abc_ReadPla( char * pFileName ) +{ + int nIns, nOuts, nPats; + int RetValue = Abc_ReadPlaResubParams( pFileName, &nIns, &nOuts, &nPats ); + if ( !RetValue ) return NULL; + Abc_RData_t * p = Abc_RDataStart( nIns, nOuts, nPats ); + RetValue = Abc_ReadPlaResubData( p, pFileName ); + return p; +} +static inline void Abc_WritePla( Abc_RData_t * p, char * pFileName, int fRel ) +{ + FILE * pFile = fopen( pFileName, "wb" ); int i, k; + if ( pFile == NULL ) { + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + return; + } + assert( fRel || Vec_WrdSize(p->vSimsOut) == 2*p->nOuts*p->nSimWords ); + assert( !fRel || Vec_WrdSize(p->vSimsOut) == (1 << p->nOuts)*p->nSimWords ); + fprintf( pFile, ".i %d\n", p->nIns ); + fprintf( pFile, ".o %d\n", p->nOuts ); + if ( fRel == 2 ) { + int n, iLine = 0, Count = 0; word Entry; + Vec_WrdForEachEntry( p->vSimsOut, Entry, i ) + Count += Abc_TtCountOnes(Entry); + fprintf( pFile, ".p %d\n", Count ); + for ( i = 0; i < p->nPats; i++ ) + for ( n = 0; n < (1 << p->nOuts); n++ ) { + if ( !Abc_InfoHasBit((unsigned *)Vec_WrdEntryP(p->vSimsOut, n*p->nSimWords), i) ) + continue; + for ( k = 0; k < p->nIns; k++ ) + fprintf( pFile, "%d", Abc_InfoHasBit((unsigned *)Vec_WrdEntryP(p->vSimsIn, k*p->nSimWords), i) ); + fprintf( pFile, " "); + for ( k = 0; k < p->nOuts; k++ ) + fprintf( pFile, "%d", (n >> k) & 1 ); + fprintf( pFile, "\n"); + iLine++; + } + assert( iLine == Count ); + } + else { + fprintf( pFile, ".p %d\n", p->nPats ); + for ( i = 0; i < p->nPats; i++ ) { + for ( k = 0; k < p->nIns; k++ ) + fprintf( pFile, "%d", Abc_InfoHasBit((unsigned *)Vec_WrdEntryP(p->vSimsIn, k*p->nSimWords), i) ); + fprintf( pFile, " "); + if ( !fRel ) { // multi-output function + for ( k = 0; k < p->nOuts; k++ ) { + int Val0 = Abc_InfoHasBit((unsigned *)Vec_WrdEntryP(p->vSimsOut, (2*k+0)*p->nSimWords), i); + int Val1 = Abc_InfoHasBit((unsigned *)Vec_WrdEntryP(p->vSimsOut, (2*k+1)*p->nSimWords), i); + char Val = (Val0 && Val1) ? '-' : Val1 ? '1' : '0'; + fprintf( pFile, "%c", Val ); + } + } + else { // relation + for ( k = 0; k < (1 << p->nOuts); k++ ) + fprintf( pFile, "%d", Abc_InfoHasBit((unsigned *)Vec_WrdEntryP(p->vSimsOut, k*p->nSimWords), i) ); + } + fprintf( pFile, "\n"); + } + } + fprintf( pFile, ".e\n" ); + fclose(pFile); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_RDataIsRel( Abc_RData_t * p ) +{ + assert( p->nIns < 64 ); + Vec_Wrd_t * vTransIn = Vec_WrdStart( 64*p->nSimWords ); + Extra_BitMatrixTransposeP( p->vSimsIn, p->nSimWords, vTransIn, 64*p->nSimWords ); + Vec_WrdShrink( vTransIn, p->nPats ); + Vec_WrdUniqify( vTransIn ); + int Value = Vec_WrdSize(vTransIn) < p->nPats; + Vec_WrdFree( vTransIn ); + return Value; +} +static inline Abc_RData_t * Abc_RData2Rel( Abc_RData_t * p ) +{ + assert( p->nIns < 64 ); + assert( p->nOuts < 32 ); + int w; + Vec_Wrd_t * vSimsIn2 = Vec_WrdStart( 64*p->nSimWords ); + Vec_Wrd_t * vSimsOut2 = Vec_WrdStart( 64*p->nSimWords ); + for ( w = 0; w < p->nIns; w++ ) + Abc_TtCopy( Vec_WrdEntryP(vSimsIn2, w*p->nSimWords), Vec_WrdEntryP(p->vSimsIn, w*p->nSimWords), p->nSimWords, 0 ); + for ( w = 0; w < p->nOuts; w++ ) + Abc_TtCopy( Vec_WrdEntryP(vSimsOut2, w*p->nSimWords), Vec_WrdEntryP(p->vSimsOut, (2*w+1)*p->nSimWords), p->nSimWords, 0 ); + Vec_Wrd_t * vTransIn = Vec_WrdStart( 64*p->nSimWords ); + Vec_Wrd_t * vTransOut = Vec_WrdStart( 64*p->nSimWords ); + Extra_BitMatrixTransposeP( vSimsIn2, p->nSimWords, vTransIn, 1 ); + Extra_BitMatrixTransposeP( vSimsOut2, p->nSimWords, vTransOut, 1 ); + Vec_WrdShrink( vTransIn, p->nPats ); + Vec_WrdShrink( vTransOut, p->nPats ); + Vec_Wrd_t * vTransInCopy = Vec_WrdDup(vTransIn); + Vec_WrdUniqify( vTransInCopy ); + if ( Vec_WrdSize(vTransInCopy) == p->nPats ) + printf( "This resub problem is not a relation.\n" ); + // create the relation + Abc_RData_t * pNew = Abc_RDataStart( p->nIns, 1 << (p->nOuts-1), Vec_WrdSize(vTransInCopy) ); + pNew->nOuts = p->nOuts; + int i, k, n, iLine = 0; word Entry, Entry2; + Vec_WrdForEachEntry( vTransInCopy, Entry, i ) { + for ( n = 0; n < p->nIns; n++ ) + if ( (Entry >> n) & 1 ) + Abc_InfoSetBit( (unsigned *)Vec_WrdEntryP(pNew->vSimsIn, n*pNew->nSimWords), iLine ); + Vec_WrdForEachEntry( vTransIn, Entry2, k ) { + if ( Entry != Entry2 ) + continue; + Entry2 = Vec_WrdEntry( vTransOut, k ); + assert( Entry2 < (1 << p->nOuts) ); + Abc_InfoSetBit( (unsigned *)Vec_WrdEntryP(pNew->vSimsOut, Entry2*pNew->nSimWords), iLine ); + } + iLine++; + } + assert( iLine == pNew->nPats ); + Vec_WrdFree( vTransOut ); + Vec_WrdFree( vTransInCopy ); + Vec_WrdFree( vTransIn ); + Vec_WrdFree( vSimsIn2 ); + Vec_WrdFree( vSimsOut2 ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +/* +void Abc_ReadPlaTest( char * pFileName ) +{ + Abc_RData_t * p = Abc_ReadPla( pFileName ); + Abc_WritePla( p, "resub_out.pla", 0 ); + Abc_RData_t * p2 = Abc_RData2Rel( p ); + Abc_WritePla( p2, "resub_out1.pla", 1 ); + Abc_WritePla( p2, "resub_out2.pla", 2 ); + Abc_RDataStop( p2 ); + Abc_RDataStop( p ); +} +*/ + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/base/io/ioWriteDot.c b/src/base/io/ioWriteDot.c index 0ab3c4d2f..dc1f97698 100644 --- a/src/base/io/ioWriteDot.c +++ b/src/base/io/ioWriteDot.c @@ -52,7 +52,7 @@ void Io_WriteDot( Abc_Ntk_t * pNtk, char * FileName ) { Vec_Ptr_t * vNodes; vNodes = Abc_NtkCollectObjects( pNtk ); - Io_WriteDotNtk( pNtk, vNodes, NULL, FileName, 0, 0 ); + Io_WriteDotNtk( pNtk, vNodes, NULL, FileName, 0, 0, 0 ); Vec_PtrFree( vNodes ); } @@ -68,12 +68,12 @@ void Io_WriteDot( Abc_Ntk_t * pNtk, char * FileName ) SeeAlso [] ***********************************************************************/ -void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ) +void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse, int fAigIds ) { FILE * pFile; Abc_Obj_t * pNode, * pFanin; - char * pSopString; - int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl, Prev; + char * pSopString, SopString[32]; + int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl, Prev, AigNodeId; int Limit = 500; assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); @@ -302,9 +302,22 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho pSopString = Mio_GateReadName((Mio_Gate_t *)pNode->pData); else if ( Abc_NtkHasMapping(pNtk) ) pSopString = Abc_NtkPrintSop(Mio_GateReadSop((Mio_Gate_t *)pNode->pData)); - else - pSopString = Abc_NtkPrintSop((char *)pNode->pData); - fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString ); + else { + int nCubes = Abc_SopGetCubeNum((char *)pNode->pData); + if ( nCubes <= 16 ) + pSopString = Abc_NtkPrintSop((char *)pNode->pData); + else { + sprintf( SopString, "%d cubes", nCubes ); + pSopString = SopString; + } + } + //if ( pNtk->vOrigNodeIds ) + // printf( "%d = %d \n", pNode->Id, Vec_IntEntry(pNtk->vOrigNodeIds, pNode->Id) ) + AigNodeId = (fAigIds && pNtk->vOrigNodeIds) ? Vec_IntEntry(pNtk->vOrigNodeIds, pNode->Id) : -1; + if ( AigNodeId > 0 ) + fprintf( pFile, " Node%d [label = \"%s%d\\n%s\"", pNode->Id, Abc_LitIsCompl(AigNodeId) ? "-":"+", Abc_Lit2Var(AigNodeId), pSopString ); + else + fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString ); // fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, // SuppSize, // pSopString ); diff --git a/src/base/main/abcapis.h b/src/base/main/abcapis.h index 30494f77c..d723e3e6f 100644 --- a/src/base/main/abcapis.h +++ b/src/base/main/abcapis.h @@ -82,6 +82,7 @@ extern ABC_DLL void Abc_FrameGiaInputMiniLut2( Abc_Frame_t * pAbc, void * pMin extern ABC_DLL void * Abc_FrameGiaOutputMiniLut( Abc_Frame_t * pAbc ); extern ABC_DLL char * Abc_FrameGiaOutputMiniLutAttr( Abc_Frame_t * pAbc, void * pMiniLut ); extern ABC_DLL int * Abc_FrameReadMiniLutSwitching( Abc_Frame_t * pAbc ); +extern ABC_DLL int * Abc_FrameReadMiniLutSwitching2( Abc_Frame_t * pAbc, int nRandPiFactor ); extern ABC_DLL int * Abc_FrameReadMiniLutSwitchingPo( Abc_Frame_t * pAbc ); // procedures to input/output NDR data-structure diff --git a/src/base/wlc/wlc.c b/src/base/wlc/wlc.c index 91656efc8..0968b6ea7 100644 --- a/src/base/wlc/wlc.c +++ b/src/base/wlc/wlc.c @@ -678,7 +678,6 @@ Gia_Man_t * Wlc_ManGenTree( int nInputs, int Value, int nBits, int fVerbose ) Gia_Man_t * Wlc_ManGenProd( int nInputs, int fVerbose ) { extern void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds, int fVerbose ); - extern void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ); Vec_Int_t * vIns = Vec_IntAlloc( 2*nInputs ); Gia_Man_t * pTemp, * pNew; Vec_Wec_t * vProds; int i; @@ -694,8 +693,6 @@ Gia_Man_t * Wlc_ManGenProd( int nInputs, int fVerbose ) Gia_ManHashAlloc( pNew ); Wlc_BlastBooth( pNew, Vec_IntArray(vIns), Vec_IntArray(vIns)+nInputs, nInputs, nInputs, NULL, 0, 0, &vProds, 0 ); - //Wlc_BlastMultiplier3( pNew, Vec_IntArray(vIns), Vec_IntArray(vIns)+nInputs, nInputs, nInputs, NULL, 0, 0, &vProds ); - //Vec_WecPrint( vProds, 0 ); Wlc_ManGenTreeOne( pNew, vProds, 1, fVerbose ); Gia_ManHashStop( pNew ); Vec_WecFree( vProds ); diff --git a/src/base/wlc/wlcAbs.c b/src/base/wlc/wlcAbs.c index c297c54fe..632778fe4 100644 --- a/src/base/wlc/wlcAbs.c +++ b/src/base/wlc/wlcAbs.c @@ -1886,8 +1886,8 @@ int Wlc_NtkAbsCore( Wlc_Ntk_t * p, Wlc_Par_t * pPars ) Vec_IntFree( vRefine ); Abc_CexFree( pCex ); } - Vec_IntFree( vBlacks ); - Vec_BitFree( vUnmark ); + Vec_IntFreeP( &vBlacks ); + Vec_BitFreeP( &vUnmark ); // report the result if ( pPars->fVerbose ) printf( "\n" ); diff --git a/src/base/wlc/wlcBlast.c b/src/base/wlc/wlcBlast.c index d3b2b3a05..2e419d344 100644 --- a/src/base/wlc/wlcBlast.c +++ b/src/base/wlc/wlcBlast.c @@ -891,7 +891,7 @@ void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vL { Vec_Int_t * vLevel, * vProd; int i, NodeS, NodeC, LevelS, LevelC, Node1, Node2, Node3, Level1, Level2, Level3; - int nSize = Vec_WecSize(vProds); + int nSize = Vec_WecSize(vProds), nFAs = Vec_WecSize(vProds), nHAs = 0; assert( nSize == Vec_WecSize(vLevels) ); for ( i = 0; i < nSize; i++ ) { @@ -911,6 +911,12 @@ void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vL Level2 = Vec_IntPop( vLevel ); Level3 = Vec_IntPop( vLevel ); + int nInputs = (Node1 > 1) + (Node2 > 1) + (Node3 > 1); + if ( nInputs == 3 ) + nFAs++; + else if ( nInputs == 2 ) + nHAs++; + Wlc_BlastFullAdder( pNew, Node1, Node2, Node3, &NodeC, &NodeS ); LevelS = Abc_MaxInt( Abc_MaxInt(Level1, Level2), Level3 ) + 2; LevelC = LevelS - 1; @@ -929,7 +935,7 @@ void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vL { vProd = Vec_WecEntry( vProds, i ); while ( Vec_IntSize(vProd) < 2 ) - Vec_IntPush( vProd, 0 ); + Vec_IntPush( vProd, 0 ), nFAs--, nHAs++; assert( Vec_IntSize(vProd) == 2 ); } // Vec_WecPrint( vProds, 0 ); @@ -950,6 +956,7 @@ void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vL Wlc_BlastAdderCLA( pNew, Vec_IntArray(vRes), Vec_IntArray(vLevel), Vec_IntSize(vRes), fSigned, 0 ); else Wlc_BlastAdder( pNew, Vec_IntArray(vRes), Vec_IntArray(vLevel), Vec_IntSize(vRes), 0 ); + //printf( "Created %d-bit %d-input AT with %d FAs and %d HAs.\n", Vec_WecSize(vProds), Vec_WecSizeSize(vProds), nFAs, nHAs ); } int Wlc_BlastAddLevel( Gia_Man_t * pNew, int Start ) @@ -1049,7 +1056,6 @@ void Wlc_BlastReduceMatrix2( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Int_t * v Vec_IntFree( vTemp ); } - void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds, int fVerbose ) { Vec_Wec_t * vProds = Vec_WecStart( nArgA + nArgB ); diff --git a/src/base/wln/wlnBlast.c b/src/base/wln/wlnBlast.c index c3281a2e0..87fbc0fb0 100644 --- a/src/base/wln/wlnBlast.c +++ b/src/base/wln/wlnBlast.c @@ -70,7 +70,7 @@ void Rtl_NtkBlastNode( Gia_Man_t * pNew, int Type, int nIns, Vec_Int_t * vDatas, extern void Wlc_BlastSubtract( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int Carry ); // result is in pAdd0 extern int Wlc_NtkCountConstBits( int * pArray, int nSize ); extern void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds, int fVerbose ); - extern void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ); + extern void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds, int fVerbose ); extern void Wlc_BlastZeroCondition( Gia_Man_t * pNew, int * pDiv, int nDiv, Vec_Int_t * vRes ); extern void Wlc_BlastDividerTop( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes, int fNonRest ); extern void Wlc_BlastDividerSigned( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes, int fNonRest ); @@ -305,7 +305,7 @@ void Rtl_NtkBlastNode( Gia_Man_t * pNew, int Type, int nIns, Vec_Int_t * vDatas, if ( fBooth ) Wlc_BlastBooth( pNew, Vec_IntArray(vArg0), Vec_IntArray(vArg1), Vec_IntSize(vArg0), Vec_IntSize(vArg1), vRes, fSigned, fCla, NULL, 0 ); else - Wlc_BlastMultiplier3( pNew, Vec_IntArray(vArg0), Vec_IntArray(vArg1), Vec_IntSize(vArg0), Vec_IntSize(vArg1), vRes, fSigned, fCla, NULL ); + Wlc_BlastMultiplier3( pNew, Vec_IntArray(vArg0), Vec_IntArray(vArg1), Vec_IntSize(vArg0), Vec_IntSize(vArg1), vRes, fSigned, fCla, NULL, 0 ); if ( nRange > Vec_IntSize(vRes) ) Vec_IntFillExtra( vRes, nRange, fSigned ? Vec_IntEntryLast(vRes) : 0 ); else diff --git a/src/bdd/cas/casCore.c b/src/bdd/cas/casCore.c index 21c21d200..23d7be521 100644 --- a/src/bdd/cas/casCore.c +++ b/src/bdd/cas/casCore.c @@ -460,18 +460,6 @@ void Experiment2( BFunc * pFunc ) /// SINGLE OUTPUT FUNCTION /// //////////////////////////////////////////////////////////////////////// -// the bit count for the first 256 integer numbers -//static unsigned char BitCount8[256] = { -// 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, -// 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, -// 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, -// 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, -// 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, -// 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, -// 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, -// 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 -//}; - ///////////////////////////////////////////////////////////// static int s_SuppSize[MAXOUTPUTS]; int CompareSupports( int *ptrX, int *ptrY ) diff --git a/src/bdd/dsd/dsd.h b/src/bdd/dsd/dsd.h index 4c5cd8915..2990c0259 100644 --- a/src/bdd/dsd/dsd.h +++ b/src/bdd/dsd/dsd.h @@ -115,7 +115,7 @@ extern int Dsd_TreeCountPrimeNodesOne( Dsd_Node_t * pRoot ); extern int Dsd_TreeCollectDecomposableVars( Dsd_Manager_t * dMan, int * pVars ); extern Dsd_Node_t ** Dsd_TreeCollectNodesDfs( Dsd_Manager_t * dMan, int * pnNodes ); extern Dsd_Node_t ** Dsd_TreeCollectNodesDfsOne( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pNode, int * pnNodes ); -extern void Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * dMan, char * pInputNames[], char * pOutputNames[], int fShortNames, int Output ); +extern void Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * dMan, char * pInputNames[], char * pOutputNames[], int fShortNames, int Output, int OffSet ); extern void Dsd_TreePrint2( FILE * pFile, Dsd_Manager_t * dMan, char * pInputNames[], char * pOutputNames[], int Output ); extern void Dsd_NodePrint( FILE * pFile, Dsd_Node_t * pNode ); /*=== dsdLocal.c =======================================================*/ diff --git a/src/bdd/dsd/dsdTree.c b/src/bdd/dsd/dsdTree.c index 9b9dd2121..42eee2cc5 100644 --- a/src/bdd/dsd/dsdTree.c +++ b/src/bdd/dsd/dsdTree.c @@ -638,7 +638,7 @@ void Dsd_TreeCollectNodesDfs_rec( Dsd_Node_t * pNode, Dsd_Node_t * ppNodes[], in SeeAlso [] ***********************************************************************/ -void Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * pDsdMan, char * pInputNames[], char * pOutputNames[], int fShortNames, int Output ) +void Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * pDsdMan, char * pInputNames[], char * pOutputNames[], int fShortNames, int Output, int OffSet ) { Dsd_Node_t * pNode; int SigCounter; @@ -650,14 +650,14 @@ void Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * pDsdMan, char * pInputNames[], for ( i = 0; i < pDsdMan->nRoots; i++ ) { pNode = Dsd_Regular( pDsdMan->pRoots[i] ); - Dsd_TreePrint_rec( pFile, pNode, (pNode != pDsdMan->pRoots[i]), pInputNames, pOutputNames[i], 0, &SigCounter, fShortNames ); + Dsd_TreePrint_rec( pFile, pNode, (pNode != pDsdMan->pRoots[i]), pInputNames, pOutputNames[i], OffSet, &SigCounter, fShortNames ); } } else { assert( Output >= 0 && Output < pDsdMan->nRoots ); pNode = Dsd_Regular( pDsdMan->pRoots[Output] ); - Dsd_TreePrint_rec( pFile, pNode, (pNode != pDsdMan->pRoots[Output]), pInputNames, pOutputNames[Output], 0, &SigCounter, fShortNames ); + Dsd_TreePrint_rec( pFile, pNode, (pNode != pDsdMan->pRoots[Output]), pInputNames, pOutputNames[Output], OffSet, &SigCounter, fShortNames ); } } @@ -686,7 +686,7 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp if ( !fComp ) fprintf( pFile, "%s = ", pOutputName ); else - fprintf( pFile, "NOT(%s) = ", pOutputName ); + fprintf( pFile, "~%s = ", pOutputName ); pInputNums = ABC_ALLOC( int, pNode->nDecs ); if ( pNode->Type == DSD_NODE_CONST1 ) { @@ -711,7 +711,7 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp if ( i ) fprintf( pFile, "," ); if ( fCompNew ) - fprintf( pFile, " NOT(" ); + fprintf( pFile, " ~" ); else fprintf( pFile, " " ); if ( pInput->Type == DSD_NODE_BUF ) @@ -727,8 +727,8 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp pInputNums[i] = (*pSigCounter)++; fprintf( pFile, "<%d>", pInputNums[i] ); } - if ( fCompNew ) - fprintf( pFile, ")" ); + //if ( fCompNew ) + // fprintf( pFile, "" ); } fprintf( pFile, " )\n" ); // call recursively for the following blocks @@ -751,7 +751,7 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp if ( i ) fprintf( pFile, "," ); if ( fCompNew ) - fprintf( pFile, " NOT(" ); + fprintf( pFile, " ~" ); else fprintf( pFile, " " ); if ( pInput->Type == DSD_NODE_BUF ) @@ -767,8 +767,8 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp pInputNums[i] = (*pSigCounter)++; fprintf( pFile, "<%d>", pInputNums[i] ); } - if ( fCompNew ) - fprintf( pFile, ")" ); + //if ( fCompNew ) + // fprintf( pFile, "" ); } fprintf( pFile, " )\n" ); // call recursively for the following blocks @@ -791,7 +791,7 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp if ( i ) fprintf( pFile, "," ); if ( fCompNew ) - fprintf( pFile, " NOT(" ); + fprintf( pFile, " ~" ); else fprintf( pFile, " " ); if ( pInput->Type == DSD_NODE_BUF ) @@ -807,8 +807,8 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp pInputNums[i] = (*pSigCounter)++; fprintf( pFile, "<%d>", pInputNums[i] ); } - if ( fCompNew ) - fprintf( pFile, ")" ); + //if ( fCompNew ) + // fprintf( pFile, "" ); } fprintf( pFile, " )\n" ); // call recursively for the following blocks @@ -979,7 +979,7 @@ void Dsd_NodePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pOut if ( !fComp ) fprintf( pFile, "%s = ", pOutputName ); else - fprintf( pFile, "NOT(%s) = ", pOutputName ); + fprintf( pFile, "~%s = ", pOutputName ); pInputNums = ABC_ALLOC( int, pNode->nDecs ); if ( pNode->Type == DSD_NODE_CONST1 ) { diff --git a/src/bdd/extrab/extraLutCas.h b/src/bdd/extrab/extraLutCas.h new file mode 100644 index 000000000..df7a14010 --- /dev/null +++ b/src/bdd/extrab/extraLutCas.h @@ -0,0 +1,72 @@ +/**CFile**************************************************************** + + FileName [extraLutCas.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [extra] + + Synopsis [LUT cascade decomposition.] + + Description [LUT cascade decomposition.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 6, 2024.] + + Revision [$Id: extraLutCas.h,v 1.00 2024/08/06 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__misc__extra__extra_lutcas_h +#define ABC__misc__extra__extra_lutcas_h + +#ifdef _WIN32 +#define inline __inline // compatible with MS VS 6.0 +#endif + +#include +#include +#include +#include + +#include "bdd/cudd/cuddInt.h" + +ABC_NAMESPACE_HEADER_START + +/* + The decomposed structure of the LUT cascade is represented as an array of 64-bit integers (words). + The first word in the record is the number of LUT info blocks in the record, which follow one by one. + Each LUT info block contains the following: + - the number of words in this block + - the number of fanins + - the list of fanins + - the variable ID of the output (can be one of the fanin variables) + - truth tables (one word for 6 vars or less; more words as needed for more than 6 vars) + For a 6-input node, the LUT info block takes 10 words (block size, fanin count, 6 fanins, output ID, truth table). + For a 4-input node, the LUT info block takes 8 words (block size, fanin count, 4 fanins, output ID, truth table). + If the LUT cascade contains a 6-LUT followed by a 4-LUT, the record contains 1+10+8=19 words. +*/ + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int fVerbose ) +{ + word * pLuts = NULL; + return pLuts; +} + +ABC_NAMESPACE_HEADER_END + +#endif /* __EXTRA_H__ */ diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp index d8a44b1d5..7628ab39e 100644 --- a/src/map/if/acd/ac_decomposition.hpp +++ b/src/map/if/acd/ac_decomposition.hpp @@ -40,6 +40,11 @@ #include "kitty_operators.hpp" #include "kitty_static_tt.hpp" +#ifdef _MSC_VER +# include +# define __builtin_popcount __popcnt +#endif + ABC_NAMESPACE_CXX_HEADER_START namespace acd @@ -459,7 +464,7 @@ private: if ( free_set_size == offset ) { best_cost = fn( tt ); - return { tt, permutations, best_cost }; + return std::make_tuple( tt, permutations, best_cost ); } /* works up to 16 input truth tables */ diff --git a/src/map/if/acd/ac_wrapper.cpp b/src/map/if/acd/ac_wrapper.cpp index ad923edd2..ed512961f 100644 --- a/src/map/if/acd/ac_wrapper.cpp +++ b/src/map/if/acd/ac_wrapper.cpp @@ -118,32 +118,25 @@ int acd2_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay return 0; } -inline int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition ) +inline int acd66_evaluate( word * pTruth, unsigned nVars ) { using namespace acd; + acd66_impl acd( nVars, true, false ); if ( acd.run( pTruth ) == 0 ) return 0; - if ( decomposition == NULL ) - return 1; - int val = acd.compute_decomposition(); - if ( val != 0 ) - { - return 0; - } - acd.get_decomposition( decomposition ); return 1; } -int acdXX_decompose( word * pTruth, unsigned lutSize, unsigned nVars, unsigned char *decomposition ) +int acdXX_evaluate( word * pTruth, unsigned lutSize, unsigned nVars ) { using namespace acd; if ( lutSize == 6 ) { - return acd66_decompose( pTruth, nVars, decomposition ); + return acd66_evaluate( pTruth, nVars ); } acdXX_params ps; @@ -153,14 +146,29 @@ int acdXX_decompose( word * pTruth, unsigned lutSize, unsigned nVars, unsigned c if ( acd.run( pTruth ) == 0 ) return 0; - if ( decomposition == NULL ) - return 1; - int val = acd.compute_decomposition(); - if ( val != 0 ) + + return 1; +} + +int acdXX_decompose( word * pTruth, unsigned lutSize, unsigned nVars, unsigned char *decomposition ) +{ + using namespace acd; + + acdXX_params ps; + ps.lut_size = lutSize; + + for ( int i = 0; i <= lutSize - 2; ++i ) { + ps.max_shared_vars = i; + ps.min_shared_vars = i; + acdXX_impl acd( nVars, ps ); + + if ( acd.run( pTruth ) == 0 ) + continue; + acd.compute_decomposition(); + acd.get_decomposition( decomposition ); return 0; } - acd.get_decomposition( decomposition ); return 1; } diff --git a/src/map/if/acd/ac_wrapper.h b/src/map/if/acd/ac_wrapper.h index edb45ca7f..47c9afe45 100644 --- a/src/map/if/acd/ac_wrapper.h +++ b/src/map/if/acd/ac_wrapper.h @@ -37,6 +37,7 @@ int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, int acd2_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); int acd2_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); +int acdXX_evaluate( word * pTruth, unsigned lutSize, unsigned nVars ); int acdXX_decompose( word * pTruth, unsigned lutSize, unsigned nVars, unsigned char *decomposition ); ABC_NAMESPACE_HEADER_END diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp index 109512986..607eee197 100644 --- a/src/map/if/acd/acd66.hpp +++ b/src/map/if/acd/acd66.hpp @@ -39,6 +39,11 @@ #include "kitty_operators.hpp" #include "kitty_static_tt.hpp" +#ifdef _MSC_VER +# include +# define __builtin_popcount __popcnt +#endif + ABC_NAMESPACE_CXX_HEADER_START namespace acd diff --git a/src/map/if/acd/acdXX.hpp b/src/map/if/acd/acdXX.hpp index e43404ea9..13d1bdddf 100644 --- a/src/map/if/acd/acdXX.hpp +++ b/src/map/if/acd/acdXX.hpp @@ -39,6 +39,11 @@ #include "kitty_operators.hpp" #include "kitty_static_tt.hpp" +#ifdef _MSC_VER +# include +# define __builtin_popcount __popcnt +#endif + ABC_NAMESPACE_CXX_HEADER_START namespace acd @@ -52,6 +57,9 @@ struct acdXX_params /* Maximum number of variables in the shared set */ uint32_t max_shared_vars{ 4 }; + /* Minimum number of variables in the shared set */ + uint32_t min_shared_vars{ 0 }; + /* Run verification */ bool verify{ false }; }; @@ -795,7 +803,7 @@ private: uint32_t max_shared_vars = std::min( ps.lut_size - best_free_set - 1, ps.max_shared_vars ); /* search for a feasible shared set */ - for ( uint32_t i = target_num_ss; i <= max_shared_vars; ++i ) + for ( uint32_t i = std::max( target_num_ss, ps.min_shared_vars ); i <= max_shared_vars; ++i ) { for ( uint32_t i = 0; i < 6; ++i ) { diff --git a/src/map/if/acd/kitty_operations.hpp b/src/map/if/acd/kitty_operations.hpp index e0292bc05..f1893144c 100644 --- a/src/map/if/acd/kitty_operations.hpp +++ b/src/map/if/acd/kitty_operations.hpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include "kitty_algorithm.hpp" diff --git a/src/map/if/acd/kitty_operators.hpp b/src/map/if/acd/kitty_operators.hpp index 7ccab7ca1..ded73b002 100644 --- a/src/map/if/acd/kitty_operators.hpp +++ b/src/map/if/acd/kitty_operators.hpp @@ -6,7 +6,6 @@ #include #include #include -#include #include "kitty_constants.hpp" #include "kitty_dynamic_tt.hpp" diff --git a/src/map/if/if.h b/src/map/if/if.h index 723fda780..136e61573 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -563,6 +563,8 @@ extern int If_CluCheckExt( void * p, word * pTruth, int nVars, int n char * pLut0, char * pLut1, word * pFunc0, word * pFunc1 ); extern int If_CluCheckExt3( void * p, word * pTruth, int nVars, int nLutLeaf, int nLutLeaf2, int nLutRoot, char * pLut0, char * pLut1, char * pLut2, word * pFunc0, word * pFunc1, word * pFunc2 ); +extern int If_CluCheckXXExt( void * p, word * pTruth, int nVars, int nLutLeaf, int nLutRoot, + char * pLut0, char * pLut1, word * pFunc0, word * pFunc1 ); extern int If_MatchCheck1( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_MatchCheck2( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); /*=== ifDelay.c =============================================================*/ diff --git a/src/map/if/ifDec07.c b/src/map/if/ifDec07.c index b8851e500..6311df6d1 100644 --- a/src/map/if/ifDec07.c +++ b/src/map/if/ifDec07.c @@ -29,17 +29,6 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -// the bit count for the first 256 integer numbers -static int BitCount8[256] = { - 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 -}; // variable swapping code static word PMasks[5][3] = { { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) }, @@ -208,7 +197,7 @@ static inline int If_Dec6CofCount2( word t ) int i, Mask = 0; for ( i = 0; i < 16; i++ ) Mask |= (1 << ((t >> (i<<2)) & 15)); - return BitCount8[((unsigned char*)&Mask)[0]] + BitCount8[((unsigned char*)&Mask)[1]]; + return __builtin_popcount( Mask & 0xffff ); } // count the number of unique cofactors (up to 3) static inline int If_Dec7CofCount3( word t[2] ) @@ -696,7 +685,7 @@ static inline word If_Dec5CofCount2( word t, int x, int y, int * Pla2Var, word t for ( Mask = i = 0; i < 16; i++ ) if ( ((i >> x) & 1) == ((m >> 0) & 1) && ((i >> y) & 1) == ((m >> 1) & 1) ) Mask |= (1 << ((t >> (i<<1)) & 3)); - if ( BitCount8[Mask & 0xF] > 2 ) + if ( __builtin_popcount( Mask & 0xF ) > 2 ) return 0; } // Kit_DsdPrintFromTruth( (unsigned *)&t, 5 ); printf( "\n" ); @@ -726,12 +715,12 @@ static inline word If_Dec5CofCount2( word t, int x, int y, int * Pla2Var, word t if ( ((i >> x) & 1) == ((m >> 0) & 1) && ((i >> y) & 1) == ((m >> 1) & 1) ) Mask |= (1 << ((t >> (i<<1)) & 3)); // find the values - if ( BitCount8[Mask & 0xF] == 1 ) + if ( __builtin_popcount( Mask & 0xF ) == 1 ) { C2[m] = F[Abc_Tt6FirstBit( Mask )]; D2[m] = ~(word)0; } - else if ( BitCount8[Mask & 0xF] == 2 ) + else if ( __builtin_popcount( Mask & 0xF ) == 2 ) { int Bit0 = Abc_Tt6FirstBit( Mask ); int Bit1 = Abc_Tt6FirstBit( Mask ^ (((word)1)< +# define __builtin_popcount __popcnt +#endif + ABC_NAMESPACE_IMPL_START @@ -29,17 +34,6 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -// the bit count for the first 256 integer numbers -static int BitCount8[256] = { - 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 -}; // variable swapping code static word PMasks[5][3] = { { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) }, @@ -374,7 +368,7 @@ void If_Dec08Cofactors( word * pF, int nVars, int iVar, word * pCof0, word * pCo static inline int If_Dec08Count16( int Num16 ) { assert( Num16 < (1<<16)-1 ); - return BitCount8[Num16 & 255] + BitCount8[(Num16 >> 8) & 255]; + return __builtin_popcount( Num16 & 0xffff ); } static inline void If_DecVerifyPerm( int Pla2Var[10], int Var2Pla[10], int nVars ) { diff --git a/src/map/if/ifDec10.c b/src/map/if/ifDec10.c index 00904a182..73717180b 100644 --- a/src/map/if/ifDec10.c +++ b/src/map/if/ifDec10.c @@ -22,6 +22,11 @@ #include "misc/extra/extra.h" #include "bool/kit/kit.h" +#ifdef _MSC_VER +# include +# define __builtin_popcount __popcnt +#endif + ABC_NAMESPACE_IMPL_START @@ -29,17 +34,6 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -// the bit count for the first 256 integer numbers -static int BitCount8[256] = { - 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 -}; // variable swapping code static word PMasks[5][3] = { { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) }, @@ -371,7 +365,7 @@ void If_Dec10Cofactors( word * pF, int nVars, int iVar, word * pCof0, word * pCo static inline int If_Dec10Count16( int Num16 ) { assert( Num16 < (1<<16)-1 ); - return BitCount8[Num16 & 255] + BitCount8[(Num16 >> 8) & 255]; + return __builtin_popcount( Num16 & 0xffff ); } static inline void If_DecVerifyPerm( int Pla2Var[10], int Var2Pla[10], int nVars ) { diff --git a/src/map/if/ifDec66.c b/src/map/if/ifDec66.c index 9c486685c..7ded4ad18 100644 --- a/src/map/if/ifDec66.c +++ b/src/map/if/ifDec66.c @@ -104,6 +104,27 @@ static inline int If_CluWordNum2( int nVars ) return nVars <= 6 ? 1 : 1 << (nVars-6); } +static inline word If_CluAdjust2( word t, int nVars ) +{ + assert( nVars >= 0 && nVars <= 6 ); + if ( nVars == 6 ) + return t; + t &= (((word)1) << (1 << nVars)) - 1; + if ( nVars == 0 ) + t |= t << (1< void Map_ManSetSwitching( Map_Man_t * p, int fSwitching ) { p->fSwitching = fSwitching; } void Map_ManSetSkipFanout( Map_Man_t * p, int fSkipFanout ) { p->fSkipFanout = fSkipFanout; } void Map_ManSetUseProfile( Map_Man_t * p ) { p->fUseProfile = 1; } +void Map_ManCreateAigIds( Map_Man_t * p, int nObjs ) { p->pAigNodeIDs = ABC_CALLOC( int, nObjs ); } /**Function************************************************************* @@ -91,6 +92,7 @@ Map_Man_t * Map_NodeReadMan( Map_Node_t * p ) { return p char * Map_NodeReadData( Map_Node_t * p, int fPhase ) { return fPhase? p->pData1 : p->pData0; } int Map_NodeReadNum( Map_Node_t * p ) { return p->Num; } int Map_NodeReadLevel( Map_Node_t * p ) { return Map_Regular(p)->Level; } +int Map_NodeReadAigId( Map_Node_t * p ) { return p->p->pAigNodeIDs[p->Num]; } Map_Cut_t * Map_NodeReadCuts( Map_Node_t * p ) { return p->pCuts; } Map_Cut_t * Map_NodeReadCutBest( Map_Node_t * p, int fPhase ) { return p->pCutBest[fPhase]; } Map_Node_t * Map_NodeReadOne( Map_Node_t * p ) { return p->p1; } @@ -99,6 +101,10 @@ void Map_NodeSetData( Map_Node_t * p, int fPhase, char * pData ) { if void Map_NodeSetNextE( Map_Node_t * p, Map_Node_t * pNextE ) { p->pNextE = pNextE; } void Map_NodeSetRepr( Map_Node_t * p, Map_Node_t * pRepr ) { p->pRepr = pRepr; } void Map_NodeSetSwitching( Map_Node_t * p, float Switching ) { p->Switching = Switching; } +void Map_NodeSetAigId( Map_Node_t * p, int Id ) { p->p->pAigNodeIDs[p->Num] = Id; } + +; + /**Function************************************************************* @@ -261,6 +267,7 @@ void Map_ManFree( Map_Man_t * p ) if ( p->pCounters ) ABC_FREE( p->pCounters ); Extra_MmFixedStop( p->mmNodes ); Extra_MmFixedStop( p->mmCuts ); + ABC_FREE( p->pAigNodeIDs ); ABC_FREE( p->pNodeDelays ); ABC_FREE( p->pInputArrivals ); ABC_FREE( p->pOutputRequireds ); diff --git a/src/map/mapper/mapperCutUtils.c b/src/map/mapper/mapperCutUtils.c index aa307368b..18e5a009a 100644 --- a/src/map/mapper/mapperCutUtils.c +++ b/src/map/mapper/mapperCutUtils.c @@ -219,6 +219,51 @@ int Map_CutListCount( Map_Cut_t * pSets ) return i; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_CutInternalNodes_rec( Map_Node_t * pObj, Vec_Ptr_t * vAnds ) +{ + if ( pObj->TravId == pObj->p->nTravIds ) + return; + pObj->TravId = pObj->p->nTravIds; + Map_CutInternalNodes_rec( Map_Regular(pObj->p1), vAnds ); + Map_CutInternalNodes_rec( Map_Regular(pObj->p2), vAnds ); + Vec_PtrPush( vAnds, pObj ); +} +Vec_Ptr_t * Map_CutInternalNodes( Map_Node_t * pObj, Map_Cut_t * pCut ) +{ + Vec_Ptr_t * vAnds = Vec_PtrAlloc( 4 ); + Map_Node_t * pTemp; int i; + pObj->p->nTravIds++; + for ( i = 0; i < pCut->nLeaves; i++ ) + pCut->ppLeaves[i]->TravId = pObj->p->nTravIds; + Map_CutInternalNodes_rec( pObj, vAnds ); + if ( 0 ) + { + printf( "Leaves:\n" ); + for ( i = 0; i < pCut->nLeaves; i++ ) + printf( " %d", pCut->ppLeaves[i]->Num ); + printf( "\n" ); + printf( "Nodes:\n" ); + Vec_PtrForEachEntry( Map_Node_t *, vAnds, pTemp, i ) + printf( "%d = %s%d & %s%d\n", pTemp->Num, + Map_IsComplement(pTemp->p1) ? "~" : " ", Map_Regular(pTemp->p1)->Num, + Map_IsComplement(pTemp->p2) ? "~" : " ", Map_Regular(pTemp->p2)->Num ); + printf( "\n" ); + } + return vAnds; +} + + #if 0 /**function************************************************************* diff --git a/src/map/mapper/mapperInt.h b/src/map/mapper/mapperInt.h index 79c8d61ad..768255a8a 100644 --- a/src/map/mapper/mapperInt.h +++ b/src/map/mapper/mapperInt.h @@ -107,6 +107,7 @@ struct Map_ManStruct_t_ char ** ppOutputNames; // the primary output names Map_Time_t * pInputArrivals;// the PI arrival times Map_Time_t * pOutputRequireds;// the PI arrival times + int * pAigNodeIDs; // IDs of the original AIG nodes // mapping parameters int nVarsMax; // the max number of variables diff --git a/src/map/mapper/mapperSuper.c b/src/map/mapper/mapperSuper.c index 0c33d5800..049c7cc52 100644 --- a/src/map/mapper/mapperSuper.c +++ b/src/map/mapper/mapperSuper.c @@ -115,7 +115,7 @@ int Map_LibraryReadFile( Map_SuperLib_t * pLib, FILE * pFile ) fclose( pFileGen ); // read the genlib library - pLib->pGenlib = Mio_LibraryRead( pLibName, NULL, 0, 0 ); + pLib->pGenlib = Mio_LibraryRead( pLibName, NULL, 0, 0, 0 ); if ( pLib->pGenlib == NULL ) { printf( "Cannot read genlib file \"%s\".\n", pLibName ); diff --git a/src/map/mio/mio.c b/src/map/mio/mio.c index 9ca6767db..cfe5d3e8c 100644 --- a/src/map/mio/mio.c +++ b/src/map/mio/mio.c @@ -152,7 +152,7 @@ int Mio_UpdateGenlib2( Vec_Str_t * vStr, Vec_Str_t * vStr2, char * pFileName, in { Mio_Library_t * pLib; // set the new network - pLib = Mio_LibraryRead( pFileName, Vec_StrArray(vStr), NULL, fVerbose ); + pLib = Mio_LibraryRead( pFileName, Vec_StrArray(vStr), NULL, 0, fVerbose ); if ( pLib == NULL ) return 0; @@ -291,12 +291,13 @@ int Mio_CommandReadGenlib( Abc_Frame_t * pAbc, int argc, char **argv ) char * pExcludeFile = NULL; double WireDelay = 0.0; int fShortNames = 0; + int nFaninLimit = 0; int c, fVerbose = 1; pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "WEnvh")) != EOF ) + while ( (c = Extra_UtilGetopt(argc, argv, "WEKnvh")) != EOF ) { switch (c) { @@ -320,6 +321,15 @@ int Mio_CommandReadGenlib( Abc_Frame_t * pAbc, int argc, char **argv ) pExcludeFile = argv[globalUtilOptind]; globalUtilOptind++; break; + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by a file name.\n" ); + goto usage; + } + nFaninLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; case 'n': fShortNames ^= 1; break; @@ -351,7 +361,7 @@ int Mio_CommandReadGenlib( Abc_Frame_t * pAbc, int argc, char **argv ) fclose( pFile ); // set the new network - pLib = Mio_LibraryRead( pFileName, NULL, pExcludeFile, fVerbose ); + pLib = Mio_LibraryRead( pFileName, NULL, pExcludeFile, nFaninLimit, fVerbose ); if ( pLib == NULL ) { fprintf( pErr, "Reading genlib library has failed.\n" ); @@ -382,13 +392,14 @@ int Mio_CommandReadGenlib( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; usage: - fprintf( pErr, "usage: read_genlib [-W float] [-E filename] [-nvh]\n"); + fprintf( pErr, "usage: read_genlib [-W float] [-E filename] [-K num] [-nvh]\n"); fprintf( pErr, "\t read the library from a genlib file\n" ); fprintf( pErr, "\t (if the library contains more than one gate\n" ); fprintf( pErr, "\t with the same Boolean function, only the gate\n" ); fprintf( pErr, "\t with the smallest area will be used)\n" ); fprintf( pErr, "\t-W float : wire delay (added to pin-to-pin gate delays) [default = %g]\n", WireDelay ); - fprintf( pErr, "\t-E file : the file name with gates to be excluded [default = none]\n" ); + fprintf( pErr, "\t-E file : the file name with gates to be excluded [default = none]\n" ); + fprintf( pErr, "\t-K num : the max number of gate fanins (0 = no limit) [default = %d]\n", nFaninLimit ); fprintf( pErr, "\t-n : toggle replacing gate/pin names by short strings [default = %s]\n", fShortNames? "yes": "no" ); fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pErr, "\t-h : enable verbose output\n"); diff --git a/src/map/mio/mio.h b/src/map/mio/mio.h index 18e3b92b0..ce6f0aa9b 100644 --- a/src/map/mio/mio.h +++ b/src/map/mio/mio.h @@ -178,7 +178,7 @@ extern double Mio_PinReadDelayBlockMax ( Mio_Pin_t * pPin ); extern Mio_Pin_t * Mio_PinReadNext ( Mio_Pin_t * pPin ); /*=== mioRead.c =============================================================*/ extern char * Mio_ReadFile( char * FileName, int fAddEnd ); -extern Mio_Library_t * Mio_LibraryRead( char * FileName, char * pBuffer, char * ExcludeFile, int fVerbose ); +extern Mio_Library_t * Mio_LibraryRead( char * FileName, char * pBuffer, char * ExcludeFile, int nFaninLimit, int fVerbose ); extern int Mio_LibraryReadExclude( char * ExcludeFile, st__table * tExcludeGate ); /*=== mioFunc.c =============================================================*/ extern int Mio_LibraryParseFormulas( Mio_Library_t * pLib ); @@ -230,8 +230,6 @@ extern void Mio_LibraryMatches2Fetch( Mio_Library_t * pLib, Vec_Ptr /*=== sclUtil.c =========================================================*/ extern Mio_Library_t * Abc_SclDeriveGenlibSimple( void * pScl ); extern Mio_Library_t * Abc_SclDeriveGenlib( void * pScl, void * pMio, float Slew, float Gain, int nGatesMin, int fVerbose ); -extern int Abc_SclHasDelayInfo( void * pScl ); - ABC_NAMESPACE_HEADER_END diff --git a/src/map/mio/mioRead.c b/src/map/mio/mioRead.c index c19c07d4d..79d5dc4ef 100644 --- a/src/map/mio/mioRead.c +++ b/src/map/mio/mioRead.c @@ -31,9 +31,9 @@ ABC_NAMESPACE_IMPL_START /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// -static Mio_Library_t * Mio_LibraryReadOne( char * FileName, int fExtendedFormat, st__table * tExcludeGate, int fVerbose ); - Mio_Library_t * Mio_LibraryReadBuffer( char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int fVerbose ); -static int Mio_LibraryReadInternal( Mio_Library_t * pLib, char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int fVerbose ); +static Mio_Library_t * Mio_LibraryReadOne( char * FileName, int fExtendedFormat, st__table * tExcludeGate, int nFaninLimit, int fVerbose ); + Mio_Library_t * Mio_LibraryReadBuffer( char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int nFaninLimit, int fVerbose ); +static int Mio_LibraryReadInternal( Mio_Library_t * pLib, char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int nFaninLimit, int fVerbose ); static Mio_Gate_t * Mio_LibraryReadGate( char ** ppToken, int fExtendedFormat ); static Mio_Pin_t * Mio_LibraryReadPin( char ** ppToken, int fExtendedFormat ); static char * chomp( char *s ); @@ -51,7 +51,7 @@ static void Io_ReadFileRemoveComments( char * pBuffer, int * pnDots, SeeAlso [] ***********************************************************************/ -Mio_Library_t * Mio_LibraryRead( char * FileName, char * pBuffer, char * ExcludeFile, int fVerbose ) +Mio_Library_t * Mio_LibraryRead( char * FileName, char * pBuffer, char * ExcludeFile, int nFaninLimit, int fVerbose ) { Mio_Library_t * pLib; int num; @@ -73,20 +73,20 @@ Mio_Library_t * Mio_LibraryRead( char * FileName, char * pBuffer, char * Exclude pBufferCopy = Abc_UtilStrsav(pBuffer); if ( pBuffer == NULL ) - pLib = Mio_LibraryReadOne( FileName, 0, tExcludeGate, fVerbose ); // try normal format first .. + pLib = Mio_LibraryReadOne( FileName, 0, tExcludeGate, nFaninLimit, fVerbose ); // try normal format first .. else { - pLib = Mio_LibraryReadBuffer( pBuffer, 0, tExcludeGate, fVerbose ); // try normal format first .. + pLib = Mio_LibraryReadBuffer( pBuffer, 0, tExcludeGate, nFaninLimit, fVerbose ); // try normal format first .. if ( pLib ) pLib->pName = Abc_UtilStrsav( Extra_FileNameGenericAppend(FileName, ".genlib") ); } if ( pLib == NULL ) { if ( pBuffer == NULL ) - pLib = Mio_LibraryReadOne( FileName, 1, tExcludeGate, fVerbose ); // try normal format first .. + pLib = Mio_LibraryReadOne( FileName, 1, tExcludeGate, nFaninLimit, fVerbose ); // try normal format first .. else { - pLib = Mio_LibraryReadBuffer( pBufferCopy, 1, tExcludeGate, fVerbose ); // try normal format first .. + pLib = Mio_LibraryReadBuffer( pBufferCopy, 1, tExcludeGate, nFaninLimit, fVerbose ); // try normal format first .. if ( pLib ) pLib->pName = Abc_UtilStrsav( Extra_FileNameGenericAppend(FileName, ".genlib") ); } @@ -152,7 +152,7 @@ char * Mio_ReadFile( char * FileName, int fAddEnd ) SeeAlso [] ***********************************************************************/ -Mio_Library_t * Mio_LibraryReadBuffer( char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int fVerbose ) +Mio_Library_t * Mio_LibraryReadBuffer( char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int nFaninLimit, int fVerbose ) { Mio_Library_t * pLib; @@ -165,7 +165,7 @@ Mio_Library_t * Mio_LibraryReadBuffer( char * pBuffer, int fExtendedFormat, st__ Io_ReadFileRemoveComments( pBuffer, NULL, NULL ); // parse the contents of the file - if ( Mio_LibraryReadInternal( pLib, pBuffer, fExtendedFormat, tExcludeGate, fVerbose ) ) + if ( Mio_LibraryReadInternal( pLib, pBuffer, fExtendedFormat, tExcludeGate, nFaninLimit, fVerbose ) ) { Mio_LibraryDelete( pLib ); return NULL; @@ -196,7 +196,7 @@ Mio_Library_t * Mio_LibraryReadBuffer( char * pBuffer, int fExtendedFormat, st__ SeeAlso [] ***********************************************************************/ -Mio_Library_t * Mio_LibraryReadOne( char * FileName, int fExtendedFormat, st__table * tExcludeGate, int fVerbose ) +Mio_Library_t * Mio_LibraryReadOne( char * FileName, int fExtendedFormat, st__table * tExcludeGate, int nFaninLimit, int fVerbose ) { Mio_Library_t * pLib; char * pBuffer; @@ -207,7 +207,7 @@ Mio_Library_t * Mio_LibraryReadOne( char * FileName, int fExtendedFormat, st__ta pBuffer = Mio_ReadFile( FileName, 1 ); if ( pBuffer == NULL ) return NULL; - pLib = Mio_LibraryReadBuffer( pBuffer, fExtendedFormat, tExcludeGate, fVerbose ); + pLib = Mio_LibraryReadBuffer( pBuffer, fExtendedFormat, tExcludeGate, nFaninLimit, fVerbose ); ABC_FREE( pBuffer ); if ( pLib ) pLib->pName = Abc_UtilStrsav( FileName ); @@ -225,7 +225,7 @@ Mio_Library_t * Mio_LibraryReadOne( char * FileName, int fExtendedFormat, st__ta SeeAlso [] ***********************************************************************/ -int Mio_LibraryReadInternal( Mio_Library_t * pLib, char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int fVerbose ) +int Mio_LibraryReadInternal( Mio_Library_t * pLib, char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int nFaninLimit, int fVerbose ) { Mio_Gate_t * pGate, ** ppGate; char * pToken; @@ -262,6 +262,19 @@ int Mio_LibraryReadInternal( Mio_Library_t * pLib, char * pBuffer, int fExtended if ( pGate == NULL ) return 1; + // consider the fanin limit + if ( nFaninLimit ) + { + Mio_Pin_t * pPin; int nIns = 0; + for ( pPin = Mio_GateReadPins(pGate); pPin; pPin = Mio_PinReadNext(pPin) ) + nIns++; + if ( nIns > nFaninLimit ) + { + Mio_GateDelete( pGate ); + continue; + } + } + // skip the gate if its formula has problems if ( !Mio_ParseCheckFormula(pGate, pGate->pForm) ) { diff --git a/src/map/scl/sclLibUtil.c b/src/map/scl/sclLibUtil.c index 9624be93e..147c67f3e 100644 --- a/src/map/scl/sclLibUtil.c +++ b/src/map/scl/sclLibUtil.c @@ -846,7 +846,7 @@ Mio_Library_t * Abc_SclDeriveGenlibSimple( void * pScl ) { SC_Lib * p = (SC_Lib *)pScl; Vec_Str_t * vStr = Abc_SclProduceGenlibStrSimple( p ); - Mio_Library_t * pLib = Mio_LibraryRead( p->pFileName, Vec_StrArray(vStr), NULL, 0 ); + Mio_Library_t * pLib = Mio_LibraryRead( p->pFileName, Vec_StrArray(vStr), NULL, 0, 0 ); Vec_StrFree( vStr ); if ( pLib ) printf( "Derived GENLIB library \"%s\" with %d gates.\n", p->pName, SC_LibCellNum(p) ); @@ -1029,7 +1029,7 @@ Mio_Library_t * Abc_SclDeriveGenlib( void * pScl, void * pMio, float SlewInit, f vStr = Abc_SclProduceGenlibStr( p, Slew, Gain, nGatesMin, &nCellCount ); else vStr = Abc_SclProduceGenlibStrProfile( p, (Mio_Library_t *)pMio, Slew, Gain, nGatesMin, &nCellCount ); - pLib = Mio_LibraryRead( p->pFileName, Vec_StrArray(vStr), NULL, 0 ); + pLib = Mio_LibraryRead( p->pFileName, Vec_StrArray(vStr), NULL, 0, 0 ); Vec_StrFree( vStr ); if ( !pLib ) printf( "Reading library has filed.\n" ); diff --git a/src/map/super/super.c b/src/map/super/super.c index 7868ba78e..21b193845 100644 --- a/src/map/super/super.c +++ b/src/map/super/super.c @@ -267,7 +267,7 @@ int Super_CommandSupergates( Abc_Frame_t * pAbc, int argc, char **argv ) fclose( pFile ); // set the new network - pLib = Mio_LibraryRead( FileName, NULL, ExcludeFile, fVerbose ); + pLib = Mio_LibraryRead( FileName, NULL, ExcludeFile, nVarsMax, fVerbose ); if ( pLib == NULL ) { fprintf( pErr, "Reading library has failed.\n" ); diff --git a/src/misc/util/abc_global.h b/src/misc/util/abc_global.h index 909046082..96944d7cc 100644 --- a/src/misc/util/abc_global.h +++ b/src/misc/util/abc_global.h @@ -549,6 +549,9 @@ extern int * Abc_QuickSortCost( int * pCosts, int nSize, int fDecrease ); extern unsigned Abc_Random( int fReset ); extern word Abc_RandomW( int fReset ); +// pthreads +extern void Util_ProcessThreads( int (*pUserFunc)(void *), void * vData, int nProcs, int TimeOut, int fVerbose ); + ABC_NAMESPACE_HEADER_END #endif diff --git a/src/misc/util/module.make b/src/misc/util/module.make index 5b3601bbb..66e87653f 100644 --- a/src/misc/util/module.make +++ b/src/misc/util/module.make @@ -4,5 +4,6 @@ SRC += src/misc/util/utilBridge.c \ src/misc/util/utilFile.c \ src/misc/util/utilIsop.c \ src/misc/util/utilNam.c \ + src/misc/util/utilPth.c \ src/misc/util/utilSignal.c \ src/misc/util/utilSort.c diff --git a/src/misc/util/utilPth.c b/src/misc/util/utilPth.c new file mode 100644 index 000000000..06581e9fe --- /dev/null +++ b/src/misc/util/utilPth.c @@ -0,0 +1,191 @@ +/**CFile**************************************************************** + + FileName [utilPth.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Generic interface to pthreads.] + + Synopsis [Generic interface to pthreads.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 3, 2024.] + + Revision [$Id: utilPth.c,v 1.00 2024/08/03 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include +#include +#include + +#ifdef ABC_USE_PTHREADS + +#ifdef _WIN32 +#include "../lib/pthread.h" +#else +#include +#endif + +#ifdef __cplusplus +#include +using namespace std; +#else +#include +#endif + +#endif + +#include "misc/vec/vec.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +#ifndef ABC_USE_PTHREADS + +void Util_ProcessThreads( int (*pUserFunc)(void *), void * vData, int nProcs, int TimeOut, int fVerbose ) +{ + void * pData; int i; + Vec_PtrForEachEntry( void *, (Vec_Ptr_t *)vData, pData, i ) + pUserFunc( pData ); +} + +#else // pthreads are used + +#define PAR_THR_MAX 100 +typedef struct Util_ThData_t_ +{ + void * pUserData; + int (*pUserFunc)(void *); + int iThread; + int nTimeOut; + atomic_bool fWorking; +} Util_ThData_t; + +void * Util_Thread( void * pArg ) +{ + struct timespec pause_duration; + pause_duration.tv_sec = 0; + pause_duration.tv_nsec = 10000000L; // 10 milliseconds + + Util_ThData_t * pThData = (Util_ThData_t *)pArg; + while ( 1 ) + { + while ( !atomic_load_explicit((atomic_bool *)&pThData->fWorking, memory_order_acquire) ) + nanosleep(&pause_duration, NULL); + if ( pThData->pUserData == NULL ) + { + pthread_exit( NULL ); + assert( 0 ); + return NULL; + } + pThData->pUserFunc( pThData->pUserData ); + atomic_store_explicit(&pThData->fWorking, 0, memory_order_release); + } + assert( 0 ); + return NULL; +} + +void Util_ProcessThreads( int (*pUserFunc)(void *), void * vData, int nProcs, int TimeOut, int fVerbose ) +{ + //abctime clkStart = Abc_Clock(); + Util_ThData_t ThData[PAR_THR_MAX]; + pthread_t WorkerThread[PAR_THR_MAX]; + Vec_Ptr_t * vStack = NULL; + int i, status; + fflush( stdout ); + if ( nProcs <= 2 ) { + void * pData; int i; + Vec_PtrForEachEntry( void *, (Vec_Ptr_t *)vData, pData, i ) + pUserFunc( pData ); + return; + } + // subtract manager thread + nProcs--; + assert( nProcs >= 1 && nProcs <= PAR_THR_MAX ); + // start threads + for ( i = 0; i < nProcs; i++ ) + { + ThData[i].pUserData = NULL; + ThData[i].pUserFunc = pUserFunc; + ThData[i].iThread = i; + ThData[i].nTimeOut = TimeOut; + atomic_store_explicit(&ThData[i].fWorking, 0, memory_order_release); + status = pthread_create( WorkerThread + i, NULL, Util_Thread, (void *)(ThData + i) ); assert( status == 0 ); + } + + struct timespec pause_duration; + pause_duration.tv_sec = 0; + pause_duration.tv_nsec = 10000000L; // 10 milliseconds + + // look at the threads + vStack = Vec_PtrDup( (Vec_Ptr_t *)vData ); + while ( Vec_PtrSize(vStack) > 0 ) + { + for ( i = 0; i < nProcs; i++ ) + { + if ( atomic_load_explicit(&ThData[i].fWorking, memory_order_acquire) ) + continue; + ThData[i].pUserData = Vec_PtrPop( vStack ); + atomic_store_explicit(&ThData[i].fWorking, 1, memory_order_release); + break; + } + } + Vec_PtrFree( vStack ); + + // wait till threads finish + for ( i = 0; i < nProcs; i++ ) + { + if ( atomic_load_explicit(&ThData[i].fWorking, memory_order_acquire) ) + i = -1; // Start from the beginning again + nanosleep(&pause_duration, NULL); + } + + // stop threads + for ( i = 0; i < nProcs; i++ ) + { + ThData[i].pUserData = NULL; + atomic_store_explicit(&ThData[i].fWorking, 1, memory_order_release); + } + + // Join threads + for ( i = 0; i < nProcs; i++ ) + pthread_join( WorkerThread[i], NULL ); + + //if ( fVerbose ) + // Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); +} + +#endif // pthreads are used + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/misc/util/utilSort.c b/src/misc/util/utilSort.c index a748caf95..0bbd7d289 100644 --- a/src/misc/util/utilSort.c +++ b/src/misc/util/utilSort.c @@ -1003,8 +1003,13 @@ void Abc_QuickSortTest() unsigned Abc_Random( int fReset ) { +#ifdef _MSC_VER static unsigned int m_z = NUMBER1; static unsigned int m_w = NUMBER2; +#else + static __thread unsigned int m_z = NUMBER1; + static __thread unsigned int m_w = NUMBER2; +#endif if ( fReset ) { m_z = NUMBER1; diff --git a/src/misc/util/utilTruth.h b/src/misc/util/utilTruth.h index 2624f9463..35f0f83e4 100644 --- a/src/misc/util/utilTruth.h +++ b/src/misc/util/utilTruth.h @@ -25,6 +25,11 @@ /// INCLUDES /// //////////////////////////////////////////////////////////////////////// +#ifdef _MSC_VER +# include +# define __builtin_popcount __popcnt +#endif + //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// @@ -129,18 +134,7 @@ static word s_PPMasks[5][6][3] = { } }; -// the bit count for the first 256 integer numbers -static int Abc_TtBitCount8[256] = { - 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 -}; -static inline int Abc_TtBitCount16( int i ) { return Abc_TtBitCount8[i & 0xFF] + Abc_TtBitCount8[i >> 8]; } +static inline int Abc_TtBitCount16( int i ) { return __builtin_popcount( i & 0xffff ); } //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// diff --git a/src/misc/vec/vecWrd.h b/src/misc/vec/vecWrd.h index b0d16efe6..5bfee43fb 100644 --- a/src/misc/vec/vecWrd.h +++ b/src/misc/vec/vecWrd.h @@ -1368,6 +1368,27 @@ static inline void Vec_WrdDumpBool( char * pFileName, Vec_Wrd_t * p, int nWords, printf( "Written %d bits of simulation data for %d objects into file \"%s\".\n", nBits, Vec_WrdSize(p)/nWords, pFileName ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_WrdPrintBin( Vec_Wrd_t * p, int nWords ) +{ + int i, k, nNodes = Vec_WrdSize(p) / nWords; + assert( Vec_WrdSize(p) % nWords == 0 ); + printf( "The array contains %d bit-strings of %d bits:\n", nNodes, 64*nWords ); + for ( i = 0; i < nNodes; i++, printf("\n") ) + for ( k = 0; k < 64*nWords; k++ ) + printf( "%d", Abc_InfoHasBit((unsigned*)Vec_WrdEntryP(p, i*nWords), k) ); +} + /**Function************************************************************* Synopsis [] @@ -1396,6 +1417,7 @@ static inline void Vec_WrdPrintHex( Vec_Wrd_t * p, int nWords ) { int i, nNodes = Vec_WrdSize(p) / nWords; assert( Vec_WrdSize(p) % nWords == 0 ); + printf( "The array contains %d bit-strings of %d bits:\n", nNodes, 64*nWords ); for ( i = 0; i < nNodes; i++ ) Vec_WrdDumpHexOne( stdout, Vec_WrdEntryP(p, i*nWords), nWords ); } diff --git a/src/opt/dau/dauCanon.c b/src/opt/dau/dauCanon.c index dd954d9a7..bd97c280c 100644 --- a/src/opt/dau/dauCanon.c +++ b/src/opt/dau/dauCanon.c @@ -24,6 +24,11 @@ #include "bool/lucky/lucky.h" #include +#ifdef _MSC_VER +# include +# define __builtin_popcount __popcnt +#endif + ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// @@ -380,7 +385,7 @@ static int Abc_TtScc6(word wTruth, int ck) if (!wTruth) return 0; for (i = 0; i < 64; i++) if (wTruth & (word)1 << i) { - int ci = Abc_TtBitCount8[i] + ck; + int ci = __builtin_popcount( i & 0xff ) + ck; sum += shiftFunc(ci); } return sum; @@ -406,7 +411,7 @@ static inline void Abc_TtSccInCofs6(word wTruth, int nVars, int ck, int * pStore { if (wTruth & (word)1 << j) { - int ci = Abc_TtBitCount8[i] + ck; + int ci = __builtin_popcount( i & 0xff ) + ck; sum += shiftFunc(ci); } i++; diff --git a/src/opt/dau/dauNpn.c b/src/opt/dau/dauNpn.c index 2b9e1915d..71cc857b6 100644 --- a/src/opt/dau/dauNpn.c +++ b/src/opt/dau/dauNpn.c @@ -800,6 +800,65 @@ void Dau_FunctionEnum( int nInputs, int nVars, int nNodeMax, int fUseTwo, int fR fflush(stdout); } +/**Function************************************************************* + + Synopsis [Function enumeration.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Mem_t * Dau_CollectNpnFunctions( word * p, int nVars, int fVerbose ) +{ + abctime clkStart = Abc_Clock(); + Vec_Mem_t * vTtMem = Vec_MemAllocForTTSimple( nVars ); + int nWords = Abc_Truth6WordNum(nVars); + word * pCopy = ABC_ALLOC( word, nWords ); + Abc_TtCopy( pCopy, p, nWords, p[0] & 1 ); + Vec_MemHashInsert( vTtMem, pCopy ); + int nPerms = Extra_Factorial( nVars ); + int nMints = 1 << nVars; + int * pPerm = Extra_PermSchedule( nVars ); + int * pComp = Extra_GreyCodeSchedule( nVars ); + int m, i, k, nFuncs; + for ( m = 0; m < nMints; m++ ) { + Abc_TtFlip( pCopy, nWords, pComp[m] ); + if ( pCopy[0] & 1 ) { + Abc_TtNot( pCopy, nWords ); + assert( (pCopy[0] & 1) == 0 ); + Vec_MemHashInsert( vTtMem, pCopy ); + Abc_TtNot( pCopy, nWords ); + } + else + Vec_MemHashInsert( vTtMem, pCopy ); + } + assert( Abc_TtEqual(pCopy, Vec_MemReadEntry(vTtMem, 0), nWords) ); + nFuncs = Vec_MemEntryNum(vTtMem); + if ( fVerbose ) + printf( "Collected %d NN functions and ", nFuncs ), fflush(stdout); + for ( i = 0; i < nFuncs; i++ ) { + Abc_TtCopy( pCopy, Vec_MemReadEntry(vTtMem, i), nWords, 0 ); + for ( k = 0; k < nPerms; k++ ) { + Abc_TtSwapAdjacent( pCopy, nWords, pPerm[k] ); + assert( (pCopy[0] & 1) == 0 ); + Vec_MemHashInsert( vTtMem, pCopy ); + } + assert( Abc_TtEqual(pCopy, Vec_MemReadEntry(vTtMem, i), nWords) ); + } + ABC_FREE( pPerm ); + ABC_FREE( pComp ); + ABC_FREE( pCopy ); + nFuncs = Vec_MemEntryNum(vTtMem); + if ( fVerbose ) + printf( "%d NPN functions. ", nFuncs ), + Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ), + fflush(stdout); + return vTtMem; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/opt/lpk/lpkCore.c b/src/opt/lpk/lpkCore.c index cc6087e89..58de15e88 100644 --- a/src/opt/lpk/lpkCore.c +++ b/src/opt/lpk/lpkCore.c @@ -46,12 +46,12 @@ ABC_NAMESPACE_IMPL_START ***********************************************************************/ Abc_Ntk_t * Abc_NtkDecFromTruth( word * pTruth, int nVars, int nLutSize ) { - extern Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ); + extern Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtk, int nLutSize, int fReorder, int fVerbose ); Vec_Int_t * vCover = Vec_IntAlloc( 1 << 16 ); Abc_Ntk_t * pTemp = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); char * pSopCover = Abc_SopCreateFromTruthIsop( (Mem_Flex_t *)pTemp->pManFunc, nVars, pTruth, vCover ); Abc_Ntk_t * pNtk = Abc_NtkCreateWithNode( pSopCover ); - Abc_Ntk_t * pNew = Abc_NtkLutmin( pNtk, nLutSize, 0 ); + Abc_Ntk_t * pNew = Abc_NtkLutmin( pNtk, nLutSize, 1, 0 ); Abc_NtkDelete( pTemp ); Abc_NtkDelete( pNtk ); Vec_IntFree( vCover ); diff --git a/src/proof/cec/cec.h b/src/proof/cec/cec.h index c9aa96658..10101e6c0 100644 --- a/src/proof/cec/cec.h +++ b/src/proof/cec/cec.h @@ -122,6 +122,7 @@ struct Cec_ParFra_t_ int iOutFail; // the failed output int fBMiterInfo; // printing BMiter information int nPO; // number of po in original design given a bmiter + char * pDumpName; // file name to dump statistics }; // combinational equivalence checking parameters diff --git a/src/proof/cec/cecCorr.c b/src/proof/cec/cecCorr.c index d1d8958fc..550ea4541 100644 --- a/src/proof/cec/cecCorr.c +++ b/src/proof/cec/cecCorr.c @@ -1269,6 +1269,171 @@ Gia_Man_t * Cec_ManLSCorrespondence( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) return pNew; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManCreateRegSupps( Gia_Man_t * p, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Gia_Obj_t * pObj; int i, Id; + Vec_Wec_t * vSuppsR = Vec_WecStart( Gia_ManRegNum(p) ); + Vec_Wec_t * vSupps = Vec_WecStart( Gia_ManObjNum(p) ); + Gia_ManForEachRo( p, pObj, i ) + Vec_IntPush( Vec_WecEntry(vSupps, Gia_ObjId(p, pObj)), i ); + Gia_ManForEachAnd( p, pObj, Id ) + Vec_IntTwoMerge2( Vec_WecEntry(vSupps, Gia_ObjFaninId0(pObj, Id)), + Vec_WecEntry(vSupps, Gia_ObjFaninId1(pObj, Id)), + Vec_WecEntry(vSupps, Id) ); + Gia_ManForEachRi( p, pObj, i ) + Vec_IntAppend( Vec_WecEntry(vSuppsR, i), Vec_WecEntry(vSupps, Gia_ObjFaninId0p(p, pObj)) ); + Vec_WecFree( vSupps ); + if ( fVerbose ) + Abc_PrintTime( 1, "Support computation", Abc_Clock() - clk ); + return vSuppsR; +} +Vec_Int_t * Gia_ManFindStopFlops( Gia_Man_t * p, int nFlopIncFreq, int fVerbose ) +{ + Vec_Int_t * vRes = NULL, * vTemp; int i, k, Spot, Temp, nItems = 0; + Vec_Wec_t * vSupps = Gia_ManCreateRegSupps( p, fVerbose ); + Vec_Int_t * vNexts = Vec_IntStartFull( Gia_ManRegNum(p) ); + Vec_Int_t * vAvail = Vec_IntStart( Gia_ManRegNum(p) ); + Vec_Int_t * vHeads = Vec_IntAlloc( 10 ); + Vec_WecForEachLevel( vSupps, vTemp, i ) { + if ( Vec_IntSize(vTemp) > 2 ) + continue; + if ( (Spot = Vec_IntFind(vTemp, i)) >= 0 ) + Vec_IntDrop( vTemp, Spot ); + if ( Vec_IntSize(vTemp) != 1 ) + continue; + Vec_IntWriteEntry( vNexts, i, Vec_IntEntry(vTemp, 0) ); + Vec_IntWriteEntry( vAvail, Vec_IntEntry(vTemp, 0), 1 ); + } + Vec_IntForEachEntry( vNexts, Spot, i ) + if ( Spot >= 0 && Vec_IntEntry(vAvail, i) == 0 ) + Vec_IntPush( vHeads, i ); + Vec_IntForEachEntry( vHeads, Spot, i ) { + for ( k = 0, Temp = Spot; Vec_IntEntry(vNexts, Temp) >= 0; k++, Temp = Vec_IntEntry(vNexts, Temp) ) + ; + if ( k > 100 ) + { + nItems++; + if ( vRes == NULL ) + vRes = Vec_IntAlloc( 100 ); + for ( k = 0, Temp = Spot; Vec_IntEntry(vNexts, Temp) >= 0; k++, Temp = Vec_IntEntry(vNexts, Temp) ) + if ( k % nFlopIncFreq == 0 ) + Vec_IntPush( vRes, Temp ); + } + while ( Vec_IntEntry(vNexts, Spot) >= 0 ) + { + int Next = Vec_IntEntry(vNexts, Spot); + Vec_IntWriteEntry( vNexts, Spot, -1 ); + Spot = Next; + } + } + if ( fVerbose && vRes ) + printf( "Detected %d sequence%s containing %d flops.\n", nItems, nItems > 1 ? "s":"", Vec_IntSize(vRes) ); + Vec_IntFree( vNexts ); + Vec_IntFree( vAvail ); + Vec_IntFree( vHeads ); + Vec_WecFree( vSupps ); + return vRes; +} +Gia_Man_t * Gia_ManDupStopsAdd( Gia_Man_t * p, Vec_Int_t * vStops ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; int i, Stop; + Vec_Int_t * vExtras = Vec_IntAlloc( Vec_IntSize(vStops) ); + 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, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Vec_IntForEachEntry( vStops, Stop, i ) + Vec_IntPush( vExtras, Gia_ManAppendCi(pNew) ); + Gia_ManForEachRo( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Vec_IntForEachEntry( vStops, Stop, i ) + { + int Lit = Gia_ManCi(p, Gia_ManPiNum(p)+Stop)->Value; + Gia_ManCi(p, Gia_ManPiNum(p)+Stop)->Value = Vec_IntEntry(vExtras, i); + Vec_IntWriteEntry( vExtras, i, Lit ); + } + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Vec_IntForEachEntry( vExtras, Stop, i ) + Gia_ManAppendCo( pNew, Stop ); + Gia_ManForEachRi( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Vec_IntFree( vExtras ); + return pNew; +} +void Gia_ManDupStopsRem_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDupStopsRem_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManDupStopsRem_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManDupStopsRem( Gia_Man_t * p, Vec_Int_t * vStops ) +{ + 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_ManForEachPi( p, pObj, i ) + if ( i < Gia_ManPiNum(p) - Vec_IntSize(vStops) ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachRo( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachPo( p, pObj, i ) + if ( i >= Gia_ManPoNum(p) - Vec_IntSize(vStops) ) + Gia_ManDupStopsRem_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachPi( p, pObj, i ) + if ( i >= Gia_ManPiNum(p) - Vec_IntSize(vStops) ) + pObj->Value = Gia_ObjFanin0Copy( Gia_ManPo(p, i - Gia_ManPiNum(p) + Gia_ManPoNum(p)) ); + Gia_ManForEachPo( p, pObj, i ) + if ( i < Gia_ManPoNum(p) - Vec_IntSize(vStops) ) + Gia_ManDupStopsRem_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachRi( p, pObj, i ) + Gia_ManDupStopsRem_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + if ( i < Gia_ManPoNum(p) - Vec_IntSize(vStops) ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManForEachRi( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} +Gia_Man_t * Gia_ManDupStopsTest( Gia_Man_t * p ) +{ + Vec_Int_t * vStops = Gia_ManFindStopFlops( p, 1, 1 ); + if ( vStops == NULL ) + return Gia_ManDup(p); + Gia_Man_t * pNew1 = Gia_ManDupStopsAdd( p, vStops ); + Gia_Man_t * pNew2 = Gia_ManDupStopsRem( pNew1, vStops ); + Gia_ManStop( pNew1 ); + Vec_IntFree( vStops ); + return pNew2; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index b198c7ffe..554fd550d 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -1783,6 +1783,48 @@ void Gia_ManRemoveWrongChoices( Gia_Man_t * p ) //Abc_Print( 1, "Removed %d wrong choices.\n", Counter ); } +void Cec4_ManSimulateDumpInfo( Cec4_Man_t * pMan ) +{ + Gia_Obj_t * pObj; int i, k, nWords = pMan->pAig->nSimWords, nOuts[2] = {0}; + Vec_Wrd_t * vSims = NULL, * vSimsPi = NULL; + FILE * pFile = fopen( pMan->pPars->pDumpName, "wb" ); + if ( pFile == NULL ) { + printf( "Cannot open file \"%s\" for writing primary output information.\n", pMan->pPars->pDumpName ); + return; + } + vSimsPi = Vec_WrdDup( pMan->pAig->vSimsPi ); + memmove( Vec_WrdArray(vSimsPi), Vec_WrdArray(vSimsPi) + nWords, Gia_ManCiNum(pMan->pAig) * nWords ); + Vec_WrdShrink( vSimsPi, Gia_ManCiNum(pMan->pAig) * nWords ); + if ( Abc_TtIsConst0(Vec_WrdArray(vSimsPi), Gia_ManCiNum(pMan->pAig) * nWords) ) { + Vec_WrdFree( vSimsPi ); + vSimsPi = Vec_WrdStartRandom( Gia_ManCiNum(pMan->pAig) * nWords ); + } + vSims = Gia_ManSimPatSimOut( pMan->pAig, vSimsPi, 1 ); + assert( nWords * Gia_ManCiNum(pMan->pAig) == Vec_WrdSize(vSimsPi) ); + Gia_ManForEachCo( pMan->pAig, pObj, i ) + { + void Extra_PrintHex2( FILE * pFile, unsigned * pTruth, int nVars ); + word * pSims = Vec_WrdEntryP( vSims, nWords*i ); + //Extra_PrintHex2( stdout, (unsigned *)pSims, 8 ); printf( "\n" ); + fprintf( pFile, "%d ", i ); + if ( Gia_ObjFaninLit0p(pMan->pNew, Gia_ManCo(pMan->pNew, i)) == 0 ) + nOuts[0]++; + else if ( Abc_TtIsConst0(pSims, nWords) ) + fprintf( pFile, "-" ); + else { + int iPat = Abc_TtFindFirstBit2(pSims, nWords); + for ( k = 0; k < Gia_ManPiNum(pMan->pAig); k++ ) + fprintf( pFile, "%d", Abc_TtGetBit(Vec_WrdEntryP(vSimsPi, nWords*k), iPat) ); + nOuts[1]++; + } + fprintf( pFile, "\n" ); + } + printf( "Information about %d sat, %d unsat, and %d undecided primary outputs was written into file \"%s\".\n", + nOuts[1], nOuts[0], Gia_ManCoNum(pMan->pAig)-nOuts[1]-nOuts[0], pMan->pPars->pDumpName ); + fclose( pFile ); + Vec_WrdFree( vSims ); + Vec_WrdFree( vSimsPi ); +} int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** ppNew, int fSimOnly ) { @@ -1954,6 +1996,8 @@ finalize: ABC_FREE( pBase ); printf( "Dumped miter \"%s\" with %d pairs.\n", pFileName, pMan->vPairs ? Vec_IntSize(pMan->vPairs)/2 : -1 ); } + if ( pPars->pDumpName ) + Cec4_ManSimulateDumpInfo( pMan ); Cec4_ManDestroy( pMan ); //Gia_ManStaticFanoutStop( p ); //Gia_ManEquivPrintClasses( p, 1, 0 ); diff --git a/src/proof/ssw/sswPart.c b/src/proof/ssw/sswPart.c index 0c6e54cef..a01885b2f 100644 --- a/src/proof/ssw/sswPart.c +++ b/src/proof/ssw/sswPart.c @@ -32,6 +32,13 @@ #include #endif +#ifdef __cplusplus +#include +using namespace std; +#else +#include +#endif + #endif @@ -98,17 +105,20 @@ typedef struct Par_ScorrThData_t_ int * pMap; int iThread; int nTimeOut; - int fWorking; + atomic_bool fWorking; } Par_ScorrThData_t; void * Ssw_GiaWorkerThread( void * pArg ) { + struct timespec pause_duration; + pause_duration.tv_sec = 0; + pause_duration.tv_nsec = 10000000L; // 10 milliseconds + Par_ScorrThData_t * pThData = (Par_ScorrThData_t *)pArg; - volatile int * pPlace = &pThData->fWorking; while ( 1 ) { - while ( *pPlace == 0 ); - assert( pThData->fWorking ); + while ( !atomic_load_explicit((atomic_bool *)&pThData->fWorking, memory_order_acquire) ) + nanosleep(&pause_duration, NULL); if ( pThData->p == NULL ) { pthread_exit( NULL ); @@ -116,7 +126,7 @@ void * Ssw_GiaWorkerThread( void * pArg ) return NULL; } Cec_ManLSCorrespondenceClasses( pThData->p, &pThData->CorPars ); - pThData->fWorking = 0; + atomic_store_explicit(&pThData->fWorking, 0, memory_order_release); } assert( 0 ); return NULL; @@ -144,37 +154,46 @@ void Ssw_SignalCorrespondenceArray( Vec_Ptr_t * vGias, Ssw_Pars_t * pPars ) { ThData[i].CorPars = *pCorPars; ThData[i].iThread = i; - //ThData[i].nTimeOut = pPars->nTimeOut; - ThData[i].fWorking = 0; + atomic_store_explicit(&ThData[i].fWorking, 0, memory_order_release); status = pthread_create( WorkerThread + i, NULL, Ssw_GiaWorkerThread, (void *)(ThData + i) ); assert( status == 0 ); } + + struct timespec pause_duration; + pause_duration.tv_sec = 0; + pause_duration.tv_nsec = 10000000L; // 10 milliseconds + // look at the threads vStack = Vec_PtrDup( vGias ); while ( Vec_PtrSize(vStack) > 0 ) { for ( i = 0; i < nProcs; i++ ) { - if ( ThData[i].fWorking ) + if ( atomic_load_explicit(&ThData[i].fWorking, memory_order_acquire) ) continue; ThData[i].p = (Gia_Man_t*)Vec_PtrPop( vStack ); - ThData[i].fWorking = 1; + atomic_store_explicit(&ThData[i].fWorking, 1, memory_order_release); break; } } Vec_PtrFree( vStack ); // wait till threads finish for ( i = 0; i < nProcs; i++ ) - if ( ThData[i].fWorking ) - i = -1; + { + if ( atomic_load_explicit(&ThData[i].fWorking, memory_order_acquire) ) + i = -1; // Start from the beginning again + nanosleep(&pause_duration, NULL); + } + // stop threads for ( i = 0; i < nProcs; i++ ) { - assert( !ThData[i].fWorking ); - // stop ThData[i].p = NULL; - ThData[i].fWorking = 1; + atomic_store_explicit(&ThData[i].fWorking, 1, memory_order_release); } + // Join threads + for ( i = 0; i < nProcs; i++ ) + pthread_join( WorkerThread[i], NULL ); } #endif // pthreads are used diff --git a/src/sat/bmc/bmcMaj.c b/src/sat/bmc/bmcMaj.c index 4d35c7de1..5e9c1310c 100644 --- a/src/sat/bmc/bmcMaj.c +++ b/src/sat/bmc/bmcMaj.c @@ -23,6 +23,7 @@ #include "misc/util/utilTruth.h" #include "sat/glucose/AbcGlucose.h" #include "aig/miniaig/miniaig.h" +#include "base/io/ioResub.h" ABC_NAMESPACE_IMPL_START @@ -3423,7 +3424,7 @@ void Exa6_ManGenMint( Exa6_Man_t * p, int iMint, int fOnlyAnd, int fFancy ) assert( t ); if ( ~t ) { - Abc_Tt6IsopCover( t, t, p->nOuts, pCover, &nCubes ); + Abc_Tt6IsopCover( ~t, ~t, p->nOuts, pCover, &nCubes ); for ( c = 0; c < nCubes; c++ ) { int nLits = 0; @@ -3667,7 +3668,7 @@ Vec_Wrd_t * Exa6_ManTransformOutputs( Vec_Wrd_t * vOuts, int nOuts ) Vec_Wrd_t * Exa6_ManTransformInputs( Vec_Wrd_t * vIns ) { Vec_Wrd_t * vRes = Vec_WrdAlloc( Vec_WrdSize(vIns) ); - int i, Polar = Vec_WrdEntry( vIns, 0 ); word Entry; + int i; word Entry, Polar = Vec_WrdEntry( vIns, 0 ); Vec_WrdForEachEntry( vIns, Entry, i ) Vec_WrdPush( vRes, Entry ^ Polar ); return vRes; @@ -3682,7 +3683,7 @@ void Exa_ManExactPrint( Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut, int nDivs, i Abc_TtPrintBits( &Entry, 1 << nOuts ); printf( "\n" ); } -Mini_Aig_t * Exa_ManExactSynthesis6Int( Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut, int nVars, int nDivs, int nOuts, int nNodes, int fOnlyAnd, int fVerbose ) +Mini_Aig_t * Exa_ManExactSynthesis6Int( Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut, int nVars, int nDivs, int nOuts, int nNodes, int fOnlyAnd, int fVerbose, char * pFileName ) { Mini_Aig_t * pTemp, * pMini; Vec_Wrd_t * vSimsDiv2, * vSimsOut2; @@ -3704,10 +3705,10 @@ Mini_Aig_t * Exa_ManExactSynthesis6Int( Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsO pMini = Mini_AigDupCompl( pTemp = pMini, DivCompl, OutCompl ); Mini_AigStop( pTemp ); } - Mini_AigerWrite( "exa6.aig", pMini, 1 ); - if ( nVars <= 6 ) - Exa_ManMiniVerify( pMini, vSimsDiv, vSimsOut ); - printf( "\n" ); + Mini_AigerWrite( pFileName ? Extra_FileNameGenericAppend(pFileName, "_twoexact.aig") : (char *)"exa6.aig", pMini, 1 ); + //if ( nVars <= 6 ) + // Exa_ManMiniVerify( pMini, vSimsDiv, vSimsOut ); + //printf( "\n" ); //Mini_AigStop( pMini ); } Vec_WrdFreeP( &vSimsDiv2 ); @@ -3718,11 +3719,37 @@ void Exa_ManExactSynthesis6( Bmc_EsPar_t * pPars, char * pFileName ) { Mini_Aig_t * pMini = NULL; Vec_Wrd_t * vSimsDiv = NULL, * vSimsOut = NULL; - int nDivs, nOuts, nVars = Exa6_ReadFile( pFileName, &vSimsDiv, &vSimsOut, &nDivs, &nOuts ); + int i, k, nDivs, nOuts, nVars = 0; + if ( !strcmp(pFileName + strlen(pFileName) - 3, "rel") ) + nVars = Exa6_ReadFile( pFileName, &vSimsDiv, &vSimsOut, &nDivs, &nOuts ); + else if ( !strcmp(pFileName + strlen(pFileName) - 3, "pla") ) { + Abc_RData_t * p = Abc_ReadPla( pFileName ); + Abc_RData_t * p2 = p ? Abc_RData2Rel( p ) : NULL; + if ( !p || !p2 ) return; + nDivs = 0; + nOuts = p->nOuts; + nVars = p->nIns; + vSimsDiv = Vec_WrdStart( p2->nPats ); + for ( k = 0; k < p->nIns; k++ ) + for ( i = 0; i < p2->nPats; i++ ) + if ( Abc_RDataGetIn(p2, k, i) ) + Abc_InfoSetBit((unsigned *)Vec_WrdEntryP(vSimsDiv, i), 1+k); + vSimsOut = Vec_WrdStart( p2->nPats ); + for ( k = 0; k < (1 << p->nOuts); k++ ) + for ( i = 0; i < p2->nPats; i++ ) + if ( Abc_RDataGetOut(p2, k, i) ) + Abc_InfoSetBit((unsigned *)Vec_WrdEntryP(vSimsOut, i), k); + Abc_RDataStop( p ); + Abc_RDataStop( p2 ); + } + else + printf( "Unknown file extension in file \"%s\".\n", pFileName ); if ( nVars == 0 ) return; + //Vec_WrdPrintBin( vSimsDiv, 1 ); + //Vec_WrdPrintBin( vSimsOut, 1 ); Exa6_SortSims( vSimsDiv, vSimsOut ); - pMini = Exa_ManExactSynthesis6Int( vSimsDiv, vSimsOut, nVars, nDivs, nOuts, pPars->nNodes, pPars->fOnlyAnd, pPars->fVerbose ); + pMini = Exa_ManExactSynthesis6Int( vSimsDiv, vSimsOut, nVars, nDivs, nOuts, pPars->nNodes, pPars->fOnlyAnd, pPars->fVerbose, pFileName ); Vec_WrdFreeP( &vSimsDiv ); Vec_WrdFreeP( &vSimsOut ); if ( pMini ) Mini_AigStop( pMini ); diff --git a/src/sat/bsat/satVec.h b/src/sat/bsat/satVec.h index 8cc8ba4eb..305df9160 100644 --- a/src/sat/bsat/satVec.h +++ b/src/sat/bsat/satVec.h @@ -130,7 +130,9 @@ static inline void vecp_remove(vecp* v, void* e) typedef int lit; typedef int cla; -typedef char lbool; +// Explicitly make it signed so promotion-to-int behavior doesn't vary +// across platforms that define signedness of char differently. +typedef signed char lbool; static const int var_Undef = -1; static const lit lit_Undef = -2; diff --git a/src/sat/glucose/Alloc.h b/src/sat/glucose/Alloc.h index a63de032f..9ceb5dcd0 100644 --- a/src/sat/glucose/Alloc.h +++ b/src/sat/glucose/Alloc.h @@ -100,11 +100,7 @@ void RegionAllocator::capacity(uint32_t min_cap) cap += delta; if (cap <= prev_cap) -#ifdef __wasm - abort(); -#else - throw OutOfMemoryException(); -#endif + fatal_out_of_memory(); } //printf(" .. (%p) cap = %u\n", this, cap); @@ -126,11 +122,7 @@ RegionAllocator::alloc(int size) // Handle overflow: if (sz < prev_sz) -#ifdef __wasm - abort(); -#else - throw OutOfMemoryException(); -#endif + fatal_out_of_memory(); return prev_sz; } diff --git a/src/sat/glucose/Vec.h b/src/sat/glucose/Vec.h index 4ef2bdf10..a985a1114 100644 --- a/src/sat/glucose/Vec.h +++ b/src/sat/glucose/Vec.h @@ -100,11 +100,7 @@ void vec::capacity(int min_cap) { if (cap >= min_cap) return; int add = imax((min_cap - cap + 1) & ~1, ((cap >> 1) + 2) & ~1); // NOTE: grow by approximately 3/2 if (add > INT_MAX - cap || (((data = (T*)::realloc((void*)data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM)) -#ifdef __wasm - abort(); -#else - throw OutOfMemoryException(); -#endif + fatal_out_of_memory(); } diff --git a/src/sat/glucose/XAlloc.h b/src/sat/glucose/XAlloc.h index d1f1062af..e08584e4c 100644 --- a/src/sat/glucose/XAlloc.h +++ b/src/sat/glucose/XAlloc.h @@ -34,16 +34,18 @@ namespace Gluco { //================================================================================================= // Simple layer on top of malloc/realloc to catch out-of-memory situtaions and provide some typing: -class OutOfMemoryException{}; +static inline void fatal_out_of_memory() +{ + fputs("Out of memory\n", stderr); + abort(); +} + static inline void* xrealloc(void *ptr, size_t size) { void* mem = realloc(ptr, size); if (mem == NULL && errno == ENOMEM){ -#ifdef __wasm - abort(); -#else - throw OutOfMemoryException(); -#endif + fatal_out_of_memory(); + return NULL; }else { return mem; } diff --git a/src/sat/glucose2/Alloc.h b/src/sat/glucose2/Alloc.h index 427cd3232..6575020c7 100644 --- a/src/sat/glucose2/Alloc.h +++ b/src/sat/glucose2/Alloc.h @@ -100,11 +100,7 @@ void RegionAllocator::capacity(uint32_t min_cap) cap += delta; if (cap <= prev_cap) -#ifdef __wasm - abort(); -#else - throw OutOfMemoryException(); -#endif + fatal_out_of_memory(); } //printf(" .. (%p) cap = %u\n", this, cap); @@ -126,11 +122,7 @@ RegionAllocator::alloc(int size) // Handle overflow: if (sz < prev_sz) -#ifdef __wasm - abort(); -#else - throw OutOfMemoryException(); -#endif + fatal_out_of_memory(); return prev_sz; } diff --git a/src/sat/glucose2/Vec.h b/src/sat/glucose2/Vec.h index ace47412e..1483ac798 100644 --- a/src/sat/glucose2/Vec.h +++ b/src/sat/glucose2/Vec.h @@ -102,22 +102,14 @@ void vec::capacity(int min_cap) { if (cap >= min_cap) return; int add = imax((min_cap - cap + 1) & ~1, ((cap >> 1) + 2) & ~1); // NOTE: grow by approximately 3/2 if (add > INT_MAX - cap || (((data = (T*)::realloc((void*)data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM)) -#ifdef __wasm - abort(); -#else - throw OutOfMemoryException(); -#endif + fatal_out_of_memory(); } template void vec::prelocate(int ext_cap) { if (cap >= ext_cap) return; if (ext_cap > INT_MAX || (((data = (T*)::realloc((void*)data, ext_cap * sizeof(T))) == NULL) && errno == ENOMEM)) -#ifdef __wasm - abort(); -#else - throw OutOfMemoryException(); -#endif + fatal_out_of_memory();; cap = ext_cap; } diff --git a/src/sat/glucose2/XAlloc.h b/src/sat/glucose2/XAlloc.h index 86e65a494..45a802ce5 100644 --- a/src/sat/glucose2/XAlloc.h +++ b/src/sat/glucose2/XAlloc.h @@ -34,16 +34,18 @@ namespace Gluco2 { //================================================================================================= // Simple layer on top of malloc/realloc to catch out-of-memory situtaions and provide some typing: -class OutOfMemoryException{}; +static inline void fatal_out_of_memory() +{ + fputs("Out of memory\n", stderr); + abort(); +} + static inline void* xrealloc(void *ptr, size_t size) { void* mem = realloc(ptr, size); if (mem == NULL && errno == ENOMEM){ -#ifdef __wasm - abort(); -#else - throw OutOfMemoryException(); -#endif + fatal_out_of_memory(); + return NULL; }else { return mem; }