diff --git a/.gitattributes b/.gitattributes index 400b529f0b..93b5c8649a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ +/.gitcommit export-subst * text=auto *.c text diff --git a/.gitcommit b/.gitcommit new file mode 100644 index 0000000000..6828f88dcb --- /dev/null +++ b/.gitcommit @@ -0,0 +1 @@ +$Format:%H$ diff --git a/.github/workflows/build-posix-cmake.yml b/.github/workflows/build-posix-cmake.yml index 5e101cd792..50f9ef902f 100644 --- a/.github/workflows/build-posix-cmake.yml +++ b/.github/workflows/build-posix-cmake.yml @@ -6,10 +6,10 @@ on: jobs: - build-posix: + build-posix-cmake: strategy: matrix: - os: [macos-11, ubuntu-latest] + os: [macos-latest, ubuntu-latest] use_namespace: [false, true] runs-on: ${{ matrix.os }} @@ -22,7 +22,7 @@ jobs: steps: - name: Git Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: submodules: recursive @@ -44,6 +44,10 @@ jobs: run: | cmake --build build + - name: Run Unit Tests + run: | + ctest --output-on-failure + - name: Test Executable run: | ./build/abc -c "r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec" @@ -60,7 +64,7 @@ jobs: cp build/abc build/libabc.a staging/ - name: Upload pacakge artifact - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: - name: package + name: package-cmake-${{ matrix.os }}-${{ matrix.use_namespace }} path: staging/ diff --git a/.github/workflows/build-posix.yml b/.github/workflows/build-posix.yml index e26b67b89d..080c6e0453 100644 --- a/.github/workflows/build-posix.yml +++ b/.github/workflows/build-posix.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Git Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: submodules: recursive @@ -60,7 +60,7 @@ jobs: cp abc libabc.a staging/ - name: Upload pacakge artifact - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: - name: package + name: package-posix-${{ matrix.os }}-${{ matrix.use_namespace }} path: staging/ diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 8e1ac37dfb..2d08943648 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -13,7 +13,7 @@ jobs: steps: - name: Git Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: submodules: recursive @@ -46,7 +46,7 @@ jobs: copy UpgradeLog.htm staging/ - name: Upload pacakge artifact - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: - name: package + name: package-windows path: staging/ diff --git a/.gitignore b/.gitignore index cbb4241526..cdf34f18d1 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ lib/m114* lib/bip* docs/ .vscode/ +.cache/ src/ext* src/xxx/ diff --git a/CMakeLists.txt b/CMakeLists.txt index b90ac02df4..918fb79a15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,3 +119,17 @@ add_library(libabc-pic EXCLUDE_FROM_ALL ${ABC_SRC}) abc_properties(libabc-pic PUBLIC) set_property(TARGET libabc-pic PROPERTY POSITION_INDEPENDENT_CODE ON) set_property(TARGET libabc-pic PROPERTY OUTPUT_NAME abc-pic) + +if(NOT DEFINED ABC_SKIP_TESTS) + enable_testing() + include(FetchContent) + FetchContent_Declare( + googletest + DOWNLOAD_EXTRACT_TIMESTAMP TRUE + # Specify the commit you depend on and update it regularly. + URL "https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip" + ) + FetchContent_MakeAvailable(googletest) + include(GoogleTest) + add_subdirectory(test) +endif() \ No newline at end of file diff --git a/Makefile b/Makefile index e94591b20b..798fb2e7b0 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,8 @@ AR := ar LD := $(CXX) MSG_PREFIX ?= -ABCSRC = . +ABCSRC ?= . +VPATH = $(ABCSRC) $(info $(MSG_PREFIX)Using CC=$(CC)) $(info $(MSG_PREFIX)Using CXX=$(CXX)) @@ -41,7 +42,7 @@ default: $(PROG) ARCHFLAGS_EXE ?= ./arch_flags $(ARCHFLAGS_EXE) : arch_flags.c - $(CC) arch_flags.c -o $(ARCHFLAGS_EXE) + $(CC) $< -o $(ARCHFLAGS_EXE) INCLUDES += -I$(ABCSRC)/src @@ -138,11 +139,11 @@ endif # LIBS := -ldl -lrt LIBS += -lm -ifneq ($(OS), FreeBSD) +ifneq ($(OS), $(filter $(OS), FreeBSD OpenBSD NetBSD)) LIBS += -ldl endif -ifneq ($(findstring Darwin, $(shell uname)), Darwin) +ifneq ($(OS), $(filter $(OS), FreeBSD OpenBSD NetBSD Darwin)) LIBS += -lrt endif @@ -152,7 +153,7 @@ ifdef ABC_USE_LIBSTDCXX endif $(info $(MSG_PREFIX)Using CFLAGS=$(CFLAGS)) -CXXFLAGS += $(CFLAGS) -std=c++17 +CXXFLAGS += $(CFLAGS) -std=c++17 -fno-exceptions SRC := GARBAGE := core core.* *.stackdump ./tags $(PROG) arch_flags @@ -174,26 +175,32 @@ DEP := $(OBJ:.o=.d) # implicit rules %.o: %.c + @mkdir -p $(dir $@) @echo "$(MSG_PREFIX)\`\` Compiling:" $(LOCAL_PATH)/$< $(VERBOSE)$(CC) -c $(OPTFLAGS) $(INCLUDES) $(CFLAGS) $< -o $@ %.o: %.cc + @mkdir -p $(dir $@) @echo "$(MSG_PREFIX)\`\` Compiling:" $(LOCAL_PATH)/$< $(VERBOSE)$(CXX) -c $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< -o $@ %.o: %.cpp + @mkdir -p $(dir $@) @echo "$(MSG_PREFIX)\`\` Compiling:" $(LOCAL_PATH)/$< $(VERBOSE)$(CXX) -c $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< -o $@ %.d: %.c + @mkdir -p $(dir $@) @echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$< $(VERBOSE)$(ABCSRC)/depends.sh "$(CC)" `dirname $*.c` $(OPTFLAGS) $(INCLUDES) $(CFLAGS) $< > $@ %.d: %.cc + @mkdir -p $(dir $@) @echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$< $(VERBOSE)$(ABCSRC)/depends.sh "$(CXX)" `dirname $*.cc` $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< > $@ %.d: %.cpp + @mkdir -p $(dir $@) @echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$< $(VERBOSE)$(ABCSRC)/depends.sh "$(CXX)" `dirname $*.cpp` $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< > $@ @@ -207,7 +214,10 @@ depend: $(DEP) clean: @echo "$(MSG_PREFIX)\`\` Cleaning up..." - $(VERBOSE)rm -rvf $(PROG) lib$(PROG).a $(OBJ) $(GARBAGE) $(OBJ:.o=.d) + $(VERBOSE)rm -rvf $(PROG) lib$(PROG).a + $(VERBOSE)rm -rvf $(OBJ) + $(VERBOSE)rm -rvf $(GARBAGE) + $(VERBOSE)rm -rvf $(OBJ:.o=.d) tags: etags `find . -type f -regex '.*\.\(c\|h\)'` diff --git a/abc.rc b/abc.rc index a3efc0b09a..c87e70b4ba 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 06802171f7..559d59d2a3 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 31e5123676..7615b8fcc7 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 e3d89942ae..7612d02b1f 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 68be112f18..aad8c250c4 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 3c1bc2f229..32d4e807ee 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; }; @@ -549,9 +554,11 @@ static inline int Gia_ObjFaninIdp( Gia_Man_t * p, Gia_Obj_t * pObj, int static inline int Gia_ObjFaninLit0( Gia_Obj_t * pObj, int ObjId ) { return Abc_Var2Lit( Gia_ObjFaninId0(pObj, ObjId), Gia_ObjFaninC0(pObj) ); } static inline int Gia_ObjFaninLit1( Gia_Obj_t * pObj, int ObjId ) { return Abc_Var2Lit( Gia_ObjFaninId1(pObj, ObjId), Gia_ObjFaninC1(pObj) ); } static inline int Gia_ObjFaninLit2( Gia_Man_t * p, int ObjId ) { return (p->pMuxes && p->pMuxes[ObjId]) ? p->pMuxes[ObjId] : -1; } +static inline int Gia_ObjFaninLit( Gia_Obj_t * pObj, int ObjId, int n ){ return n ? Gia_ObjFaninLit1(pObj, ObjId) : Gia_ObjFaninLit0(pObj, ObjId);} static inline int Gia_ObjFaninLit0p( Gia_Man_t * p, Gia_Obj_t * pObj) { return Abc_Var2Lit( Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninC0(pObj) ); } static inline int Gia_ObjFaninLit1p( Gia_Man_t * p, Gia_Obj_t * pObj) { return Abc_Var2Lit( Gia_ObjFaninId1p(p, pObj), Gia_ObjFaninC1(pObj) ); } static inline int Gia_ObjFaninLit2p( Gia_Man_t * p, Gia_Obj_t * pObj) { return (p->pMuxes && p->pMuxes[Gia_ObjId(p, pObj)]) ? p->pMuxes[Gia_ObjId(p, pObj)] : -1; } +static inline int Gia_ObjFaninLitp( Gia_Man_t * p, Gia_Obj_t * pObj, int n ){ return n ? Gia_ObjFaninLit1p(p, pObj) : Gia_ObjFaninLit0p(p, pObj);} static inline void Gia_ObjFlipFaninC0( Gia_Obj_t * pObj ) { assert( Gia_ObjIsCo(pObj) ); pObj->fCompl0 ^= 1; } static inline int Gia_ObjFaninNum( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsMux(p, pObj) ) return 3; if ( Gia_ObjIsAnd(pObj) ) return 2; if ( Gia_ObjIsCo(pObj) ) return 1; return 0; } static inline int Gia_ObjWhatFanin( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanin ) { if ( Gia_ObjFanin0(pObj) == pFanin ) return 0; if ( Gia_ObjFanin1(pObj) == pFanin ) return 1; if ( Gia_ObjFanin2(p, pObj) == pFanin ) return 2; assert(0); return -1; } @@ -1243,7 +1250,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 /// //////////////////////////////////////////////////////////////////////// @@ -1671,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 ); @@ -1712,6 +1729,7 @@ extern word Gia_ManRandomW( int fReset ); extern void Gia_ManRandomInfo( Vec_Ptr_t * vInfo, int iInputStart, int iWordStart, int iWordStop ); extern char * Gia_TimeStamp(); extern char * Gia_FileNameGenericAppend( char * pBase, char * pSuffix ); +extern Vec_Ptr_t * Gia_GetFakeNames( int nNames, int fCaps ); extern void Gia_ManIncrementTravId( Gia_Man_t * p ); extern void Gia_ManCleanMark01( Gia_Man_t * p ); extern void Gia_ManSetMark0( Gia_Man_t * p ); @@ -1738,6 +1756,7 @@ extern Vec_Int_t * Gia_ManReverseLevel( Gia_Man_t * p ); extern Vec_Int_t * Gia_ManRequiredLevel( Gia_Man_t * p ); extern void Gia_ManCreateValueRefs( Gia_Man_t * p ); extern void Gia_ManCreateRefs( Gia_Man_t * p ); +extern void Gia_ManCreateLitRefs( Gia_Man_t * p ); extern int * Gia_ManCreateMuxRefs( Gia_Man_t * p ); extern int Gia_ManCrossCut( Gia_Man_t * p, int fReverse ); extern Vec_Int_t * Gia_ManCollectPoIds( Gia_Man_t * p ); diff --git a/src/aig/gia/giaAiger.c b/src/aig/gia/giaAiger.c index de94c46022..9c6ca89922 100644 --- a/src/aig/gia/giaAiger.c +++ b/src/aig/gia/giaAiger.c @@ -1464,6 +1464,18 @@ void Gia_AigerWriteS( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, in Vec_StrFree( vStrExt ); if ( fVerbose ) printf( "Finished writing extension \"m\".\n" ); } + // write cell mapping + if ( Gia_ManHasCellMapping(p) ) + { + extern Vec_Str_t * Gia_AigerWriteCellMappingDoc( Gia_Man_t * p ); + fprintf( pFile, "M" ); + vStrExt = Gia_AigerWriteCellMappingDoc( p ); + Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); + fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); + Vec_StrFree( vStrExt ); + if ( fVerbose ) printf( "Finished writing extension \"M\".\n" ); + + } // write placement if ( p->pPlacement ) { diff --git a/src/aig/gia/giaAigerExt.c b/src/aig/gia/giaAigerExt.c index 50c3588d94..d149b0a5e9 100644 --- a/src/aig/gia/giaAigerExt.c +++ b/src/aig/gia/giaAigerExt.c @@ -19,6 +19,9 @@ ***********************************************************************/ #include "gia.h" +#include "misc/st/st.h" +#include "map/mio/mio.h" +#include "map/mio/mioInt.h" ABC_NAMESPACE_IMPL_START @@ -288,6 +291,101 @@ Vec_Str_t * Gia_AigerWriteMappingDoc( Gia_Man_t * p ) return Vec_StrAllocArray( (char *)pBuffer, 4*nSize ); } +int Gia_AigerWriteCellMappingInstance( Gia_Man_t * p, unsigned char * pBuffer, int nSize2, int i ) +{ + int k, iFan; + if ( !Gia_ObjIsCellInv(p, i) ) { + Gia_AigerWriteInt( pBuffer + nSize2, Gia_ObjCellId(p, i) ); nSize2 += 4; + Gia_AigerWriteInt( pBuffer + nSize2, i ); nSize2 += 4; + Gia_CellForEachFanin( p, i, iFan, k ) + { + Gia_AigerWriteInt( pBuffer + nSize2, iFan ); + nSize2 += 4; + } + } else { + Gia_AigerWriteInt( pBuffer + nSize2, 3 ); nSize2 += 4; + Gia_AigerWriteInt( pBuffer + nSize2, i ); nSize2 += 4; + Gia_AigerWriteInt( pBuffer + nSize2, Abc_LitNot(i) ); nSize2 += 4; + } + + return nSize2; +} + +Vec_Str_t * Gia_AigerWriteCellMappingDoc( Gia_Man_t * p ) +{ + unsigned char * pBuffer; + int i, iFan, nCells = 0, nInstances = 0, nSize = 8, nSize2 = 0; + Mio_Cell2_t * pCells = Mio_CollectRootsNewDefault2( 6, &nCells, 0 ); + assert( pCells ); + + for (int i = 0; i < nCells; i++) + { + Mio_Gate_t *pGate = (Mio_Gate_t *) pCells[i].pMioGate; + Mio_Pin_t *pPin; + nSize += strlen(Mio_GateReadName(pGate)) + 1; + nSize += strlen(Mio_GateReadOutName(pGate)) + 1 + 4; + Mio_GateForEachPin( pGate, pPin ) + nSize += strlen(Mio_PinReadName(pPin)) + 1; + } + + Gia_ManForEachCell( p, i ) + { + assert ( !Gia_ObjIsCellBuf(p, i) ); // not implemented + nInstances++; + if ( Gia_ObjIsCellInv(p, i) ) + nSize += 12; + else + nSize += Gia_ObjCellSize(p, i) * 4 + 8; + } + + pBuffer = ABC_ALLOC( unsigned char, nSize ); + Gia_AigerWriteInt( pBuffer + nSize2, nCells ); nSize2 += 4; + Gia_AigerWriteInt( pBuffer + nSize2, nInstances ); nSize2 += 4; + + for (int i = 0; i < nCells; i++) + { + int nPins = 0; + Mio_Gate_t *pGate = (Mio_Gate_t *) pCells[i].pMioGate; + Mio_Pin_t *pPin; + + strcpy((char *) pBuffer + nSize2, Mio_GateReadName(pGate)); + nSize2 += strlen(Mio_GateReadName(pGate)) + 1; + strcpy((char *) pBuffer + nSize2, Mio_GateReadOutName(pGate)); + nSize2 += strlen(Mio_GateReadOutName(pGate)) + 1; + + Mio_GateForEachPin( pGate, pPin ) + nPins++; + Gia_AigerWriteInt( pBuffer + nSize2, nPins ); nSize2 += 4; + + Mio_GateForEachPin( pGate, pPin ) + { + strcpy((char *) pBuffer + nSize2, Mio_PinReadName(pPin)); + nSize2 += strlen(Mio_PinReadName(pPin)) + 1; + } + } + + Gia_ManForEachCell( p, i ) + { + if ( Gia_ObjIsCellBuf(p, i) ) + continue; + + if ( Gia_ObjIsCellInv(p, i) && !Abc_LitIsCompl(i) ) { + // swap the order so that the inverter is after the driver + // of the inverter's input + nSize2 = Gia_AigerWriteCellMappingInstance(p, pBuffer, nSize2, Abc_LitNot(i) ); + nSize2 = Gia_AigerWriteCellMappingInstance(p, pBuffer, nSize2, i ); + i += 1; + continue; + } + + nSize2 = Gia_AigerWriteCellMappingInstance(p, pBuffer, nSize2, i ); + } + + assert( nSize2 == nSize ); + ABC_FREE( pCells ); + return Vec_StrAllocArray( (char *)pBuffer, nSize ); +} + /**Function************************************************************* Synopsis [Read/write packing information.] diff --git a/src/aig/gia/giaClp.c b/src/aig/gia/giaClp.c index 68f9bf5656..dba81637ee 100644 --- a/src/aig/gia/giaClp.c +++ b/src/aig/gia/giaClp.c @@ -42,42 +42,6 @@ extern int Gia_ManFactorNode( Gia_Man_t * p, char * pSop, Vec_Int_t * vLeaves ); /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Gia_GetFakeNames( int nNames ) -{ - Vec_Ptr_t * vNames; - char Buffer[5]; - int i; - - vNames = Vec_PtrAlloc( nNames ); - for ( i = 0; i < nNames; i++ ) - { - if ( nNames < 26 ) - { - Buffer[0] = 'a' + i; - Buffer[1] = 0; - } - else - { - Buffer[0] = 'a' + i%26; - Buffer[1] = '0' + i/26; - Buffer[2] = 0; - } - Vec_PtrPush( vNames, Extra_UtilStrsav(Buffer) ); - } - return vNames; -} - /**Function************************************************************* Synopsis [] @@ -378,11 +342,11 @@ Gia_Man_t * Gia_ManCollapseTest( Gia_Man_t * p, int fVerbose ) Dsd_Decompose( pManDsd, (DdNode **)Vec_PtrArray(vFuncs), Vec_PtrSize(vFuncs) ); if ( fVerbose ) { - Vec_Ptr_t * vNamesCi = Gia_GetFakeNames( Gia_ManCiNum(p) ); - Vec_Ptr_t * vNamesCo = Gia_GetFakeNames( Gia_ManCoNum(p) ); + Vec_Ptr_t * vNamesCi = Gia_GetFakeNames( Gia_ManCiNum(p), 0 ); + Vec_Ptr_t * vNamesCo = Gia_GetFakeNames( Gia_ManCoNum(p), 1 ); 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 +368,145 @@ void Gia_ManCollapseTestTest( Gia_Man_t * p ) Gia_ManStop( pNew ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintDsdOne( Dsd_Manager_t * pManDsd, int Output, int OffSet ) +{ + Vec_Str_t * vStr = Vec_StrAlloc( 100 ); + Dsd_TreePrint4( vStr, pManDsd, Output ); + for ( int i = 0; i < OffSet; i++ ) + printf( " " ); + printf( "Supp %2d nDsd %2d %s\n", Dsd_TreeSuppSize(pManDsd, Output), Dsd_TreeNonDsdMax(pManDsd, Output), Vec_StrArray(vStr) ); + Vec_StrFree( vStr ); + fflush( stdout ); +} +void Gia_ManPrintDsd( Dsd_Manager_t * pManDsd, int Output, int nOutputs, int OffSet ) +{ + if ( Output == -1 ) + { + for ( int i = 0; i < nOutputs; i++ ) + Gia_ManPrintDsdOne( pManDsd, i, OffSet ); + } + else + { + assert( Output >= 0 && Output < nOutputs ); + Gia_ManPrintDsdOne( pManDsd, Output, OffSet ); + } +} + +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 **)Vec_PtrArray(vFuncs), Vec_PtrSize(vFuncs) ); + + if ( fVerbose ) + { + Vec_Ptr_t * vNamesCi = Gia_GetFakeNames( Gia_ManCiNum(p), 0 ); + Vec_Ptr_t * vNamesCo = Gia_GetFakeNames( Gia_ManCoNum(p), 1 ); + 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 ); + } + else + Gia_ManPrintDsd( pManDsd, 0, Vec_PtrSize(vFuncs), 0 ); + + Dsd_ManagerStop( pManDsd ); + Gia_ManCollapseDeref( dd, vFuncs ); + Extra_StopManager( dd ); +} + +Vec_Ptr_t * Gia_ManRecurDsdCof( DdManager * dd, Vec_Ptr_t * vFuncs, int iVar ) +{ + Vec_Ptr_t * vNew = Vec_PtrAlloc( 2 * Vec_PtrSize(vFuncs) ); DdNode * bFunc; int i; + Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i ) { + DdNode * bCof0 = Cudd_Cofactor( dd, bFunc, Cudd_Not(Cudd_bddIthVar(dd, iVar)) ); Cudd_Ref( bCof0 ); + DdNode * bCof1 = Cudd_Cofactor( dd, bFunc, Cudd_bddIthVar(dd, iVar) ); Cudd_Ref( bCof1 ); + Vec_PtrPush( vNew, bCof0 ); + Vec_PtrPush( vNew, bCof1 ); + } + return vNew; +} +void Gia_ManRecurDsd( Gia_Man_t * p, int fVerbose ) +{ + DdManager * dd; + Dsd_Manager_t * pManDsd; + Vec_Ptr_t * vFuncs, * vAux; + 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 **)Vec_PtrArray(vFuncs), Vec_PtrSize(vFuncs) ); + + printf( "Function:\n" ); + Gia_ManPrintDsd( pManDsd, 0, Vec_PtrSize(vFuncs), 0 ); + + for ( int i = 0; i < 5 && Dsd_TreeNonDsdMax(pManDsd, -1) > 0; i++ ) + { + int v, iBestV = -1, DsdMin = ABC_INFINITY, SuppMin = ABC_INFINITY; + for ( v = 0; v < Gia_ManCiNum(p); v++ ) + { + Vec_Ptr_t * vTemp = Gia_ManRecurDsdCof( dd, vFuncs, v ); + Dsd_Decompose( pManDsd, (DdNode **)Vec_PtrArray(vTemp), Vec_PtrSize(vTemp) ); + int DsdCur = Dsd_TreeNonDsdMax( pManDsd, -1 ); + int SuppCur = Dsd_TreeSuppSize( pManDsd, -1 ); + if ( DsdMin > DsdCur || (DsdMin == DsdCur && SuppMin > SuppCur) ) + DsdMin = DsdCur, SuppMin = SuppCur, iBestV = v; + Gia_ManCollapseDeref( dd, vTemp ); + } + assert( iBestV >= 0 ); + vFuncs = Gia_ManRecurDsdCof( dd, vAux = vFuncs, iBestV ); + Gia_ManCollapseDeref( dd, vAux ); + printf( "Cofactoring variable %c:\n", (int)(iBestV >= 26 ? 'A' - 26 : 'a') + iBestV ); + Dsd_Decompose( pManDsd, (DdNode **)Vec_PtrArray(vFuncs), Vec_PtrSize(vFuncs) ); + Gia_ManPrintDsd( pManDsd, -1, Vec_PtrSize(vFuncs), (i+1)*2 ); + } + + Dsd_ManagerStop( pManDsd ); + Gia_ManCollapseDeref( dd, vFuncs ); + Extra_StopManager( dd ); +} + #else Gia_Man_t * Gia_ManCollapseTest( Gia_Man_t * p, int fVerbose ) @@ -411,6 +514,14 @@ Gia_Man_t * Gia_ManCollapseTest( Gia_Man_t * p, int fVerbose ) return NULL; } +void Gia_ManCheckDsd( Gia_Man_t * p, int OffSet, int fVerbose ) +{ +} + +void Gia_ManRecurDsd( Gia_Man_t * p, int fVerbose ) +{ +} + #endif //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaCof.c b/src/aig/gia/giaCof.c index c6ccb7d1fc..d89e258671 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 19e2d8fc9f..19d98c3be2 100644 --- a/src/aig/gia/giaCut.c +++ b/src/aig/gia/giaCut.c @@ -30,7 +30,7 @@ ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// #define GIA_MAX_CUTSIZE 8 -#define GIA_MAX_CUTNUM 65 +#define GIA_MAX_CUTNUM 257 #define GIA_MAX_TT_WORDS ((GIA_MAX_CUTSIZE > 6) ? 1 << (GIA_MAX_CUTSIZE-6) : 1) #define GIA_CUT_NO_LEAF 0xF @@ -45,6 +45,7 @@ struct Gia_Cut_t_ unsigned nTreeLeaves : 28; // tree leaves unsigned nLeaves : 4; // leaf count int pLeaves[GIA_MAX_CUTSIZE]; // leaves + float CostF; }; typedef struct Gia_Sto_t_ Gia_Sto_t; @@ -281,7 +282,7 @@ static inline int Gia_CutSetLastCutIsContained( Gia_Cut_t ** pCuts, int nCuts ) SeeAlso [] ***********************************************************************/ -static inline int Gia_CutCompare( Gia_Cut_t * pCut0, Gia_Cut_t * pCut1 ) +static inline int Gia_CutCompare2( Gia_Cut_t * pCut0, Gia_Cut_t * pCut1 ) { if ( pCut0->nTreeLeaves < pCut1->nTreeLeaves ) return -1; if ( pCut0->nTreeLeaves > pCut1->nTreeLeaves ) return 1; @@ -289,6 +290,14 @@ static inline int Gia_CutCompare( Gia_Cut_t * pCut0, Gia_Cut_t * pCut1 ) if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; return 0; } +static inline int Gia_CutCompare( Gia_Cut_t * pCut0, Gia_Cut_t * pCut1 ) +{ + if ( pCut0->CostF > pCut1->CostF ) return -1; + if ( pCut0->CostF < pCut1->CostF ) return 1; + if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; + if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; + return 0; +} static inline int Gia_CutSetLastCutContains( Gia_Cut_t ** pCuts, int nCuts ) { int i, k, fChanges = 0; @@ -432,6 +441,13 @@ static inline int Gia_CutTreeLeaves( Gia_Sto_t * p, Gia_Cut_t * pCut ) Cost += Vec_IntEntry( p->vRefs, pCut->pLeaves[i] ) == 1; return Cost; } +static inline float Gia_CutGetCost( Gia_Sto_t * p, Gia_Cut_t * pCut ) +{ + int i, Cost = 0; + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + Cost += Vec_IntEntry( p->vRefs, pCut->pLeaves[i] ); + return (float)Cost / Abc_MaxInt(1, pCut->nLeaves); +} static inline int Gia_StoPrepareSet( Gia_Sto_t * p, int iObj, int Index ) { Vec_Int_t * vThis = Vec_WecEntry( p->vCuts, iObj ); @@ -445,6 +461,7 @@ static inline int Gia_StoPrepareSet( Gia_Sto_t * p, int iObj, int Index ) pCutTemp->iFunc = pCut[pCut[0]+1]; pCutTemp->Sign = Gia_CutGetSign( pCutTemp ); pCutTemp->nTreeLeaves = Gia_CutTreeLeaves( p, pCutTemp ); + pCutTemp->CostF = Gia_CutGetCost( p, pCutTemp ); } return pList[0]; } @@ -512,6 +529,7 @@ void Gia_StoMergeCuts( Gia_Sto_t * p, int iObj ) if ( p->fCutMin && Gia_CutComputeTruth(p, pCut0, pCut1, fComp0, fComp1, pCutsR[nCutsR], fIsXor) ) pCutsR[nCutsR]->Sign = Gia_CutGetSign(pCutsR[nCutsR]); pCutsR[nCutsR]->nTreeLeaves = Gia_CutTreeLeaves( p, pCutsR[nCutsR] ); + pCutsR[nCutsR]->CostF = Gia_CutGetCost( p, pCutsR[nCutsR] ); nCutsR = Gia_CutSetAddCut( pCutsR, nCutsR, nCutNum ); } p->CutCount[3] += nCutsR; @@ -986,10 +1004,381 @@ 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, j, k, * pCut; + Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); + Vec_Wec_t * vCuts = Vec_WecAlloc( 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 ); + vLevel = Vec_WecPushLevel( vCuts ); + Vec_IntPush( vLevel, i ); + for ( j = 1; j <= pCut[0]; j++ ) + Vec_IntPush( vLevel, pCut[j] ); + break; + } + } + printf( "Nodes with matching cuts: " ); + Vec_IntPrint( vNodes ); + if ( Vec_WecSize(vCuts) > 32 ) + Vec_WecShrink(vCuts, 32); + Vec_WecPrint( vCuts, 0 ); + Vec_WecFree( vCuts ); + 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; +} +Vec_Ptr_t * Gia_ManMatchCutsMany( Vec_Mem_t * vTtMem, Vec_Int_t * vMap, int nFuncs, 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, j, k, * pCut; + abctime clkStart = Abc_Clock(); + assert( Abc_Truth6WordNum(nCutSize) == Vec_MemEntrySize(vTtMem) ); + Vec_Ptr_t * vRes = Vec_PtrAlloc( nFuncs ); + for ( i = 0; i < nFuncs; i++ ) + Vec_PtrPush( vRes, Vec_WecAlloc(10) ); + 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]) ); + assert( (pTruth[0] & 1) == 0 ); + int * pSpot = Vec_MemHashLookup( vTtMem, pTruth ); + if ( *pSpot == -1 ) + continue; + int iFunc = vMap ? Vec_IntEntry( vMap, *pSpot ) : 0; + assert( iFunc < nFuncs ); + Vec_Wec_t * vCuts = (Vec_Wec_t *)Vec_PtrEntry( vRes, iFunc ); + vLevel = Vec_WecPushLevel( vCuts ); + Vec_IntPush( vLevel, i ); + for ( j = 1; j <= pCut[0]; j++ ) + Vec_IntPush( vLevel, pCut[j] ); + break; + } + } + Gia_StoFree( p ); + if ( fVerbose ) + Abc_PrintTime( 1, "Cut matching time", Abc_Clock() - clkStart ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [Function enumeration.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Gia_ManCollectCutFuncs( Gia_Man_t * p, int nCutSize, int nCutNum, int fVerbose ) +{ + Gia_Sto_t * pSto = Gia_ManMatchCutsInt( p, nCutSize, nCutNum, 0 ); + Vec_Wrd_t * vFuncs = Vec_WrdAlloc( 1000 ); Vec_Int_t * vLevel; int i, k, * pCut; + Vec_WecForEachLevel( pSto->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) + Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) if ( pCut[0] == nCutSize ) { + word * pTruth = Vec_MemReadEntry( pSto->vTtMem, Abc_Lit2Var(pCut[pCut[0]+1]) ); + Vec_WrdPush( vFuncs, pTruth[0] ); + } + Gia_StoFree( pSto ); + if ( fVerbose ) + printf( "Collected %d cut functions using the AIG with %d nodes.\n", Vec_WrdSize(vFuncs), Gia_ManAndNum(p) ); + return vFuncs; +} +Vec_Int_t * Gia_ManCountNpnClasses( Vec_Mem_t * vTtMem, Vec_Int_t * vMap, int nClasses, Vec_Wrd_t * vOrig ) +{ + assert( Vec_MemEntryNum(vTtMem) == Vec_IntSize(vMap) ); + Vec_Int_t * vClassCounts = Vec_IntStart( nClasses ); int i; word Func; + Vec_WrdForEachEntry( vOrig, Func, i ) { + int * pSpot = Vec_MemHashLookup( vTtMem, &Func ); + if ( *pSpot == -1 ) + continue; + int iClass = Vec_IntEntry( vMap, *pSpot ); + if ( iClass == -1 ) + continue; + assert( iClass < Vec_IntSize(vClassCounts) ); + Vec_IntAddToEntry( vClassCounts, iClass, 1 ); + } + return vClassCounts; +} +Vec_Wrd_t * Gia_ManMatchFilterClasses( Vec_Mem_t * vTtMem, Vec_Int_t * vMap, Vec_Int_t * vClassCounts, int nNumFuncs, int fVerbose ) +{ + int * pPerm = Abc_MergeSortCost( Vec_IntArray(vClassCounts), Vec_IntSize(vClassCounts) ); + Vec_Wrd_t * vBest = Vec_WrdAlloc( nNumFuncs ); int i, k, Entry; + Vec_Int_t * vMapNew = Vec_IntStartFull( Vec_IntSize(vMap) ); + for ( i = Vec_IntSize(vClassCounts)-1; i >= 0; i-- ) { + word Best = ~(word)0; + Vec_IntForEachEntry( vMap, Entry, k ) { + if ( Entry != pPerm[i] ) + continue; + if ( Best > Vec_MemReadEntry(vTtMem, k)[0] ) + Best = Vec_MemReadEntry(vTtMem, k)[0]; + Vec_IntWriteEntry( vMapNew, k, Vec_WrdSize(vBest) ); + } + Vec_WrdPush( vBest, Best ); + assert( ~Best ); + if ( Vec_WrdSize(vBest) == nNumFuncs ) + break; + } + ABC_SWAP( Vec_Int_t, *vMap, *vMapNew ); + Vec_IntFree( vMapNew ); + ABC_FREE( pPerm ); + if ( fVerbose ) + printf( "Isolated %d (out of %d) most frequently occuring classes.\n", Vec_WrdSize(vBest), Vec_IntSize(vClassCounts) ); + return vBest; +} +void Gia_ManMatchProfileFunctions( Vec_Wrd_t * vBestReprs, Vec_Mem_t * vTtMem, Vec_Int_t * vMap, Vec_Wrd_t * vFuncs, int nCutSize ) +{ + int BarSize = 60; + extern void Dau_DsdPrintFromTruth( word * pTruth, int nVarsInit ); + Vec_Int_t * vCounts = Gia_ManCountNpnClasses( vTtMem, vMap, Vec_WrdSize(vBestReprs), vFuncs ); + word Repr; int c, i, MaxCount = Vec_IntFindMax( vCounts ); + Vec_WrdForEachEntry( vBestReprs, Repr, c ) + { + int nSymb = BarSize*Vec_IntEntry(vCounts, c)/Abc_MaxInt(MaxCount, 1); + printf( "Class%4d : ", c ); + printf( "Count =%6d ", Vec_IntEntry(vCounts, c) ); + for ( i = 0; i < nSymb; i++ ) + printf( "*" ); + for ( i = nSymb; i < BarSize+3; i++ ) + printf( " " ); + Dau_DsdPrintFromTruth( &Repr, nCutSize ); + } + Vec_IntFree( vCounts ); +} +void Gia_ManMatchCones( Gia_Man_t * pBig, Gia_Man_t * pSmall, int nCutSize, int nCutNum, int nNumFuncs, int nNumCones, int fVerbose ) +{ + abctime clkStart = Abc_Clock(); + extern void Dau_CanonicizeArray( Vec_Wrd_t * vFuncs, int nVars, int fVerbose ); + extern Vec_Mem_t * Dau_CollectNpnFunctionsArray( Vec_Wrd_t * vFuncs, int nVars, Vec_Int_t ** pvMap, int fVerbose ); + Vec_Wrd_t * vFuncs = Gia_ManCollectCutFuncs( pSmall, nCutSize, nCutNum, fVerbose ); + Vec_Wrd_t * vOrig = Vec_WrdDup( vFuncs ); + Dau_CanonicizeArray( vFuncs, nCutSize, fVerbose ); + Vec_Int_t * vMap = NULL; int n; + Vec_Mem_t * vTtMem = Dau_CollectNpnFunctionsArray( vFuncs, nCutSize, &vMap, fVerbose ); + Vec_WrdFree( vFuncs ); + Vec_Int_t * vClassCounts = Gia_ManCountNpnClasses( vTtMem, vMap, Vec_IntEntryLast(vMap)+1, vOrig ); + Vec_Wrd_t * vBestReprs = Gia_ManMatchFilterClasses( vTtMem, vMap, vClassCounts, nNumFuncs, fVerbose ); + assert( Vec_WrdSize(vBestReprs) == nNumFuncs ); + Vec_IntFree( vClassCounts ); + printf( "Frequency profile for %d most popular classes in the small AIG:\n", nNumFuncs ); + Gia_ManMatchProfileFunctions( vBestReprs, vTtMem, vMap, vOrig, nCutSize ); + Vec_WrdFree( vOrig ); + Abc_Random( 1 ); + for ( n = 0; n < nNumCones; n++ ) { + int nRand = Abc_Random( 0 ) % Gia_ManCoNum(pBig); + Gia_Man_t * pCone = Gia_ManDupCones( pBig, &nRand, 1, 1 ); + Vec_Wrd_t * vCutFuncs = Gia_ManCollectCutFuncs( pCone, nCutSize, nCutNum, 0 ); + printf( "ITER %d: Considering output cone %d with %d and-nodes. ", n+1, nRand, Gia_ManAndNum(pCone) ); + printf( "Profiling %d functions of %d-cuts:\n", Vec_WrdSize(vCutFuncs), nCutSize ); + Gia_ManMatchProfileFunctions( vBestReprs, vTtMem, vMap, vCutFuncs, nCutSize ); + Vec_WrdFree( vCutFuncs ); + Gia_ManStop( pCone ); + } + Vec_WrdFree( vBestReprs ); + Vec_IntFree( vMap ); + Vec_MemHashFree( vTtMem ); + Vec_MemFree( vTtMem ); + Abc_PrintTime( 1, "Total computation time", Abc_Clock() - clkStart ); +} + +/**Function************************************************************* + + Synopsis [Function enumeration.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManMatchConesMinimizeTts( Vec_Wrd_t * vSims, int nVarsMax ) +{ + int nVars = 0; + int nWordsMax = Abc_Truth6WordNum( nVarsMax ), nWords; + int i, k = 0, nTruths = Vec_WrdSize(vSims) / nWordsMax; + assert( nTruths * nWordsMax == Vec_WrdSize(vSims) ); + // support-minimize and find the largest supp size + for ( i = 0; i < nTruths; i++ ) { + word * pTruth = Vec_WrdEntryP( vSims, i * nWordsMax ); + int nVarsCur = Abc_TtMinBase( pTruth, NULL, nVarsMax, nVarsMax ); + nVars = Abc_MaxInt( nVars, nVarsCur ); + } + // remap truth tables + nWords = Abc_Truth6WordNum( nVars ); + for ( i = 0; i < nTruths; i++ ) { + word * pTruth = Vec_WrdEntryP( vSims, i * nWordsMax ); + word * pTruth2 = Vec_WrdEntryP( vSims, k * nWords ); + if ( Abc_TtSupportSize(pTruth, nVars) < 3 ) + continue; + memmove( pTruth2, pTruth, nWords * sizeof(word) ); + k++; + if ( 0 ) { + extern void Extra_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars ); + printf( "Type%d : ", i ); + Extra_PrintHexadecimal( stdout, (unsigned *)pTruth2, nVars ); + printf( "\n" ); + } + } + Vec_WrdShrink ( vSims, k * nWords ); + return nVars; +} +void Gia_ManMatchConesOutputPrint( Vec_Ptr_t * p, int fVerbose ) +{ + Vec_Wec_t * vCuts; int i; + printf( "Nodes with matching cuts:\n" ); + Vec_PtrForEachEntry( Vec_Wec_t *, p, vCuts, i ) { + if ( fVerbose ) { + printf( "Type %d:\n", i ); + Vec_WecPrint( vCuts, 0 ); + } + else + printf( "Type %d present in %d cuts\n", i, Vec_WecSize(vCuts) ); + } +} +void Gia_ManMatchConesOutputFree( Vec_Ptr_t * p ) +{ + Vec_Wec_t * vCuts; int i; + Vec_PtrForEachEntry( Vec_Wec_t *, p, vCuts, i ) + Vec_WecFree( vCuts ); + Vec_PtrFree( p ); +} +void Gia_ManMatchConesOutput( Gia_Man_t * pBig, Gia_Man_t * pSmall, int nCutNum, int fVerbose ) +{ + abctime clkStart = Abc_Clock(); + extern Vec_Mem_t * Dau_CollectNpnFunctionsArray( Vec_Wrd_t * vFuncs, int nVars, Vec_Int_t ** pvMap, int fVerbose ); + Vec_Wrd_t * vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(pSmall) ); + Vec_Wrd_t * vSims = Gia_ManSimPatSimOut( pSmall, vSimsPi, 1 ); + int nVars = Gia_ManMatchConesMinimizeTts( vSims, Gia_ManCiNum(pSmall) ); + Vec_WrdFree( vSimsPi ); + if ( nVars > 10 ) { + printf( "Some output functions have support size more than 10.\n" ); + Vec_WrdFree( vSims ); + return; + } + Vec_Int_t * vMap = NULL; + Vec_Mem_t * vTtMem = Dau_CollectNpnFunctionsArray( vSims, nVars, &vMap, fVerbose ); + int nFuncs = Vec_WrdSize(vSims) / Abc_Truth6WordNum(nVars); + assert( Vec_WrdSize(vSims) == nFuncs * Abc_Truth6WordNum(nVars) ); + Vec_WrdFree( vSims ); + printf( "Using %d output functions with the support size between 3 and %d.\n", nFuncs, nVars ); + Vec_Ptr_t * vRes = Gia_ManMatchCutsMany( vTtMem, vMap, nFuncs, pBig, nVars, nCutNum, fVerbose ); + Vec_MemHashFree( vTtMem ); + Vec_MemFree( vTtMem ); + Vec_IntFree( vMap ); + Gia_ManMatchConesOutputPrint( vRes, fVerbose ); + Gia_ManMatchConesOutputFree( vRes ); + Abc_PrintTime( 1, "Total computation time", Abc_Clock() - clkStart ); +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index 92eb2ac893..87f2bb74c5 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/giaEquiv.c b/src/aig/gia/giaEquiv.c index aec9d39cac..e4f5a0d255 100644 --- a/src/aig/gia/giaEquiv.c +++ b/src/aig/gia/giaEquiv.c @@ -2732,6 +2732,57 @@ void Gia_ManTransferTest( Gia_Man_t * p ) Gia_ManStop( pNew ); } +/**Function************************************************************* + + Synopsis [Transfer from new to old.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTransferEquivs2( Gia_Man_t * p, Gia_Man_t * pOld ) +{ + Gia_Obj_t * pObj; + Vec_Int_t * vClass; + int i, k, iNode, iRepr; + assert( p->pReprs != NULL ); + assert( p->pNexts != NULL ); + assert( pOld->pReprs == NULL ); + assert( pOld->pNexts == NULL ); + // create map + Gia_ManFillValue( p ); + Gia_ManForEachObj( pOld, pObj, i ) + if ( ~pObj->Value ) + Gia_ManObj(p, Abc_Lit2Var(pObj->Value))->Value = Abc_Var2Lit(i, 0); + // start representatives + pOld->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pOld) ); + for ( i = 0; i < Gia_ManObjNum(pOld); i++ ) + Gia_ObjSetRepr( pOld, i, GIA_VOID ); + // iterate over constant candidates + Gia_ManForEachConst( p, i ) + Gia_ObjSetRepr( pOld, Abc_Lit2Var(Gia_ManObj(p, i)->Value), 0 ); + // iterate over class candidates + vClass = Vec_IntAlloc( 100 ); + Gia_ManForEachClass( p, i ) + { + Vec_IntClear( vClass ); + Gia_ClassForEachObj( p, i, k ) + if ( (int)Gia_ManObj(p, k)->Value >= 0 ) + Vec_IntPushUnique( vClass, Abc_Lit2Var(Gia_ManObj(p, k)->Value) ); + if ( Vec_IntSize( vClass ) <= 1 ) + continue; + assert( Vec_IntSize( vClass ) > 1 ); + Vec_IntSort( vClass, 0 ); + iRepr = Vec_IntEntry( vClass, 0 ); + Vec_IntForEachEntryStart( vClass, iNode, k, 1 ) + Gia_ObjSetRepr( pOld, iNode, iRepr ); + } + Vec_IntFree( vClass ); + pOld->pNexts = Gia_ManDeriveNexts( pOld ); +} /**Function************************************************************* diff --git a/src/aig/gia/giaGen.c b/src/aig/gia/giaGen.c index cb56ef64d2..a807fe60f7 100644 --- a/src/aig/gia/giaGen.c +++ b/src/aig/gia/giaGen.c @@ -924,6 +924,443 @@ void Gia_ManTestWordFile( Gia_Man_t * p, char * pFileName, char * pDumpFile, int Abc_PrintTime( 1, "Total checking time", Abc_Clock() - clk ); } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSumCount( char * p, Vec_Int_t * vDec, int b ) +{ + int i, Ent, Count = 0, Sum = 0; + for ( i = 0; p[i]; i++ ) { + Ent = (p[i] >= '0' && p[i] <= '9') ? p[i]-'0' : p[i]-'A'+10; + Count += Vec_IntEntry(vDec, Ent) + b * (1 << (Sum += Ent)); + } + return Count + b * ((1 << Sum) - 1); +} +Vec_Str_t * Gia_ManSumEnum_rec( int Num ) +{ + if ( Num == 1 ) { + Vec_Str_t * vRes = Vec_StrAlloc(2); + Vec_StrPush( vRes, '1' ); + Vec_StrPush( vRes, '\0' ); + return vRes; + } + Vec_Str_t * vRes = Vec_StrAlloc( 16 ); + for ( int i = 1; i < Num; i++ ) { + Vec_Str_t * vRes0 = Gia_ManSumEnum_rec(i); + Vec_Str_t * vRes1 = Gia_ManSumEnum_rec(Num-i); + for ( int c0 = 0; c0 < Vec_StrSize(vRes0); c0 += strlen(Vec_StrEntryP(vRes0,c0))+1 ) + for ( int c1 = 0; c1 < Vec_StrSize(vRes1); c1 += strlen(Vec_StrEntryP(vRes1,c1))+1 ) + Vec_StrPrintF( vRes, "%s%s%c", Vec_StrEntryP(vRes0,c0), Vec_StrEntryP(vRes1,c1), '\0' ); + Vec_StrPrintF( vRes, "%c%c", Num < 10 ? '0'+Num : 'A'+Num-10, '\0' ); + Vec_StrFree( vRes0 ); + Vec_StrFree( vRes1 ); + } + return vRes; +} +void Gia_ManSumEnum( int n, Vec_Int_t * vDec ) +{ + Vec_Str_t * vRes = Gia_ManSumEnum_rec( n ); + for ( int b = 1; b <= 256; b <<= 1 ) { + int iBest = -1, CountCur, CountBest = ABC_INFINITY; + for ( int c0 = 0; c0 < Vec_StrSize(vRes); c0 += strlen(Vec_StrEntryP(vRes,c0))+1 ) { + CountCur = Gia_ManSumCount( Vec_StrEntryP(vRes,c0), vDec, b ); + if ( CountBest > CountCur ) + CountBest = CountCur, iBest = c0; + } + printf( " %8d", CountBest ); + //printf( " %8s", Vec_StrEntryP(vRes,iBest) ); + //printf( " %.3f", (float)CountBest/(3*b*((1<> b) & 1 ) + Vec_IntWriteEntry( vLev, b, 1 ); + Vec_WrdForEachEntryStop( vData, Data, i, Vec_WrdSize(vData)-1 ) { + for ( n = 0; n < nIBits; n++, nLits += 2 ) { + Vec_Int_t * vLev = Vec_WecPushLevel( vArgs ); + Vec_IntFill( vLev, nOBits, 0 ); + for ( b = 0; b < nOBits; b++ ) + if ( ((Data >> b) & 1) && b+n < nOBits ) + Vec_IntWriteEntry( vLev, b+n, nLits ); + } + } + return vArgs; +} +Vec_Wec_t * Gia_ManGenNeuronTransformArgs( Gia_Man_t * pNew, Vec_Wec_t * vArgs, int nLutSize, int nOBits ) +{ + int i, nParts = (Vec_WecSize(vArgs) + nLutSize - 2) / nLutSize; + while ( Vec_WecSize(vArgs) < nLutSize*nParts+1 ) + Vec_IntFill( Vec_WecPushLevel(vArgs), nOBits, 0 ); + assert( Vec_WecSize(vArgs) == nLutSize*nParts+1 ); + Vec_Wec_t * vNew = Vec_WecAlloc( nParts ); + Vec_Int_t * vRes = Vec_WecPushLevel( vNew ), * vArg; + Vec_IntAppend( vRes, Vec_WecEntry(vArgs, 0) ); + Vec_WecForEachLevelStart( vArgs, vArg, i, 1 ) { + Gia_ManGenNeuronAdder( pNew, nOBits, Vec_IntArray(vArg), Vec_IntArray(vRes), 0, vRes ); + if ( (i-1) % nLutSize == nLutSize-1 && i < Vec_WecSize(vArgs)-1 ) { + vRes = Vec_WecPushLevel( vNew ); + Vec_IntFill( vRes, nOBits, 0 ); + } + } + assert( Vec_WecSize(vNew) == nParts ); + return vNew; +} +Vec_Wec_t * Gia_ManGenNeuronCompactArgs( Gia_Man_t * pNew, Vec_Wec_t * vArgs, int nLutSize, int nOBits ) +{ + int i, nParts = Vec_WecSize(vArgs) / 3; + Vec_Wec_t * vNew = Vec_WecAlloc( 2 * nParts + Vec_WecSize(vArgs) % 3 ); + for ( i = 0; i < nParts; i++ ) { + Vec_Int_t * vIn0 = Vec_WecEntry(vArgs, 3*i+0); + Vec_Int_t * vIn1 = Vec_WecEntry(vArgs, 3*i+1); + Vec_Int_t * vIn2 = Vec_WecEntry(vArgs, 3*i+2); + Vec_Int_t * vOut0 = Vec_WecPushLevel(vNew); + Vec_Int_t * vOut1 = Vec_WecPushLevel(vNew); + Gia_ManGenCompact( pNew, vIn0, vIn1, vIn2, vOut0, vOut1 ); + } + for ( i = 3*nParts; i < Vec_WecSize(vArgs); i++ ) + Vec_IntAppend( Vec_WecPushLevel(vNew), Vec_WecEntry(vArgs, i) ); + assert( Vec_WecSize(vNew) == 2 * nParts + Vec_WecSize(vArgs) % 3 ); + return vNew; +} +Vec_Int_t * Gia_ManGenNeuronFinal( Gia_Man_t * pNew, Vec_Wec_t * vArgs, int nOBits ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( nOBits ), * vArg; int i; + Vec_IntAppend( vRes, Vec_WecEntry(vArgs, 0) ); + Vec_WecForEachLevelStart( vArgs, vArg, i, 1 ) + Gia_ManGenNeuronAdder( pNew, nOBits, Vec_IntArray(vArg), Vec_IntArray(vRes), 0, vRes ); + return vRes; +} +int Gia_ManGenNeuronBitWidth( Vec_Wrd_t * vData, int nIBits ) +{ + int i, InMask = (1<pName = Abc_UtilStrsav( "neuron" ); + for ( i = 0; i < nIBits * (Vec_WrdSize(vData)-1); i++ ) + Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + + Vec_Wec_t * vTemp, * vArgs = Gia_ManGenNeuronCreateArgs( vData, nIBits, nOBits ); + Vec_WrdFree( vData ); + + if ( nLutSize ) { + vArgs = Gia_ManGenNeuronTransformArgs( pNew, vTemp = vArgs, nLutSize, nOBits ); + Vec_WecFree( vTemp ); + while ( Vec_WecSize(vArgs) > 2 ) { + vArgs = Gia_ManGenNeuronCompactArgs( pNew, vTemp = vArgs, nLutSize, nOBits ); + Vec_WecFree( vTemp ); + } + } + + Vec_Int_t * vRes = Gia_ManGenNeuronFinal( pNew, vArgs, nOBits ); + Vec_IntForEachEntry( vRes, Lit, i ) + Gia_ManAppendCo( pNew, Lit ); + Vec_IntFree( vRes ); + Vec_WecFree( vArgs ); + + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Generates minimum-node AIG for n-bit comparator (a > b).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupGenComp( int nBits, int fInterleave ) +{ + Gia_Man_t * pNew, * pTemp; int i, iLit = 1; + Vec_Int_t * vBitsA = Vec_IntAlloc( nBits + 1 ); + Vec_Int_t * vBitsB = Vec_IntAlloc( nBits + 1 ); + pNew = Gia_ManStart( 6*nBits+10 ); + pNew->pName = Abc_UtilStrsav( "comp" ); + Gia_ManHashAlloc( pNew ); + if ( fInterleave ) { + for ( i = 0; i < nBits; i++ ) + Vec_IntPush( vBitsA, Gia_ManAppendCi(pNew) ), + Vec_IntPush( vBitsB, Gia_ManAppendCi(pNew) ); + } + else { + for ( i = 0; i < nBits; i++ ) + Vec_IntPush( vBitsA, Gia_ManAppendCi(pNew) ); + for ( i = 0; i < nBits; i++ ) + Vec_IntPush( vBitsB, Gia_ManAppendCi(pNew) ); + } + Vec_IntPush( vBitsA, 0 ); + Vec_IntPush( vBitsB, 0 ); + for ( i = 0; i < nBits; i++ ) { + int iLitA0 = Vec_IntEntry(vBitsA, i); + int iLitA1 = Vec_IntEntry(vBitsA, i+1); + int iLitB0 = Vec_IntEntry(vBitsB, i); + int iLitB1 = Vec_IntEntry(vBitsB, i+1); + int iOrLit0; + if ( i == 0 ) + iOrLit0 = Gia_ManHashOr(pNew, Abc_LitNotCond(iLitA0, !(i&1)), Abc_LitNotCond(iLitB0, i&1)); + else + iOrLit0 = Gia_ManHashAnd(pNew, Abc_LitNotCond(iLitA0, !(i&1)), Abc_LitNotCond(iLitB0, i&1)); + int iOrLit1 = Gia_ManHashAnd(pNew, Abc_LitNotCond(iLitA1, !(i&1)), Abc_LitNotCond(iLitB1, i&1)); + int iOrLit = Gia_ManHashOr(pNew, iOrLit0, iOrLit1 ); + iLit = Gia_ManHashOr(pNew, Abc_LitNot(iLit), iOrLit ); + } + Gia_ManAppendCo( pNew, Abc_LitNotCond(iLit, nBits&1) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vBitsA ); + Vec_IntFree( vBitsB ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Generates optimized AIG for the decoder and the multiplexer.] + + 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 [Generates N-bit sorter using pair-wise sorting algorithm.] + + Description [https://en.wikipedia.org/wiki/Pairwise_sorting_network] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManGenSorterOne( Gia_Man_t * p, int * pLits, int i, int k ) +{ + int Lit1 = Gia_ManAppendAnd( p, pLits[i], pLits[k] ); + int Lit2 = Gia_ManAppendOr ( p, pLits[i], pLits[k] ); + pLits[i] = Lit1; + pLits[k] = Lit2; +} +static inline void Gia_ManGenSorterConstrMerge( Gia_Man_t * p, int * pLits, int lo, int hi, int r ) +{ + int i, step = r * 2; + if ( step < hi - lo ) + { + Gia_ManGenSorterConstrMerge( p, pLits, lo, hi-r, step ); + Gia_ManGenSorterConstrMerge( p, pLits, lo+r, hi, step ); + for ( i = lo+r; i < hi-r; i += step ) + Gia_ManGenSorterOne( p, pLits, i, i+r ); + } +} +static inline void Gia_ManGenSorterConstrRange( Gia_Man_t * p, int * pLits, int lo, int hi ) +{ + if ( hi - lo >= 1 ) + { + int i, mid = lo + (hi - lo) / 2; + for ( i = lo; i <= mid; i++ ) + Gia_ManGenSorterOne( p, pLits, i, i + (hi - lo + 1) / 2 ); + Gia_ManGenSorterConstrRange( p, pLits, lo, mid ); + Gia_ManGenSorterConstrRange( p, pLits, mid+1, hi ); + Gia_ManGenSorterConstrMerge( p, pLits, lo, hi, 1 ); + } +} +Gia_Man_t * Gia_ManGenSorter( int LogN ) +{ + int i, nVars = 1 << LogN; + int nVarsAlloc = nVars + 2 * (nVars * LogN * (LogN-1) / 4 + nVars - 1); + Vec_Int_t * vLits = Vec_IntAlloc( nVars ); + Gia_Man_t * p = Gia_ManStart( 1 + 2*nVars + nVarsAlloc ); + p->pName = Abc_UtilStrsav( "sorter" ); + for ( i = 0; i < nVars; i++ ) + Vec_IntPush( vLits, Gia_ManAppendCi(p) ); + Gia_ManGenSorterConstrRange( p, Vec_IntArray(vLits), 0, nVars - 1 ); + for ( i = 0; i < nVars; i++ ) + Gia_ManAppendCo( p, Vec_IntEntry(vLits, i) ); + Vec_IntFree( vLits ); + return p; +} + + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaIf.c b/src/aig/gia/giaIf.c index 7c5e706e89..c08a91ecd1 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); @@ -2107,7 +2208,7 @@ void Gia_ManMappingVerify( Gia_Man_t * p ) continue; if ( !Gia_ObjIsLut(p, Gia_ObjId(p, pFanin)) ) { - Abc_Print( -1, "Gia_ManMappingVerify: CO driver %d does not have mapping.\n", Gia_ObjId(p, pFanin) ); + Abc_Print( -1, "Gia_ManMappingVerify: Buffer driver %d does not have mapping.\n", Gia_ObjId(p, pFanin) ); Result = 0; continue; } @@ -2209,6 +2310,8 @@ void Gia_ManTransferPacking( Gia_Man_t * p, Gia_Man_t * pGia ) } void Gia_ManTransferTiming( Gia_Man_t * p, Gia_Man_t * pGia ) { + if ( p == pGia ) + return; if ( pGia->vCiArrs || pGia->vCoReqs || pGia->vCoArrs || pGia->vCoAttrs ) { p->vCiArrs = pGia->vCiArrs; pGia->vCiArrs = NULL; @@ -2236,7 +2339,7 @@ void Gia_ManTransferTiming( Gia_Man_t * p, Gia_Man_t * pGia ) p->vConfigs = pGia->vConfigs; pGia->vConfigs = NULL; p->pCellStr = pGia->pCellStr; pGia->pCellStr = NULL; } - if ( pGia->pManTime == NULL || p == pGia ) + if ( pGia->pManTime == NULL ) return; p->pManTime = pGia->pManTime; pGia->pManTime = NULL; p->pAigExtra = pGia->pAigExtra; pGia->pAigExtra = NULL; diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index f2d403ded6..8ce1db8344 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/giaMinLut.c b/src/aig/gia/giaMinLut.c index 5304486de4..e08ebec56e 100644 --- a/src/aig/gia/giaMinLut.c +++ b/src/aig/gia/giaMinLut.c @@ -193,7 +193,7 @@ Gia_Man_t * Vec_WrdReadTest( char * pFileName ) void Vec_WrdReadText( char * pFileName, Vec_Wrd_t ** pvSimI, Vec_Wrd_t ** pvSimO, int nIns, int nOuts ) { int i, nSize, iLine, nLines, nWords; - char pLine[1000]; + char pLine[2000]; Vec_Wrd_t * vSimI, * vSimO; FILE * pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) @@ -214,7 +214,7 @@ void Vec_WrdReadText( char * pFileName, Vec_Wrd_t ** pvSimI, Vec_Wrd_t ** pvSimO nWords = (nLines + 63)/64; vSimI = Vec_WrdStart( nIns *nWords ); vSimO = Vec_WrdStart( nOuts*nWords ); - for ( iLine = 0; fgets( pLine, 1000, pFile ); iLine++ ) + for ( iLine = 0; fgets( pLine, 2000, pFile ); iLine++ ) { for ( i = 0; i < nIns; i++ ) if ( pLine[nIns-1-i] == '1' ) @@ -233,7 +233,7 @@ void Vec_WrdReadText( char * pFileName, Vec_Wrd_t ** pvSimI, Vec_Wrd_t ** pvSimO int Vec_WrdReadText2( char * pFileName, Vec_Wrd_t ** pvSimI ) { int i, nSize, iLine, nLines, nWords, nIns; - char pLine[1000]; + char pLine[2000]; Vec_Wrd_t * vSimI; FILE * pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) @@ -241,7 +241,7 @@ int Vec_WrdReadText2( char * pFileName, Vec_Wrd_t ** pvSimI ) printf( "Cannot open file \"%s\" for reading.\n", pFileName ); return 0; } - if ( !fgets(pLine, 1000, pFile) || (nIns = strlen(pLine)-1) < 1 ) + if ( !fgets(pLine, 2000, pFile) || (nIns = strlen(pLine)-1) < 1 ) { printf( "Cannot find the number of inputs in file \"%s\".\n", pFileName ); fclose( pFile ); @@ -259,7 +259,7 @@ int Vec_WrdReadText2( char * pFileName, Vec_Wrd_t ** pvSimI ) nLines = nSize / (nIns + 1); nWords = (nLines + 63)/64; vSimI = Vec_WrdStart( nIns *nWords ); - for ( iLine = 0; fgets( pLine, 1000, pFile ); iLine++ ) + for ( iLine = 0; fgets( pLine, 2000, pFile ); iLine++ ) { for ( i = 0; i < nIns; i++ ) if ( pLine[nIns-1-i] == '1' ) diff --git a/src/aig/gia/giaMini.c b/src/aig/gia/giaMini.c index 2fce5d0d44..5f7ca0d57f 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 0000000000..b7bc0b0b6b --- /dev/null +++ b/src/aig/gia/giaMulFind.c @@ -0,0 +1,881 @@ +/**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 [] + +***********************************************************************/ +void Gia_ManMulFindXors2_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vXor ) +{ + if ( !Gia_ObjIsAnd(pObj) ) + return; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( !pObj->fMark0 ) + { + if ( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) + && Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) >= 4 + && Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) >= 4 ) + Vec_IntPushTwo( vXor, Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninId1p(p, pObj) ); + return; + } + Gia_Obj_t * pFan0, * pFan1; + int RetValue = Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1); + assert( RetValue ); + Gia_ManMulFindXors2_rec( p, Gia_Regular(pFan0), vXor ); + Gia_ManMulFindXors2_rec( p, Gia_Regular(pFan1), vXor ); +} +Vec_Wec_t * Gia_ManMulFindXors2( Gia_Man_t * p ) +{ + Vec_Wec_t * vXors = Vec_WecAlloc( 100 ); + Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj, * pFan0, * pFan1; int i; + Gia_ManCreateRefs( p ); + Gia_ManCleanMark01( p ); + Gia_ManForEachAnd( p, pObj, i ) { + if ( !Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) + continue; + Gia_Regular(pFan0)->fMark1 = 1; + Gia_Regular(pFan1)->fMark1 = 1; + pObj->fMark0 = 1; + } + Gia_ManForEachAnd( p, pObj, i ) { + if ( pObj->fMark0 && !pObj->fMark1 ) { + Gia_ManIncrementTravId( p ); + Vec_IntClear( vTemp ); + Gia_ManMulFindXors2_rec( p, pObj, vTemp ); + if ( Vec_IntSize(vTemp) > 0 ) + Vec_IntAppend( Vec_WecPushLevel(vXors), vTemp ); + } + } + Vec_IntFree( vTemp ); + return vXors; +} +int Gia_ManMulFindMaxSize( Vec_Wec_t * vXors, Vec_Int_t * vUsed ) +{ + Vec_Int_t * vLevel; int i, iBest = -1, nBestSize = 0; + Vec_WecForEachLevel( vXors, vLevel, i ) + if ( !Vec_IntEntry(vUsed, i) && nBestSize < Vec_IntSize(vLevel) ) + nBestSize = Vec_IntSize(vLevel), iBest = i; + return iBest; +} +int Gia_ManMulFindGetOverlap( 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; +} +int Gia_ManMulFindGetOverlap2( Vec_Int_t * p1, Vec_Int_t * p2 ) +{ + int i, k, ObjI, ObjK, Counter = 0; + Vec_IntForEachEntryStart( p1, ObjI, i, 1 ) + Vec_IntForEachEntry( p2, ObjK, k ) + if ( ObjI == ObjK ) + Counter++; + return Counter; +} +int Gia_ManMulFindMaxOverlap( Vec_Wec_t * vXors, Vec_Int_t * vUsed, Vec_Int_t * vFound ) +{ + Vec_Int_t * vLevel; int i, iBest = -1, nThisSize, nBestSize = 0; + Vec_WecForEachLevel( vXors, vLevel, i ) + if ( !Vec_IntEntry(vUsed, i) && nBestSize < (nThisSize = Gia_ManMulFindGetOverlap(vFound, vLevel)) ) + nBestSize = nThisSize, iBest = i; + return iBest; +} +Vec_Wec_t * Gia_ManMulFindSets( Gia_Man_t * p, Vec_Wec_t * vXors ) +{ + Vec_Wec_t * vSets = Vec_WecAlloc( 100 ); + Vec_Int_t * vUsed = Vec_IntStart( Vec_WecSize(vXors) ); + Vec_Int_t * vFound = Vec_IntAlloc( 100 ); int Item, k, Obj; + while ( (Item = Gia_ManMulFindMaxSize(vXors, vUsed)) != -1 ) { + Vec_Int_t * vTemp = Vec_WecEntry(vXors, Item); + Vec_Int_t * vNew = Vec_WecPushLevel( vSets ); + Vec_IntPush( vNew, Item ); + Vec_IntWriteEntry( vUsed, Item, 1 ); + Vec_IntClear( vFound ); + Vec_IntAppend( vFound, vTemp ); + while ( (Item = Gia_ManMulFindMaxOverlap(vXors, vUsed, vFound)) != -1 ) { + Vec_IntPush( vNew, Item ); + Vec_IntWriteEntry( vUsed, Item, 1 ); + vTemp = Vec_WecEntry(vXors, Item); + Vec_IntForEachEntry( vTemp, Obj, k ) + Vec_IntPushUnique( vFound, Obj ); + } + } + Vec_IntFree( vUsed ); + Vec_IntFree( vFound ); + return vSets; +} +int Gia_ManMulFindOne( Gia_Man_t * p, Vec_Wec_t * vXors, Vec_Int_t * vSet, Vec_Int_t * vMap, Vec_Int_t * vA, Vec_Int_t * vB, int fVerbose ) +{ + Vec_Int_t * vObjs = Vec_IntAlloc( 100 ); int i, j, Obj, Obj1, Obj2; + Vec_IntForEachEntry( vSet, Obj, i ) + Vec_IntAppend( vObjs, Vec_WecEntry(vXors, Obj) ); + Vec_IntForEachEntry( vObjs, Obj, i ) + Vec_IntAddToEntry( vMap, Obj, 1 ); + Vec_IntForEachEntry( vSet, Obj, i ) { + Vec_Int_t * vTemp = Vec_WecEntry(vXors, Obj); int k = 0; + Vec_IntForEachEntryDouble( vTemp, Obj1, Obj2, j ) + if ( Vec_IntEntry(vMap, Obj1) > 1 || Vec_IntEntry(vMap, Obj2) > 1 ) + Vec_IntWriteEntry(vTemp, k++, Obj1), Vec_IntWriteEntry(vTemp, k++, Obj2); + Vec_IntShrink( vTemp, k ); + } + Vec_IntForEachEntry( vObjs, Obj, i ) + Vec_IntWriteEntry( vMap, Obj, 0 ); + Vec_IntClear( vObjs ); + Vec_IntForEachEntry( vSet, Obj, i ) + Vec_IntAppend( vObjs, Vec_WecEntry(vXors, Obj) ); + if ( Vec_IntSize(vObjs) == 0 ) { + Vec_IntFree(vObjs); + return 0; + } + + Vec_IntClear( vA ); + Vec_IntClear( vB ); + Vec_IntPush( vA, Vec_IntPop(vObjs) ); + Vec_IntPush( vB, Vec_IntPop(vObjs) ); + while ( Vec_IntSize(vObjs) > 0 ) { + int k = 0; + Vec_IntForEachEntryDouble( vObjs, Obj1, Obj2, j ) { + if ( Vec_IntFind(vA, Obj1) >= 0 ) + Vec_IntPushUnique(vB, Obj2); + else if ( Vec_IntFind(vA, Obj2) >= 0 ) + Vec_IntPushUnique(vB, Obj1); + else if ( Vec_IntFind(vB, Obj1) >= 0 ) + Vec_IntPushUnique(vA, Obj2); + else if ( Vec_IntFind(vB, Obj2) >= 0 ) + Vec_IntPushUnique(vA, Obj1); + else { + Vec_IntWriteEntry(vObjs, k++, Obj1); + Vec_IntWriteEntry(vObjs, k++, Obj2); + } + } + Vec_IntShrink( vObjs, k ); + } + Vec_IntSort( vA, 0 ); + Vec_IntSort( vB, 0 ); + Vec_IntClear( vObjs ); + Vec_IntForEachEntry( vSet, Obj, i ) + Vec_IntAppend( vObjs, Vec_WecEntry(vXors, Obj) ); + Vec_IntForEachEntryDouble( vObjs, Obj1, Obj2, j ) + if ( !((Vec_IntFind(vA, Obj1) >= 0 && Vec_IntFind(vB, Obj2) >= 0) || + (Vec_IntFind(vA, Obj2) >= 0 && Vec_IntFind(vB, Obj1) >= 0)) ) { + if ( fVerbose ) + printf( "Internal verification failed.\n" ); + Vec_IntFree( vObjs ); + Vec_IntClear( vA ); + Vec_IntClear( vB ); + return 0; + } + if ( fVerbose ) + printf( "Generated system with %d+%d+%d=%d variables and %d equations.\n", + Vec_IntSize(vA),Vec_IntSize(vB),Vec_IntSize(vSet), + Vec_IntSize(vA)+Vec_IntSize(vB)+Vec_IntSize(vSet), Vec_IntSize(vObjs)/2 ); + Vec_IntFree( vObjs ); + return 1; +} +Vec_Wec_t * Gia_ManMulFindAInputs2( Gia_Man_t * p, int fVerbose ) +{ + Vec_Wec_t * vMuls = Vec_WecAlloc( 10 ); + Vec_Wec_t * vXors = Gia_ManMulFindXors2( p ); + Vec_Wec_t * vSets = Gia_ManMulFindSets( p, vXors ); + Vec_Int_t * vMap = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_Int_t * vA = Vec_IntAlloc( 100 ); + Vec_Int_t * vB = Vec_IntAlloc( 100 ); + Vec_Int_t * vSet; int i; + Vec_WecForEachLevel( vSets, vSet, i ) + { + if ( !Gia_ManMulFindOne(p, vXors, vSet, vMap, vA, vB, fVerbose) ) + continue; + Vec_IntAppend( Vec_WecPushLevel(vMuls), vA ); + Vec_IntAppend( Vec_WecPushLevel(vMuls), vB ); + Vec_WecPushLevel(vMuls); + } + Vec_WecFree( vXors ); + Vec_WecFree( vSets ); + Vec_IntFree( vMap ); + Vec_IntFree( vA ); + Vec_IntFree( vB ); + return vMuls; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManMulFindAddEntry1( Vec_Int_t * vPairs, int Obj ) +{ + int Entry, Sum, k; + Vec_IntForEachEntryDouble( vPairs, Entry, Sum, k ) + if ( Obj == Entry ) { + Vec_IntAddToEntry( vPairs, k+1, 1 ); + break; + } + if ( k == Vec_IntSize(vPairs) ) + Vec_IntPushTwo( vPairs, Obj, 1 ); +} +Vec_Int_t * Gia_ManMulFindCounts( Vec_Wec_t * vCuts4, Vec_Int_t * vSet ) +{ + Vec_Int_t * vCounts = Vec_IntAlloc( 10 ); + int i, k, Obj, Item; + Vec_IntForEachEntry( vSet, Item, i ) { + Vec_Int_t * vCut = Vec_WecEntry(vCuts4, Item); + Vec_IntForEachEntryStart( vCut, Obj, k, 1 ) + Gia_ManMulFindAddEntry1( vCounts, Obj ); + } + return vCounts; +} +int Gia_ManMulFindNextEntry( Vec_Wec_t * vCuts4, Vec_Int_t * vSet, int Entry ) +{ + int i, Item; + Vec_IntForEachEntry( vSet, Item, i ) { + Vec_Int_t * vCut = Vec_WecEntry(vCuts4, Item); + if ( Vec_IntSize(vCut) == 0 ) + continue; + assert( Vec_IntSize(vCut) == 3 ); + int RetValue = -1; + if ( Vec_IntEntry(vCut, 1) == Entry ) + RetValue = Vec_IntEntry(vCut, 2); + if ( Vec_IntEntry(vCut, 2) == Entry ) + RetValue = Vec_IntEntry(vCut, 1); + if ( RetValue == -1 ) + continue; + Vec_IntClear( vCut ); + return RetValue; + } + return -1; +} +void Gia_ManMulFindArg1( Vec_Wec_t * vCuts4, Vec_Int_t * vSet, Vec_Int_t * vArg1 ) +{ + Vec_Int_t * vCounts = Gia_ManMulFindCounts( vCuts4, vSet ); + int Entry = -1, Sum, k; + Vec_IntClear( vArg1 ); + Vec_IntForEachEntryDouble( vCounts, Entry, Sum, k ) + if ( Sum == 1 ) { + Vec_IntPush( vArg1, Entry ); + break; + } + assert( Entry != -1 ); + while ( (Entry = Gia_ManMulFindNextEntry(vCuts4, vSet, Entry)) != -1 ) + Vec_IntPush( vArg1, Entry ); + Vec_IntFree( vCounts ); +} +int Gia_ManMulFindNextEntryCount( Vec_Int_t * vCounts, int Entry0 ) +{ + int Entry, Sum, k; + Vec_IntForEachEntryDouble( vCounts, Entry, Sum, k ) + if ( Entry == Entry0 ) + return Sum; + return -1; +} +int Gia_ManMulFindNextEntry2( Vec_Wec_t * vCuts4, Vec_Int_t * vSet, int Entry, Vec_Int_t * vCounts, int * pEntry0, int * pEntry1 ) +{ + int i, Item; + Vec_IntForEachEntry( vSet, Item, i ) { + Vec_Int_t * vCut = Vec_WecEntry(vCuts4, Item); + if ( Vec_IntSize(vCut) == 0 ) + continue; + assert( Vec_IntSize(vCut) == 4 ); + int Entry0, Entry1, iPlace = Vec_IntFind( vCut, Entry ); + if ( iPlace == -1 ) + continue; + if ( iPlace == 1 ) + Entry0 = Vec_IntEntry(vCut, 2), Entry1 = Vec_IntEntry(vCut, 3); + else if ( iPlace == 2 ) + Entry0 = Vec_IntEntry(vCut, 1), Entry1 = Vec_IntEntry(vCut, 3); + else if ( iPlace == 3 ) + Entry0 = Vec_IntEntry(vCut, 1), Entry1 = Vec_IntEntry(vCut, 2); + else assert( 0 ); + int Count0 = Gia_ManMulFindNextEntryCount(vCounts, Entry0); + int Count1 = Gia_ManMulFindNextEntryCount(vCounts, Entry1); + *pEntry0 = Count0 <= Count1 ? Entry0 : Entry1; + *pEntry1 = Count0 <= Count1 ? Entry1 : Entry0; + // remove entries + Vec_IntForEachEntry( vSet, Item, i ) { + Vec_Int_t * vCut = Vec_WecEntry(vCuts4, Item); + if ( Vec_IntSize(vCut) == 0 ) + continue; + if ( Vec_IntFind( vCut, Entry ) >= 0 ) + Vec_IntClear( vCut ); + } + return 1; + } + return 0; +} +void Gia_ManMulFindArg2( Vec_Wec_t * vCuts5, Vec_Int_t * vSet, Vec_Int_t * vArg2, int Entry0, int Entry1 ) +{ + Vec_Int_t * vCounts = Gia_ManMulFindCounts( vCuts5, vSet ); + int Entry, Sum, k, SumMin = ABC_INFINITY, SumMax = 0; + Vec_IntForEachEntryDouble( vCounts, Entry, Sum, k ) { + SumMin = Abc_MinInt( SumMin, Sum ); + SumMax = Abc_MaxInt( SumMax, Sum ); + } + Vec_IntClear( vArg2 ); + Vec_IntForEachEntryDouble( vCounts, Entry, Sum, k ) + if ( Entry == Entry0 || Entry == Entry1 ) { + Vec_IntPush( vArg2, Entry == Entry0 ? Entry1 : Entry0 ); + Vec_IntPush( vArg2, Entry ); + break; + } + Entry = Vec_IntEntry(vArg2, 1); + while ( Gia_ManMulFindNextEntry2(vCuts5, vSet, Entry, vCounts, &Entry0, &Entry1) ) + Vec_IntPushTwo( vArg2, Entry0, Entry1 ), Entry = Entry1; + Vec_IntFree( vCounts ); +} +void Gia_ManMulFindAddEntry( Vec_Int_t * vPairs, int Obj0, int Obj1 ) +{ + int Entry0, Entry1, Sum, k; + Vec_IntForEachEntryTriple( vPairs, Entry0, Entry1, Sum, k ) + if ( Obj0 == Entry0 && Obj1 == Entry1 ) { + Vec_IntAddToEntry( vPairs, k+2, 1 ); + break; + } + if ( k == Vec_IntSize(vPairs) ) + Vec_IntPushThree( vPairs, Obj0, Obj1, 1 ); +} +Vec_Wec_t * Gia_ManMulFindBInputs2( Gia_Man_t * p, Vec_Wec_t * vCuts4, Vec_Wec_t * vCuts5, int fVerbose ) +{ + Vec_Wec_t * vRes = Vec_WecAlloc( 10 ); + Vec_Int_t * vPairs = Vec_IntAlloc( 1000 ); + Vec_Int_t * vSet = Vec_IntAlloc( 100 ); + Vec_Int_t * vCut, * vArg1, * vArg2; + int i, j, k, n, Entry0, Entry1, Sum, Obj0, Obj1; + Vec_WecForEachLevel( vCuts4, vCut, i ) + Vec_IntForEachEntryStart( vCut, Obj0, j, 1 ) + Vec_IntForEachEntryStart( vCut, Obj1, k, j+1 ) + Gia_ManMulFindAddEntry( vPairs, Obj0, Obj1 ); + Vec_IntForEachEntryTriple( vPairs, Entry0, Entry1, Sum, n ) { + if ( Sum < 3 ) + continue; + Vec_IntClear( vSet ); + Vec_WecForEachLevel( vCuts4, vCut, i ) + Vec_IntForEachEntryStart( vCut, Obj0, j, 1 ) + Vec_IntForEachEntryStart( vCut, Obj1, k, j+1 ) + if ( Obj0 == Entry0 && Obj1 == Entry1 ) { + Vec_IntPush( vSet, i ); + Vec_IntDrop( vCut, k ); + Vec_IntDrop( vCut, j ); + j = k = Vec_IntSize(vCut); + } + vArg1 = Vec_WecPushLevel(vRes); + vArg2 = Vec_WecPushLevel(vRes); + Vec_WecPushLevel(vRes); + Gia_ManMulFindArg1( vCuts4, vSet, vArg1 ); + // find overlapping with arg1 and remove nodes in arg1 + Vec_IntClear( vSet ); + Vec_WecForEachLevel( vCuts5, vCut, i ) + if ( Gia_ManMulFindGetOverlap2(vCut, vArg1) ) { + k = 1; + Vec_IntForEachEntryStart( vCut, Obj0, j, 1 ) + if ( Vec_IntFind(vArg1, Obj0) == -1 ) + Vec_IntWriteEntry( vCut, k++, Obj0 ); + Vec_IntShrink( vCut, k ); + Vec_IntPush( vSet, i ); + } + Gia_ManMulFindArg2( vCuts5, vSet, vArg2, Entry0, Entry1 ); + } + Vec_IntFree( vSet ); + Vec_IntFree( vPairs ); + return vRes; +} + +/**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 ) +{ + Abc_Random(1); + 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 ); + Vec_Int_t * vOutU = Vec_IntAlloc( 100 ); + Vec_Int_t * vOutS = Vec_IntAlloc( 100 ); + word Word; int w, iPlace; + Vec_WrdForEachEntry( vSimU, Word, w ) { + if ( (iPlace = Vec_WrdFind(vSims, Word)) >= 0 ) + Vec_IntPush( vOutU, Abc_Var2Lit(Vec_IntEntry(vTfo, iPlace), 0) ); + else if ( (iPlace = Vec_WrdFind(vSims, ~Word)) >= 0 ) + Vec_IntPush( vOutU, Abc_Var2Lit(Vec_IntEntry(vTfo, iPlace), 1) ); + else + Vec_IntPush( vOutU, -1 ); + } + Vec_WrdForEachEntry( vSimS, Word, w ) { + if ( (iPlace = Vec_WrdFind(vSims, Word)) >= 0 ) + Vec_IntPush( vOutS, Abc_Var2Lit(Vec_IntEntry(vTfo, iPlace), 0) ); + else if ( (iPlace = Vec_WrdFind(vSims, ~Word)) >= 0 ) + Vec_IntPush( vOutS, Abc_Var2Lit(Vec_IntEntry(vTfo, iPlace), 1) ); + else + Vec_IntPush( vOutS, -1 ); + } + assert( Vec_IntSize(vOut) == 0 ); + if ( Vec_IntCountEntry(vOutU, -1) < Vec_IntSize(vOutU) || + Vec_IntCountEntry(vOutS, -1) < Vec_IntSize(vOutS) ) + { + if ( Vec_IntCountEntry(vOutU, -1) < Vec_IntCountEntry(vOutS, -1) ) + Vec_IntAppend( vOut, vOutU ), Vec_IntPush(vOut, 0); + else + Vec_IntAppend( vOut, vOutS ), Vec_IntPush(vOut, 1); + } + else + { + Vec_IntClear(vIn0); + Vec_IntClear(vIn1); + } + Vec_WrdFree( vSim0 ); + Vec_WrdFree( vSim1 ); + Vec_WrdFree( vSimU ); + Vec_WrdFree( vSimS ); + Vec_WrdFree( vSims ); + Vec_IntFree( vTfo ); + Vec_IntFree( vOutU ); + Vec_IntFree( vOutS ); + } + 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_ManMulFindAInputs2( p, 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_ManMulFindBInputs2( 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 ) { + if ( Temp == -1 ) + printf( "n/a%s", i < Limit-1 ? " ":"" ); + else + 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 %d x %d: ", fBooth ? "B" : "Non-b", Vec_IntEntryLast(vOut) ? "" : "un", Vec_IntSize(vIn0), Vec_IntSize(vIn1) ); + 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 6d75f4d99c..5f2b070216 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 494b8636b6..e5aaabf37a 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 eaaf24e9e0..f41d8dd493 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 3f928e4ddd..93c4b1da92 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,136 @@ void Min_ManTest2( Gia_Man_t * p ) Vec_WrdFreeP( &vSimsPi ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_GenerateCexesDumpBlif( char * pFileName, Gia_Man_t * p, Vec_Wec_t * vCexes ) +{ + extern Vec_Ptr_t * Gia_GetFakeNames( int nNames, int fCaps ); + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) { + printf( "Cannot open output file name \"%s\".\n", pFileName ); + return; + } + int fFakeIns = 0, fFakeOuts = 0; + if ( p->vNamesIn == NULL ) + p->vNamesIn = Gia_GetFakeNames( Gia_ManCiNum(p), 0 ), fFakeIns = 1; + if ( p->vNamesOut == NULL ) + p->vNamesOut = Gia_GetFakeNames( Gia_ManCoNum(p), 1 ), fFakeOuts = 1; + + Gia_Obj_t * pObj, * pObj2; + char * pLine = ABC_CALLOC( char, Gia_ManCiNum(p)+3 ); + int i, k, c, iLit, nOuts[2] = {0}, nCexes = Vec_WecSize(vCexes) / Gia_ManCoNum(p); + fprintf( pFile, "# Satisfying assignments for the primary outputs generated by ABC on %s\n", Gia_TimeStamp() ); + fprintf( pFile, ".model %s\n", p->pName ); + fprintf( pFile, ".inputs" ); + Gia_ManForEachCi( p, pObj, i ) + fprintf( pFile, " %s", Gia_ObjCiName(p, i) ); + fprintf( pFile, "\n.outputs" ); + Gia_ManForEachCo( p, pObj, i ) + fprintf( pFile, " %s", Gia_ObjCoName(p, i) ); + fprintf( pFile, "\n" ); + Gia_ManForEachCo( p, pObj, i ) { + if ( Gia_ObjFaninLit0p(p, pObj) == 0 ) { + fprintf( pFile, ".names %s\n", Gia_ObjCoName(p, i) ); + nOuts[0]++; + } + else if ( Gia_ObjFaninLit0p(p, pObj) == 1 ) { + fprintf( pFile, ".names %s\n 1\n", Gia_ObjCiName(p, i) ); + nOuts[1]++; + } + else { + fprintf( pFile, ".names" ); + Gia_ManForEachCi( p, pObj2, c ) + fprintf( pFile, " %s", Gia_ObjCiName(p, c) ); + fprintf( pFile, " %s\n", Gia_ObjCoName(p, i) ); + 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, "%s 1\n", pLine ); + } + nOuts[1]++; + } + } + fprintf( pFile, ".end\n\n" ); + fclose( pFile ); + printf( "Information about %d sat, %d unsat, and %d undecided primary outputs was written into BLIF file \"%s\".\n", + nOuts[1], nOuts[0], Gia_ManCoNum(p)-nOuts[1]-nOuts[0], pFileName ); + free( pLine ); + + if ( fFakeIns ) Vec_PtrFreeFree( p->vNamesIn ), p->vNamesIn = NULL; + if ( fFakeOuts ) Vec_PtrFreeFree( p->vNamesOut ), p->vNamesOut = NULL; +} +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 fBlif, 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 ); + if ( fBlif ) + Gia_GenerateCexesDumpBlif( pFileName, p, vCexes ); + else + 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 6ccbe46053..1525e7d831 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 33fd5276d4..fc6fd7bf02 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 3203a6996e..85d5bb094a 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 c3a211849d..6a25cfd898 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/giaSif.c b/src/aig/gia/giaSif.c index c52ab4dd93..4df5c47f77 100644 --- a/src/aig/gia/giaSif.c +++ b/src/aig/gia/giaSif.c @@ -645,6 +645,25 @@ Gia_Man_t * Gia_ManSifPerform( Gia_Man_t * p, int nLutSize, int fEvalOnly, int f pNew = Gia_ManSifTransform( p, vCuts, vTimes, nLutSize, Upper, fVerbose ); Vec_IntFree( vCuts ); Vec_IntFree( vTimes ); + //Gia_ManTransferTiming( pNew, p ); + if ( p->vNamesIn ) { + char * pName; int i; + pNew->vNamesIn = p->vNamesIn; p->vNamesIn = NULL; + Vec_PtrForEachEntryStart( char *, pNew->vNamesIn, pName, i, Gia_ManPiNum(pNew) ) + ABC_FREE( pName ); + Vec_PtrShrink( pNew->vNamesIn, Gia_ManPiNum(pNew) ); + for ( i = 0; i < Gia_ManRegNum(pNew); i++ ) + Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsavNum("_fo", i) ); + } + if ( p->vNamesOut ) { + char * pName; int i; + pNew->vNamesOut = p->vNamesOut; p->vNamesOut = NULL; + Vec_PtrForEachEntryStart( char *, pNew->vNamesOut, pName, i, Gia_ManPoNum(pNew) ) + ABC_FREE( pName ); + Vec_PtrShrink( pNew->vNamesOut, Gia_ManPoNum(pNew) ); + for ( i = 0; i < Gia_ManRegNum(pNew); i++ ) + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsavNum("_fi", i) ); + } return pNew; } diff --git a/src/aig/gia/giaSimBase.c b/src/aig/gia/giaSimBase.c index 97335d3783..87614c4908 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 fc65c80bb7..68e23019ec 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; @@ -145,7 +114,11 @@ Gia_Man_t * Gia_StochProcessOne( Gia_Man_t * p, char * pScript, int Rand, int Ti sprintf( FileName, "%06x.aig", Rand ); Gia_AigerWrite( p, FileName, 0, 0, 0 ); sprintf( Command, "./abc -q \"&read %s; %s; &write %s\"", FileName, pScript, FileName ); +#if defined(__wasm) + if ( 1 ) +#else if ( system( (char *)Command ) ) +#endif { fprintf( stderr, "The following command has returned non-zero exit status:\n" ); fprintf( stderr, "\"%s\"\n", (char *)Command ); @@ -162,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 - 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 ); + if ( nProcs <= 2 ) { + if ( fVerbose ) + printf( "Running non-concurrent synthesis.\n" ), fflush(stdout); + Gia_StochProcessArray( vGias, pScript, TimeSecs, fVerbose ); + return; } - // 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--; + 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); + 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 ); } - // 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 894e26b7d0..558411eda2 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 4722ef0f59..bf94ad72dd 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 aa600c0c0d..f7b300c0d0 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/giaTtopt.cpp b/src/aig/gia/giaTtopt.cpp index a765633f8c..7f16b0d06a 100644 --- a/src/aig/gia/giaTtopt.cpp +++ b/src/aig/gia/giaTtopt.cpp @@ -1176,6 +1176,17 @@ Gia_Man_t * Gia_ManTtoptCare( Gia_Man_t * p, int nIns, int nOuts, int nRounds, c { vSupp = Gia_ManCollectSuppNew( p, g, nOuts ); nInputs = Vec_IntSize( vSupp ); + if ( nInputs == 0 ) + { + for ( k = 0; k < nOuts; k++ ) + { + pObj = Gia_ManCo( p, g+k ); + pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ObjFanin0(pObj), vSupp ); + Gia_ManAppendCo( pNew, pTruth[0] & 1 ); + } + Vec_IntFree( vSupp ); + continue; + } Ttopt::TruthTableLevelTSM tt( nInputs, nOuts ); for ( k = 0; k < nOuts; k++ ) { diff --git a/src/aig/gia/giaUtil.c b/src/aig/gia/giaUtil.c index 69a6e7235c..de71499358 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; @@ -135,6 +140,42 @@ char * Gia_FileNameGenericAppend( char * pBase, char * pSuffix ) return Buffer; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Gia_GetFakeNames( int nNames, int fCaps ) +{ + Vec_Ptr_t * vNames; + char Buffer[5]; + int i; + + vNames = Vec_PtrAlloc( nNames ); + for ( i = 0; i < nNames; i++ ) + { + if ( nNames < 26 ) + { + Buffer[0] = (fCaps ? 'A' : 'a') + i; + Buffer[1] = 0; + } + else + { + Buffer[0] = (fCaps ? 'A' : 'a') + i%26; + Buffer[1] = '0' + i/26; + Buffer[2] = 0; + } + Vec_PtrPush( vNames, Extra_UtilStrsav(Buffer) ); + } + return vNames; +} + /**Function************************************************************* Synopsis [] @@ -755,6 +796,23 @@ void Gia_ManCreateRefs( Gia_Man_t * p ) Gia_ObjRefFanin0Inc( p, pObj ); } } +void Gia_ManCreateLitRefs( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + assert( p->pRefs == NULL ); + p->pRefs = ABC_CALLOC( int, 2*Gia_ManObjNum(p) ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + { + p->pRefs[Gia_ObjFaninLit0(pObj, i)]++; + p->pRefs[Gia_ObjFaninLit1(pObj, i)]++; + } + else if ( Gia_ObjIsCo(pObj) ) + p->pRefs[Gia_ObjFaninLit0(pObj, i)]++; + } +} /**Function************************************************************* @@ -3274,6 +3332,238 @@ void Gia_ManTestProblem() } } +/**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; +} + +/**Function************************************************************* + + Synopsis [Computing equivalent nodes across the two AIGs.] + + Description [Assumes that both AIGs are structurally hashed without dandling nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCreateDualOutputMiter( Gia_Man_t * p0, Gia_Man_t * p1 ) +{ + Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; + assert( Gia_ManCiNum(p0) == Gia_ManCiNum(p1) ); + assert( Gia_ManCoNum(p0) == Gia_ManCoNum(p1) ); + // start the manager + pNew = Gia_ManStart( Gia_ManObjNum(p0) + Gia_ManObjNum(p1) ); + pNew->pName = Abc_UtilStrsav( "miter" ); + Gia_ManFillValue( p0 ); + Gia_ManFillValue( p1 ); + // map combinational inputs + Gia_ManConst0(p0)->Value = 0; + Gia_ManConst0(p1)->Value = 0; + Gia_ManForEachCi( p0, pObj, i ) + Gia_ManCi(p1, i)->Value = pObj->Value = Gia_ManAppendCi( pNew ); + // map internal nodes and outputs + Gia_ManHashAlloc( pNew ); + Gia_ManForEachAnd( p0, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + assert( Gia_ManAndNum(pNew) == Gia_ManAndNum(p0) ); // the input AIG p0 is structurally hashed + Gia_ManForEachAnd( p1, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // add the outputs + Gia_ManForEachCo( p0, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManForEachCo( p1, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + printf( "The two AIGs have %d structurally equivalent nodes.\n", Gia_ManAndNum(p0) + Gia_ManAndNum(p1) - Gia_ManAndNum(pNew) ); + // there should be no dangling nodes (otherwise, the second AIG may not be structurally hashed) + int nDangling = Gia_ManMarkDangling(pNew); + assert( nDangling == 0 ); + Gia_ManCleanMark01(pNew); + return pNew; +} +Vec_Int_t * Gia_ManFindMutualEquivs( Gia_Man_t * p0, Gia_Man_t * p1, int nConflictLimit, int fVerbose ) +{ + Vec_Int_t * vPairs = Vec_IntAlloc( 100 ); + // derive the miter + Gia_Man_t * pMiter = Gia_ManCreateDualOutputMiter( p0, p1 ); + //Gia_ManPrintStats( pMiter, NULL ); + //Gia_AigerWrite( pMiter, "out.aig", 0, 0, 0 ); + // perform SAT sweeping + extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); + Gia_Man_t * pNew = Cec4_ManSimulateTest3( pMiter, nConflictLimit, fVerbose ); + Gia_ManStop( pNew ); + // now, pMiter is annotated with the equiv class info + + // here we collect AIG node pairs with the following properties: + // - the first node belongs to p0; the second node belongs to p1 + // - both nodes are internal nodes of p0 and p1 (not primary inputs/outputs) + // - these nodes are combinationally equivalent (possibly up to the complement) + // - these nodes are "singleton" equivalences (no other nodes in p0 and p1 are equivalent to them) + // - these nodes are not structurally equivalent (that is, they have structurally different TFI logic cones) + + // count the number of nodes in each equivalence class + Vec_Int_t * vCounts = Vec_IntStart( Gia_ManObjNum(pMiter) ); + Gia_Obj_t * pObj; int i, k; + Gia_ManForEachClass( pMiter, i ) + Gia_ClassForEachObj( pMiter, i, k ) + Vec_IntAddToEntry( vCounts, i, 1 ); + + // map each miter node coming from p1 into the corresponding node in p1 + Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(pMiter) ); + int iStartP1 = 1 + Gia_ManPiNum(p0) + Gia_ManAndNum(p0); + Gia_ManForEachAnd( p1, pObj, i ) + if ( Abc_Lit2Var(pObj->Value) >= iStartP1 ) // node from p1 (not from p0) + Vec_IntWriteEntry( vMap, Abc_Lit2Var(pObj->Value), i ); + + // go through functionally (not structurally!) equivalent nodes in the second AIG + // and collect those node pairs from p0 and p1 whose equivalence class contains exactly two nodes + for ( i = iStartP1; i < Gia_ManObjNum(pMiter) - Gia_ManCoNum(pMiter); i++ ) { + assert( Gia_ObjIsAnd(Gia_ManObj(pMiter, i)) ); + int Repr = Gia_ObjRepr(pMiter, i); + if ( Repr == GIA_VOID || Repr >= iStartP1 || Vec_IntEntry(vCounts, Repr) != 2 ) + continue; + assert( Repr < iStartP1 ); // node in p0 + assert( Vec_IntEntry(vMap, i) > 0 ); // node in p1 + Vec_IntPushTwo( vPairs, Repr, Vec_IntEntry(vMap, i) ); + } + // cleanup + Vec_IntFree( vMap ); + Vec_IntFree( vCounts ); + Gia_ManStop( pMiter ); + return vPairs; +} +void Gia_ManFindMutualEquivsTest() +{ + Gia_Man_t * p0 = Gia_AigerRead( "p0.aig", 0, 0, 0 ); + Gia_Man_t * p1 = Gia_AigerRead( "p1.aig", 0, 0, 0 ); + Vec_Int_t * vPairs = Gia_ManFindMutualEquivs( p0, p1, 0, 0 ); + printf( "Pair Aig0 node Aig1 node\n" ); + int i, Obj0, Obj1; + Vec_IntForEachEntryDouble( vPairs, Obj0, Obj1, i ) + printf( "%3d %6d %6d\n", i/2, Obj0, Obj1 ); + Gia_ManStop( p0 ); + Gia_ManStop( p1 ); + Vec_IntFree( vPairs ); +} + + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/module.make b/src/aig/gia/module.make index 9e5ae3a57c..27240f443c 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/aig/saig/saig.h b/src/aig/saig/saig.h index 16e7fb4421..4744b8f86d 100644 --- a/src/aig/saig/saig.h +++ b/src/aig/saig/saig.h @@ -114,7 +114,7 @@ extern Aig_Man_t * Saig_ManDupFoldConstrs( Aig_Man_t * pAig, Vec_Int_t * v extern int Saig_ManDetectConstrTest( Aig_Man_t * p ); extern void Saig_ManDetectConstrFuncTest( Aig_Man_t * p, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose ); /*=== saigConstr2.c ==========================================================*/ -extern Aig_Man_t * Saig_ManDupFoldConstrsFunc( Aig_Man_t * pAig, int fCompl, int fVerbose ); +extern Aig_Man_t * Saig_ManDupFoldConstrsFunc( Aig_Man_t * pAig, int fCompl, int fVerbose, int fSeqCleanup ); extern Aig_Man_t * Saig_ManDupUnfoldConstrsFunc( Aig_Man_t * pAig, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose ); // -- jlong -- begin extern Aig_Man_t * Saig_ManDupFoldConstrsFunc2( Aig_Man_t * pAig, int fCompl, int fVerbose, int typeII_cnt ); diff --git a/src/aig/saig/saigConstr2.c b/src/aig/saig/saigConstr2.c index 6e560b59e4..79f557616e 100644 --- a/src/aig/saig/saigConstr2.c +++ b/src/aig/saig/saigConstr2.c @@ -939,7 +939,7 @@ Aig_Man_t * Saig_ManDupUnfoldConstrsFunc( Aig_Man_t * pAig, int nFrames, int nCo SeeAlso [] ***********************************************************************/ -Aig_Man_t * Saig_ManDupFoldConstrsFunc( Aig_Man_t * pAig, int fCompl, int fVerbose ) +Aig_Man_t * Saig_ManDupFoldConstrsFunc( Aig_Man_t * pAig, int fCompl, int fVerbose, int fSeqCleanup ) { Aig_Man_t * pAigNew; Aig_Obj_t * pMiter, * pFlopOut, * pFlopIn, * pObj; @@ -1000,7 +1000,8 @@ Aig_Man_t * Saig_ManDupFoldConstrsFunc( Aig_Man_t * pAig, int fCompl, int fVerbo // perform cleanup Aig_ManCleanup( pAigNew ); - Aig_ManSeqCleanup( pAigNew ); + if ( fSeqCleanup ) + Aig_ManSeqCleanup( pAigNew ); return pAigNew; } diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index 4bbf8a3a2b..79f73a4f52 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 805b91daa4..68b5688b8b 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 2c8e03b34b..3c8fd383e3 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 efe10a49c1..cdd53fc20c 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 ); @@ -363,7 +363,11 @@ void Abc_ShowFile( char * FileNameDot, int fKeepDot ) // generate the PostScript file using DOT sprintf( CommandDot, "%s -Tps -o %s %s", pDotName, FileNamePs, FileNameDot ); +#if defined(__wasm) + RetValue = -1; +#else RetValue = system( CommandDot ); +#endif if ( RetValue == -1 ) { fprintf( stdout, "Command \"%s\" did not succeed.\n", CommandDot ); @@ -401,7 +405,11 @@ void Abc_ShowFile( char * FileNameDot, int fKeepDot ) char CommandPs[1000]; if ( !fKeepDot ) unlink( FileNameDot ); sprintf( CommandPs, "%s %s &", pGsNameUnix, FileNamePs ); +#if defined(__wasm) + if ( 1 ) +#else if ( system( CommandPs ) == -1 ) +#endif { fprintf( stdout, "Cannot execute \"%s\".\n", CommandPs ); return; diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 49d3355ca5..5441eb973e 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -60,6 +60,7 @@ #include "opt/sbd/sbd.h" #include "bool/rpo/rpo.h" #include "map/mpm/mpm.h" +#include "map/mio/mio.h" #include "opt/fret/fretime.h" #include "opt/nwk/nwkMerge.h" #include "base/acb/acbPar.h" @@ -148,9 +149,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 ); @@ -179,6 +183,7 @@ static int Abc_CommandSwapPos ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandRemovePo ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDropSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAddPi ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAddFlop ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAppend ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPutOnTop ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFrames ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -212,6 +217,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 ); @@ -422,6 +429,7 @@ static int Abc_CommandAbc9Strash ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Topand ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Add1Hot ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Cof ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Cofs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Trim ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Dfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Sim ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -601,8 +609,21 @@ 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_CommandAbc9GenComp ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GenSorter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GenNeuron ( 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 +949,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 ); @@ -960,6 +984,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Various", "removepo", Abc_CommandRemovePo, 1 ); Cmd_CommandAdd( pAbc, "Various", "dropsat", Abc_CommandDropSat, 1 ); Cmd_CommandAdd( pAbc, "Various", "addpi", Abc_CommandAddPi, 1 ); + Cmd_CommandAdd( pAbc, "Various", "addflop", Abc_CommandAddFlop, 1 ); Cmd_CommandAdd( pAbc, "Various", "append", Abc_CommandAppend, 1 ); Cmd_CommandAdd( pAbc, "Various", "putontop", Abc_CommandPutOnTop, 1 ); Cmd_CommandAdd( pAbc, "Various", "frames", Abc_CommandFrames, 1 ); @@ -993,6 +1018,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 ); @@ -1201,6 +1228,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&topand", Abc_CommandAbc9Topand, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&add1hot", Abc_CommandAbc9Add1Hot, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cof", Abc_CommandAbc9Cof, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&cofs", Abc_CommandAbc9Cofs, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&trim", Abc_CommandAbc9Trim, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&dfs", Abc_CommandAbc9Dfs, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&sim", Abc_CommandAbc9Sim, 0 ); @@ -1386,10 +1414,23 @@ 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", "&gencomp", Abc_CommandAbc9GenComp, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&gensorter", Abc_CommandAbc9GenSorter, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&genneuron", Abc_CommandAbc9GenNeuron, 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(); @@ -1567,7 +1608,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-f : toggles printing the literal count in the factored forms [default = %s]\n", fFactor? "yes": "no" ); Abc_Print( -2, "\t-b : toggles saving the best logic network in \"best.blif\" [default = %s]\n", fSaveBest? "yes": "no" ); Abc_Print( -2, "\t-d : toggles dumping statistics about the network into file [default = %s]\n", fDumpResult? "yes": "no" ); - Abc_Print( -2, "\t-l : toggles printing delay of LUT mapping using LUT library [default = %s]\n", fSaveBest? "yes": "no" ); + Abc_Print( -2, "\t-l : toggles printing delay of LUT mapping using LUT library [default = %s]\n", fUseLutLib? "yes": "no" ); Abc_Print( -2, "\t-t : toggles printing runtime statistics [default = %s]\n", fPrintTime? "yes": "no" ); Abc_Print( -2, "\t-m : toggles printing MUX statistics [default = %s]\n", fPrintMuxes? "yes": "no" ); Abc_Print( -2, "\t-p : toggles printing power dissipation due to switching [default = %s]\n", fPower? "yes": "no" ); @@ -3206,7 +3247,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 +3257,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 +3278,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 +3295,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 +3310,7 @@ int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) 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 +3328,15 @@ int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ 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 +3349,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 +3363,7 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Print( -1, "Empty network.\n" ); return 1; - } + } if ( fGlobal ) { @@ -3328,7 +3378,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 +3402,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 +3420,7 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) 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; } @@ -3801,7 +3855,7 @@ int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "usage: strash [-acrih]\n" ); Abc_Print( -2, "\t transforms combinational logic into an AIG\n" ); Abc_Print( -2, "\t-a : toggles between using all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "DFS" ); - Abc_Print( -2, "\t-c : toggles cleanup to remove the dagling AIG nodes [default = %s]\n", fCleanup? "all": "DFS" ); + Abc_Print( -2, "\t-c : toggles cleanup to remove the dangling AIG nodes [default = %s]\n", fCleanup? "all": "DFS" ); Abc_Print( -2, "\t-r : toggles using the record of AIG subgraphs [default = %s]\n", fRecord? "yes": "no" ); Abc_Print( -2, "\t-i : toggles complementing the POs of the AIG [default = %s]\n", fComplOuts? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -5181,18 +5235,14 @@ int Abc_CommandLutpack( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ 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 +5255,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 +5273,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 +5284,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; @@ -7252,7 +7306,11 @@ int Abc_CommandRunSat( Abc_Frame_t * pAbc, int argc, char ** argv ) sprintf( pCommand, "kissat -q --seed=%d %s", i, pFileCnf ); else if ( fWalk ) sprintf( pCommand, "walk -s%d %s", i, pFileCnf ); +#if defined(__wasm) + if (1) { +#else if (system(pCommand) == -1) { +#endif fprintf(stdout, "Command \"%s\" did not succeed.\n", pCommand); return 0; } @@ -7384,14 +7442,58 @@ int Abc_CommandRunEco( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandRunGen( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Acb_NtkRunGen( char * pFileNames[2], int fVerbose ); - char * pFileNames[4] = {NULL}; - int c, fVerbose = 0; + extern void Acb_NtkRunGen( int nInputs, int nMints, int nFuncs, int Seed, int fVerbose, char * pScript ); + int c, nInputs = 10, nMints = 10, nFuncs = 10, Seed = 0, fVerbose = 0; char * pScript = NULL; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "IMRSCvh" ) ) != EOF ) { switch ( c ) { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nInputs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nMints = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nFuncs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by a script.\n" ); + goto usage; + } + pScript = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'v': fVerbose ^= 1; break; @@ -7401,21 +7503,24 @@ int Abc_CommandRunGen( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - if ( argc - globalUtilOptind != 2 ) + if ( pScript == NULL ) { - Abc_Print( 1, "Expecting two file names on the command line.\n" ); - goto usage; + Abc_Print( -1, "Command line switch \"-C\" should be specified and followed by a string.\n" ); + goto usage; } - for ( c = 0; c < 2; c++ ) - pFileNames[c] = argv[globalUtilOptind+c]; - Acb_NtkRunGen( pFileNames, fVerbose ); + Acb_NtkRunGen( nInputs, nMints, nFuncs, Seed, fVerbose, pScript ); return 0; usage: - Abc_Print( -2, "usage: rungen [-vh] \n" ); - Abc_Print( -2, "\t experimental command\n" ); - Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "usage: rungen [-IMRS num] [-C script] [-vh]\n" ); + Abc_Print( -2, "\t running the script on a set of randomly generated functions\n" ); + Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", nInputs ); + Abc_Print( -2, "\t-M : the number of positive minterms in the random function [default = %d]\n", nMints ); + Abc_Print( -2, "\t-R : the number of random functions to try [default = %d]\n", nFuncs ); + Abc_Print( -2, "\t-S : the random seed [default = %d]\n", Seed ); + Abc_Print( -2, "\t-C : the script to apply [default = provided by the user]\n" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -8346,6 +8451,182 @@ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) 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 [] @@ -8360,6 +8641,7 @@ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) 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(); @@ -8391,7 +8673,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: @@ -8599,6 +8884,123 @@ int Abc_CommandCascade( Abc_Frame_t * pAbc, int argc, char ** argv ) 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 nLuts, int nRails, int nIters, int fVerbose ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; + int c, nLutSize = 6, nLuts = 8, nRails = 1, nIters = 1, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KNRIvh" ) ) != 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 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nLuts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLuts < 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; + } + nRails = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nRails < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case '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; + } + if ( Abc_NtkCiNum(pNtk) > nLutSize + (nLutSize - nRails) * (nLuts - 1) ) + { + Abc_Print( -1, "Cannot decompose %d-input function into a %d-rail cascade of %d %d-LUTs (max suppose size = %d).\n", + Abc_NtkCiNum(pNtk), nRails, nLuts, nLutSize, nLutSize + (nLutSize - nRails) * (nLuts - 1) ); + return 1; + } + pNtkRes = Abc_NtkLutCascade( pNtk, nLutSize, nLuts, nRails, nIters, 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 [-KNRI ] [-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-N : the number of LUTs in the cascade [default = %d]\n", nLuts ); + Abc_Print( -2, "\t-R : the number of direct connections (rails) [default = %d]\n", nRails ); + Abc_Print( -2, "\t-I : the number of iterations when looking for a solution [default = %d]\n", nIters ); + 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 [] @@ -9476,8 +9878,7 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t synthesizes the smallest circuit composed of two-input gates\n" ); Abc_Print( -2, "\t for the only NPN class of 5-input functions that requires 12 gates;\n" ); Abc_Print( -2, "\t all other functions can be realized with 11 two-input gates or less\n" ); - Abc_Print( -2, "\t (see Section 7.1.2 \"Boolean evaluation\" in the book by Donald Knuth\n" ); - Abc_Print( -2, "\t http://www.cs.utsa.edu/~wagner/knuth/fasc0c.pdf)\n" ); + Abc_Print( -2, "\t (see Section 7.1.2 \"Boolean evaluation\" in the book The Art of Computer Programming by Donald Knuth)\n" ); return 1; } @@ -9494,13 +9895,14 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ); + extern int Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ); extern void Exa3_ManExactSynthesis2( Bmc_EsPar_t * pPars ); + extern void Exa3_ManExactSynthesisRand( Bmc_EsPar_t * pPars ); int c; Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "INKTiaogvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "INKTSRMiaocgvh" ) ) != EOF ) { switch ( c ) { @@ -9548,6 +9950,33 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->RuntimeLim < 0 ) goto usage; break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + pPars->pSymStr = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nRandFuncs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMintNum = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; case 'i': pPars->fUseIncr ^= 1; break; @@ -9557,6 +9986,9 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'o': pPars->fFewerVars ^= 1; break; + case 'c': + pPars->fLutCascade ^= 1; + break; case 'g': pPars->fGlucose ^= 1; break; @@ -9571,16 +10003,21 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) } if ( argc == globalUtilOptind + 1 ) pPars->pTtStr = argv[globalUtilOptind]; - if ( pPars->pTtStr == NULL ) + if ( pPars->pTtStr == NULL && pPars->pSymStr == NULL && pPars->nRandFuncs == 0 ) { Abc_Print( -1, "Truth table should be given on the command line.\n" ); return 1; } - if ( (1 << (pPars->nVars-2)) != (int)strlen(pPars->pTtStr) ) + if ( pPars->pTtStr && (1 << (pPars->nVars-2)) != (int)strlen(pPars->pTtStr) ) { Abc_Print( -1, "Truth table is expected to have %d hex digits (instead of %d).\n", (1 << (pPars->nVars-2)), strlen(pPars->pTtStr) ); return 1; } + if ( pPars->pSymStr && pPars->nVars+1 != strlen(pPars->pSymStr) ) + { + Abc_Print( -1, "The char string of the %d-variable symmetric function should have %d zeros and ones (instead of %d).\n", pPars->nVars, pPars->nVars+1, strlen(pPars->pSymStr) ); + return 1; + } if ( pPars->nVars > pPars->nNodes * (pPars->nLutSize - 1) + 1 ) { Abc_Print( -1, "Function with %d variales cannot be implemented with %d %d-input LUTs.\n", pPars->nVars, pPars->nNodes, pPars->nLutSize ); @@ -9596,22 +10033,30 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Node size should not be more than 6 inputs.\n" ); return 1; } - if ( pPars->fGlucose ) + if ( pPars->nRandFuncs ) { + pPars->fGlucose = 1; + Exa3_ManExactSynthesisRand( pPars ); + } + else if ( pPars->fGlucose ) Exa3_ManExactSynthesis( pPars ); else Exa3_ManExactSynthesis2( pPars ); return 0; usage: - Abc_Print( -2, "usage: lutexact [-INKT ] [-iaogvh] \n" ); + Abc_Print( -2, "usage: lutexact [-INKTRM ] [-S string] [-iaocgvh] \n" ); Abc_Print( -2, "\t exact synthesis of I-input function using N K-input gates\n" ); Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", pPars->nVars ); Abc_Print( -2, "\t-N : the number of K-input nodes [default = %d]\n", pPars->nNodes ); Abc_Print( -2, "\t-K : the number of node fanins [default = %d]\n", pPars->nLutSize ); Abc_Print( -2, "\t-T : the runtime limit in seconds [default = %d]\n", pPars->RuntimeLim ); + Abc_Print( -2, "\t-R : the number of random functions to try [default = unused]\n" ); + Abc_Print( -2, "\t-M : the number of positive minterms in the random function [default = unused]\n" ); + Abc_Print( -2, "\t-S : charasteristic string of a symmetric function [default = %d]\n", pPars->pSymStr ); Abc_Print( -2, "\t-i : toggle using incremental solving [default = %s]\n", pPars->fUseIncr ? "yes" : "no" ); Abc_Print( -2, "\t-a : toggle using only AND-gates when K = 2 [default = %s]\n", pPars->fOnlyAnd ? "yes" : "no" ); Abc_Print( -2, "\t-o : toggle using additional optimizations [default = %s]\n", pPars->fFewerVars ? "yes" : "no" ); + Abc_Print( -2, "\t-c : toggle synthesizing a single-rail cascade [default = %s]\n", pPars->fLutCascade ? "yes" : "no" ); Abc_Print( -2, "\t-g : toggle using Glucose 3.0 by Gilles Audemard and Laurent Simon [default = %s]\n", pPars->fGlucose ? "yes" : "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose ? "yes" : "no" ); Abc_Print( -2, "\t-h : print the command usage\n" ); @@ -10192,7 +10637,10 @@ int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) 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; } @@ -10861,7 +11309,7 @@ int Abc_CommandDropSat( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandAddPi( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; // set defaults @@ -10883,14 +11331,14 @@ int Abc_CommandAddPi( Abc_Frame_t * pAbc, int argc, char ** argv ) } // get the new network - pNtkRes = Abc_NtkDup( pNtk ); - if ( Abc_NtkPiNum(pNtkRes) == 0 ) + if ( Abc_NtkPiNum(pNtk) == 0 ) { + Abc_Ntk_t * pNtkRes = Abc_NtkDup( pNtk ); Abc_Obj_t * pObj = Abc_NtkCreatePi( pNtkRes ); Abc_ObjAssignName( pObj, "dummy_pi", NULL ); Abc_NtkOrderCisCos( pNtkRes ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); } - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: @@ -10900,6 +11348,59 @@ int Abc_CommandAddPi( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAddFlop( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -2, "The current network is not an AIG (run \"strash\").\n"); + return 0; + } + // get the new network + if ( Abc_NtkLatchNum(pNtk) == 0 ) + { + Abc_Ntk_t * pNtkRes = Abc_NtkDup( pNtk ); + Abc_NtkAddLatch( pNtkRes, Abc_AigConst1(pNtkRes), ABC_INIT_ONE ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + } + return 0; + +usage: + Abc_Print( -2, "usage: addflop [-h]\n" ); + Abc_Print( -2, "\t if the network has no flops, add one dummy flop\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -11369,6 +11870,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" ); @@ -13864,6 +14370,197 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) 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 [] @@ -14807,6 +15504,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" ); @@ -16987,6 +17685,36 @@ int Abc_CommandQbf( Abc_Frame_t * pAbc, int argc, char ** argv ) 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; } @@ -18441,7 +19169,7 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) int fUseBuffs; int fVerbose; int c; - extern Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, double AreaMulti, double DelayMulti, float LogFan, float Slew, float Gain, int nGatesMin, int fRecovery, int fSwitching, int fSkipFanout, int fUseProfile, int fUseBuffs, int fVerbose ); + extern Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, Mio_Library_t* userLib, double DelayTarget, double AreaMulti, double DelayMulti, float LogFan, float Slew, float Gain, int nGatesMin, int fRecovery, int fSwitching, int fSkipFanout, int fUseProfile, int fUseBuffs, int fVerbose ); extern int Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); pNtk = Abc_FrameReadNtk(pAbc); @@ -18592,7 +19320,7 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) } Abc_Print( 0, "The network was strashed and balanced before mapping.\n" ); // get the new network - pNtkRes = Abc_NtkMap( pNtk, DelayTarget, AreaMulti, DelayMulti, LogFan, Slew, Gain, nGatesMin, fRecovery, fSwitching, fSkipFanout, fUseProfile, fUseBuffs, fVerbose ); + pNtkRes = Abc_NtkMap( pNtk, /*userLib=*/NULL, DelayTarget, AreaMulti, DelayMulti, LogFan, Slew, Gain, nGatesMin, fRecovery, fSwitching, fSkipFanout, fUseProfile, fUseBuffs, fVerbose ); if ( pNtkRes == NULL ) { Abc_NtkDelete( pNtk ); @@ -18604,7 +19332,7 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) else { // get the new network - pNtkRes = Abc_NtkMap( pNtk, DelayTarget, AreaMulti, DelayMulti, LogFan, Slew, Gain, nGatesMin, fRecovery, fSwitching, fSkipFanout, fUseProfile, fUseBuffs, fVerbose ); + pNtkRes = Abc_NtkMap( pNtk, /*userLib=*/NULL, DelayTarget, AreaMulti, DelayMulti, LogFan, Slew, Gain, nGatesMin, fRecovery, fSwitching, fSkipFanout, fUseProfile, fUseBuffs, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Mapping has failed.\n" ); @@ -19541,7 +20269,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 ) { @@ -19812,6 +20540,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; @@ -19929,6 +20660,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 ) @@ -20112,7 +20848,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) 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 ); @@ -20152,6 +20888,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) 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; @@ -22459,7 +23196,7 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults Ssw_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLSIVMNXcmplkodsefqvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLSIVMNXRcmplkodsefqvwh" ) ) != EOF ) { switch ( c ) { @@ -22584,6 +23321,18 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nLimitMax < 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; + } + pPars->nSkip = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nSkip < 0 ) + goto usage; + break; + case 'c': pPars->fConstrs ^= 1; break; @@ -22705,7 +23454,7 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: scorr [-PQFCLSIVMNX ] [-cmplkodsefqvwh]\n" ); + Abc_Print( -2, "usage: scorr [-PQFCLSIVMNXR ] [-cmplkodsefqvwh]\n" ); Abc_Print( -2, "\t performs sequential sweep using K-step induction\n" ); Abc_Print( -2, "\t-P num : max partition size (0 = no partitioning) [default = %d]\n", pPars->nPartSize ); Abc_Print( -2, "\t-Q num : partition overlap (0 = no overlap) [default = %d]\n", pPars->nOverSize ); @@ -22719,6 +23468,7 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-M num : min call num needed to recycle the SAT solver [default = %d]\n", pPars->nRecycleCalls2 ); Abc_Print( -2, "\t-N num : set last POs to be constraints (use with -c) [default = %d]\n", nConstrs ); Abc_Print( -2, "\t-X num : the number of iterations of little or no improvement [default = %d]\n", pPars->nLimitMax ); + Abc_Print( -2, "\t-R num : the number used to skip some constraints [default = %d]\n", pPars->nSkip ); Abc_Print( -2, "\t-c : toggle using explicit constraints [default = %s]\n", pPars->fConstrs? "yes": "no" ); Abc_Print( -2, "\t-m : toggle full merge if constraints are present [default = %s]\n", pPars->fMergeFull? "yes": "no" ); Abc_Print( -2, "\t-p : toggle aligning polarity of SAT variables [default = %s]\n", pPars->fPolarFlip? "yes": "no" ); @@ -28800,17 +29550,20 @@ int Abc_CommandInduction( Abc_Frame_t * pAbc, int argc, char ** argv ) int Abc_CommandConstr( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk; + Abc_Ntk_t * pNtkRes; int c; int nFrames; int nConfs; int nProps; int fRemove; + int fPurge; int fStruct; int fInvert; int fOldAlgo; int fVerbose; int nConstrs; extern void Abc_NtkDarConstr( Abc_Ntk_t * pNtk, int nFrames, int nConfs, int nProps, int fStruct, int fOldAlgo, int fVerbose ); + extern Abc_Ntk_t * Abc_NtkMakeOnePo( Abc_Ntk_t * pNtk, int Output, int nRange ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults @@ -28818,13 +29571,14 @@ int Abc_CommandConstr( Abc_Frame_t * pAbc, int argc, char ** argv ) nConfs = 1000; nProps = 1000; fRemove = 0; + fPurge = 0; fStruct = 0; fInvert = 0; fOldAlgo = 0; fVerbose = 0; nConstrs = -1; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "FCPNrsiavh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "FCPNrpsiavh" ) ) != EOF ) { switch ( c ) { @@ -28875,6 +29629,9 @@ int Abc_CommandConstr( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'r': fRemove ^= 1; break; + case 'p': + fPurge ^= 1; + break; case 's': fStruct ^= 1; break; @@ -28910,7 +29667,22 @@ int Abc_CommandConstr( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Constraints are not defined.\n" ); return 0; } - Abc_Print( 1, "Constraints are converted to be primary outputs.\n" ); + + if ( fPurge ) + { + Abc_Print( 1, "Constraints are removed.\n" ); + pNtkRes = Abc_NtkMakeOnePo( pNtk, 0, Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk) ); + if ( pNtkRes == NULL ) + { + Abc_Print( 1,"Transformation has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + pNtk = Abc_FrameReadNtk(pAbc); + } + else + Abc_Print( 1, "Constraints are converted to be primary outputs.\n" ); pNtk->nConstrs = 0; return 0; } @@ -28955,7 +29727,7 @@ int Abc_CommandConstr( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_NtkDarConstr( pNtk, nFrames, nConfs, nProps, fStruct, fOldAlgo, fVerbose ); return 0; usage: - Abc_Print( -2, "usage: constr [-FCPN num] [-risavh]\n" ); + Abc_Print( -2, "usage: constr [-FCPN num] [-rpisavh]\n" ); Abc_Print( -2, "\t a toolkit for constraint manipulation\n" ); Abc_Print( -2, "\t if constraints are absent, detect them functionally\n" ); Abc_Print( -2, "\t if constraints are present, profiles them using random simulation\n" ); @@ -28964,7 +29736,8 @@ int Abc_CommandConstr( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-C num : the max number of conflicts in SAT solving [default = %d]\n", nConfs ); Abc_Print( -2, "\t-P num : the max number of propagations in SAT solving [default = %d]\n", nProps ); Abc_Print( -2, "\t-N num : manually set the last POs to be constraints [default = %d]\n", nConstrs ); - Abc_Print( -2, "\t-r : manually remove the constraints [default = %s]\n", fRemove? "yes": "no" ); + Abc_Print( -2, "\t-r : manually remove the constraints, converting them to POs [default = %s]\n", fRemove? "yes": "no" ); + Abc_Print( -2, "\t-p : remove constraints instead of converting them to POs [default = %s]\n", fPurge? "yes": "no" ); Abc_Print( -2, "\t-i : toggle inverting already defined constraints [default = %s]\n", fInvert? "yes": "no" ); Abc_Print( -2, "\t-s : toggle using structural detection methods [default = %s]\n", fStruct? "yes": "no" ); Abc_Print( -2, "\t-a : toggle fast implication detection [default = %s]\n", !fOldAlgo? "yes": "no" ); @@ -29144,14 +29917,16 @@ int Abc_CommandFold( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Ntk_t * pNtk, * pNtkRes; int fCompl; int fVerbose; + int fSeqCleanup; int c; - extern Abc_Ntk_t * Abc_NtkDarFold( Abc_Ntk_t * pNtk, int fCompl, int fVerbose ); + extern Abc_Ntk_t * Abc_NtkDarFold( Abc_Ntk_t * pNtk, int fCompl, int fVerbose, int fSeqCleanup ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fCompl = 0; fVerbose = 0; + fSeqCleanup = 1; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "cvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "cvsh" ) ) != EOF ) { switch ( c ) { @@ -29161,6 +29936,9 @@ int Abc_CommandFold( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'v': fVerbose ^= 1; break; + case 's': + fSeqCleanup ^= 1; + break; case 'h': goto usage; default: @@ -29190,7 +29968,7 @@ int Abc_CommandFold( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( Abc_NtkIsComb(pNtk) ) Abc_Print( 0, "The network is combinational.\n" ); // modify the current network - pNtkRes = Abc_NtkDarFold( pNtk, fCompl, fVerbose ); + pNtkRes = Abc_NtkDarFold( pNtk, fCompl, fVerbose, fSeqCleanup ); if ( pNtkRes == NULL ) { Abc_Print( 1,"Transformation has failed.\n" ); @@ -29205,6 +29983,7 @@ int Abc_CommandFold( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t (constraints fail when any of them becomes 1 in any timeframe)\n" ); Abc_Print( -2, "\t-c : toggle complementing constraints while folding [default = %s]\n", fCompl? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-s : toggle performing sequential cleanup [default = %s]\n", fSeqCleanup? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -31664,7 +32443,7 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( 0, "Internal nodes names are not transferred.\n" ); // decouple CI/CO with the same name - if ( pAbc->pGia->vNamesIn || pAbc->pGia->vNamesOut ) + if ( !Abc_NtkIsStrash(pNtk) && (pAbc->pGia->vNamesIn || pAbc->pGia->vNamesOut) ) Abc_NtkRedirectCiCo( pNtk ); // transfer timing information @@ -32158,7 +32937,7 @@ int Abc_CommandAbc9WriteVer( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } Abc_NtkInsertHierarchyGia( pNtkSpec, pAbc->pNtkCur, fVerbose ); - Io_WriteVerilog( pNtkSpec, pFileName, 0 ); + Io_WriteVerilog( pNtkSpec, pFileName, 0, 0 ); Abc_NtkDelete( pNtkSpec ); return 0; @@ -33320,8 +34099,9 @@ int Abc_CommandAbc9Strash( Abc_Frame_t * pAbc, int argc, char ** argv ) int fAddMuxes = 0; int fStrMuxes = 0; int fRehashMap = 0; + int fInvert = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "LMbacmrsh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "LMbacmrsih" ) ) != EOF ) { switch ( c ) { @@ -33365,6 +34145,9 @@ int Abc_CommandAbc9Strash( Abc_Frame_t * pAbc, int argc, char ** argv ) case 's': fStrMuxes ^= 1; break; + case 'i': + fInvert ^= 1; + break; case 'h': goto usage; default: @@ -33376,6 +34159,13 @@ int Abc_CommandAbc9Strash( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9Strash(): There is no AIG.\n" ); return 1; } + if ( fInvert ) + { + Gia_Obj_t * pObj; int i; + Gia_ManForEachPo( pAbc->pGia, pObj, i ) + Gia_ObjFlipFaninC0( pObj ); + return 0; + } if ( fAddBuffs ) { extern Gia_Man_t * Gia_ManDupAddBufs( Gia_Man_t * p ); @@ -33457,7 +34247,7 @@ int Abc_CommandAbc9Strash( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &st [-LM num] [-bacmrsh]\n" ); + Abc_Print( -2, "usage: &st [-LM num] [-bacmrsih]\n" ); Abc_Print( -2, "\t performs structural hashing\n" ); Abc_Print( -2, "\t-b : toggle adding buffers at the inputs and outputs [default = %s]\n", fAddBuffs? "yes": "no" ); Abc_Print( -2, "\t-a : toggle additional hashing [default = %s]\n", fAddStrash? "yes": "no" ); @@ -33468,6 +34258,7 @@ int Abc_CommandAbc9Strash( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-M num : create an AIG with additional primary inputs [default = %d]\n", Multi ); Abc_Print( -2, "\t-r : toggle rehashing AIG while preserving mapping [default = %s]\n", fRehashMap? "yes": "no" ); Abc_Print( -2, "\t-s : toggle using MUX restructuring [default = %s]\n", fStrMuxes? "yes": "no" ); + Abc_Print( -2, "\t-i : toggle complementing the POs of the AIG [default = %s]\n", fInvert? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -33585,9 +34376,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 ) { @@ -33602,6 +34393,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 ) { @@ -33638,7 +34440,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 ); @@ -33664,9 +34472,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" ); @@ -33674,6 +34483,96 @@ int Abc_CommandAbc9Cof( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Cofs( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManDupCofs( Gia_Man_t * p, Vec_Int_t * vVarNums ); + Gia_Man_t * pTemp; Vec_Int_t * vVars = NULL; + int c, iVar = 0, nVars = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "VNvh" ) ) != EOF ) + { + switch ( c ) + { + case 'V': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-V\" should be followed by an integer.\n" ); + goto usage; + } + iVar = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( iVar < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Cof(): There is no AIG.\n" ); + return 1; + } + if ( iVar ) { + Abc_Print( 0, "Cofactoring one variable with ID %d.\n", iVar ); + vVars = Vec_IntAlloc( 1 ); + Vec_IntPush( vVars, iVar ); + } + else if ( nVars ) { + Abc_Print( 0, "Cofactoring the first %d inputs.\n", nVars ); + vVars = Vec_IntStartNatural( nVars ); + } + else if ( globalUtilOptind < argc ) { + vVars = Vec_IntAlloc( argc ); + for ( c = globalUtilOptind; c < argc; c++ ) + Vec_IntPush( vVars, atoi(argv[c]) ); + } + else { + Abc_Print( -1, "One of the parameters, -V or -L , should be set on the command line.\n" ); + goto usage; + } + pTemp = Gia_ManDupCofs( pAbc->pGia, vVars ); + Abc_FrameUpdateGia( pAbc, pTemp ); + Vec_IntFree( vVars ); + return 0; + +usage: + Abc_Print( -2, "usage: &cofs [-VN num] [-vh]\n" ); + Abc_Print( -2, "\t derives cofactors w.r.t the set of variables\n" ); + Abc_Print( -2, "\t-V num : the zero-based ID of one variable to cofactor [default = %d]\n", iVar ); + Abc_Print( -2, "\t-N num : cofactoring the given number of first input variables [default = %d]\n", nVars ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -37770,11 +38669,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 ) { @@ -37844,6 +38744,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; @@ -37896,6 +38807,33 @@ 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 ) + { + extern void Gia_ManTransferEquivs2( Gia_Man_t * p, Gia_Man_t * pNew ); + 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_ManTransferEquivs2( pUsed, pAbc->pGia ); + 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 ) @@ -37908,7 +38846,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 ); @@ -37916,6 +38854,7 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) 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" ); @@ -39122,6 +40061,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 ) @@ -40403,7 +41347,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 ) { @@ -40555,6 +41499,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; @@ -40642,7 +41613,7 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - + if ( pAbc->pGia == NULL ) { if ( !Abc_FrameReadFlag("silentmode") ) @@ -40789,8 +41760,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 ) @@ -40818,7 +41816,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; @@ -40935,7 +41933,7 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) 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 ); @@ -40950,6 +41948,8 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) 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" ); @@ -43775,12 +44775,15 @@ int Abc_CommandAbc9LNetMap( Abc_Frame_t * pAbc, int argc, char ** argv ) 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; @@ -43795,16 +44798,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; @@ -47975,7 +48983,38 @@ int Abc_CommandAbc9Qbf( Abc_Frame_t * pAbc, int argc, char ** argv ) 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; } @@ -52118,13 +53157,16 @@ int Abc_CommandAbc9AddFlop( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9AddFlop(): There is no AIG.\n" ); return 0; } - pTemp = Gia_ManDupAddFlop( pAbc->pGia ); - Abc_FrameUpdateGia( pAbc, pTemp ); + if ( Gia_ManRegNum(pAbc->pGia) == 0 ) + { + pTemp = Gia_ManDupAddFlop( pAbc->pGia ); + Abc_FrameUpdateGia( pAbc, pTemp ); + } return 0; usage: Abc_Print( -2, "usage: &addflop [-vh]\n" ); - Abc_Print( -2, "\t adds one flop to the design\n" ); + Abc_Print( -2, "\t if the design has no flops, adds one flop to the design\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"); return 1; @@ -52274,9 +53316,68 @@ int Abc_CommandAbc9GenHie( Abc_Frame_t * pAbc, int argc, char ** argv ) 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; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + 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; +} -extern Bnd_Man_t* pBnd; /**Function************************************************************* Synopsis [] @@ -52288,6 +53389,8 @@ extern Bnd_Man_t* pBnd; 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 ); @@ -52526,7 +53629,6 @@ int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) 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 ); @@ -52631,6 +53733,1109 @@ int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) 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 fBlif, 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 fBlif = 0; + int fVerbose = 0; + int c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CMFstcbvh" ) ) != 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 'b': + fBlif ^= 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, fBlif, fVerbose, 0 ); + return 0; + +usage: + Abc_Print( -2, "usage: &gencex [-CM num] [-F file] [-stcbvh]\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 = %s]\n", fUseSim ? "yes": "no" ); + Abc_Print( -2, "\t-t : toggles using SAT solving [default = %s]\n", fUseSat ? "yes": "no" ); + Abc_Print( -2, "\t-c : toggles outputing care literals only [default = %s]\n", fShort ? "yes": "no" ); + Abc_Print( -2, "\t-b : toggles outputing the BLIF file [default = %s]\n", fBlif ? "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_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 ) + { + extern char * Wlc_NtkMuxTreeString( int nIns ); + if ( nIns <= 16 ) + pNums = Wlc_NtkMuxTreeString( nIns ); + 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_CommandAbc9GenComp( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManDupGenComp( int nBits, int fInterleave ); + Gia_Man_t * pTemp = NULL; + int c, nBits = 0, fInter = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Kivh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nBits = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nBits < 0 ) + goto usage; + break; + case 'i': + fInter ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( nBits == 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9GenComp(): The number of inputs should be defined on the command line \"-K num\".\n" ); + return 0; + } + pTemp = Gia_ManDupGenComp( nBits, fInter ); + Abc_FrameUpdateGia( pAbc, pTemp ); + if ( fVerbose ) + Abc_Print( 1, "Generated %d-bit comparator.\n", nBits ); + return 0; + +usage: + Abc_Print( -2, "usage: &gencomp [-K ] [-ivh]\n" ); + Abc_Print( -2, "\t generates the comparator\n" ); + Abc_Print( -2, "\t-K num : the number of control inputs [default = undefined]\n" ); + Abc_Print( -2, "\t-i : toggles using interleaved variable ordering [default = %s]\n", fInter ? "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_CommandAbc9GenSorter( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManGenSorter( int LogN ); + Gia_Man_t * pTemp = NULL; + int c, LogN = 0, 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; + } + LogN = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( LogN < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( LogN == 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9GenComp(): The number of inputs should be defined on the command line \"-K num\".\n" ); + return 0; + } + pTemp = Gia_ManGenSorter( LogN ); + Abc_FrameUpdateGia( pAbc, pTemp ); + if ( fVerbose ) + Abc_Print( 1, "Generated %d-input sorter composed of %d elementary 2-bit sorters.\n", 1 << LogN, (1 << LogN) * LogN * (LogN-1) / 4 + (1 << LogN) - 1 ); + return 0; + +usage: + Abc_Print( -2, "usage: &gensorter [-K ] [-vh]\n" ); + Abc_Print( -2, "\t generates the sorter using pair-wise sorting algorithm\n" ); + Abc_Print( -2, "\t-K num : the base-2 log of the number of 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"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9GenNeuron( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManGenNeuron( char * pFileName, int nIBits, int nLutSize, int fDump, int fVerbose ); + Gia_Man_t * pTemp = NULL; + int c, nBits = 0, nLutSize = 0, fDump = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IKdvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" 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 'd': + fDump ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( nBits < 1 || nBits > 31 ) + { + Abc_Print( -1, "Abc_CommandAbc9GenNeuron(): The number of inputs (0 < K < 32) should be defined on the command line \"-K num\".\n" ); + return 0; + } + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( 1, "Input file is not given.\n" ); + return 0; + } + pTemp = Gia_ManGenNeuron( argv[globalUtilOptind], nBits, nLutSize, fDump, fVerbose ); + if ( fVerbose ) + printf( "Generated %d-argument neuron with %d-bit inputs and %d-bit output.\n", Gia_ManCiNum(pTemp)/nBits, nBits, Gia_ManCoNum(pTemp) ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &genneuron [-IK ] [-dvh] \n" ); + Abc_Print( -2, "\t generates the implementation of one neuron\n" ); + Abc_Print( -2, "\t-I num : the bit-width of each input [default = undefined]\n" ); + Abc_Print( -2, "\t-K num : the LUT size for logic structuring [default = undefined]\n" ); + Abc_Print( -2, "\t-d : toggles dumping RTL Verilog [default = %s]\n", fDump ? "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 weights one per line followed by the bias (in hex notation)\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 ); + extern void Gia_ManRecurDsd( Gia_Man_t * p, int fVerbose ); + int c, iIn = -1, fDsd = 0, fAll = 0, fRecur = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Vdarvh" ) ) != 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 'r': + fRecur ^= 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 ( fRecur ) + { + Gia_ManRecurDsd( pAbc->pGia, fVerbose ); + return 0; + } + if ( fDsd ) + { + if ( iIn == -1 ) { + printf( "Function = " ); + Gia_ManCheckDsd( pAbc->pGia, 0, fVerbose ); + 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( "Cof(%c=%d) = ", 'a' + iIn, c ); + Gia_ManCheckDsd( pTemp, 12, fVerbose ); + Gia_ManStop( pTemp ); + } + } + return 0; + } + for ( c = 0; c < 2; c++ ) { + Gia_Man_t * pTemp = Gia_ManDupCofactorVar( pAbc->pGia, iIn, c ); + printf( " Cof(%c=%d) = ", 'a' + iIn, c ); + Gia_ManCheckDsd( pTemp, 0, fVerbose ); + if ( fAll ) { + for ( int iIn2 = 0; iIn2 < Gia_ManPiNum(pAbc->pGia); iIn2++ ) if ( iIn2 != iIn ) + for ( int c2 = 0; c2 < 2; c2++ ) { + Gia_Man_t * pTemp2 = Gia_ManDupCofactorVar( pTemp, iIn2, c2 ); + printf( "Cof(%c=%d,%c=%d) = ", 'a' + iIn, c, 'a' + iIn2, c2 ); + Gia_ManCheckDsd( pTemp2, 12, fVerbose ); + 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] [-drvh]\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-r : toggles recursive cofactoring to get a full DSD [default = %s]\n", fRecur ? "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 ); + extern Vec_Mem_t * Abc_TruthDecRead( char * pFileName, int nVarNum ); + extern void Abc_TtStoreDump( char * pFileName, Vec_Mem_t * vTtMem, int nBytes ); + int c, nVars, nVars2, nCutNum = 8, nCutSize = 0, nNumFuncs = 5, nNumCones = 3, fOutputs = 0, fVerbose = 0; word * pTruth = NULL; + char * pStr = NULL, * pFuncFileName = "_npn_member_funcs_.data"; Vec_Mem_t * vTtMem = NULL; Gia_Man_t * pTemp; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CKNMFovh" ) ) != 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 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nCutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutSize < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nNumFuncs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNumFuncs < 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; + } + nNumCones = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNumCones < 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; + } + pFuncFileName = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'o': + fOutputs ^= 1; + 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 ) + { + abctime clkStart = Abc_Clock(); + int nFileSize = Gia_FileSize( pFuncFileName ); + if ( nFileSize == 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9FunTrace(): Truth table in hex notation (or file name with the functions) should be given on the command line.\n" ); + return 0; + } + if ( nCutSize == 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9FunTrace(): The cut size needs to be specified on the command line (-K ) when precomputed functions are used.\n" ); + return 0; + } + vTtMem = Abc_TruthDecRead( pFuncFileName, nCutSize ); + printf( "Finished reading %d %d-input function from file \"%s\". ", nFileSize / 8 / Abc_Truth6WordNum(nCutSize), nCutSize, pFuncFileName ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + Gia_ManMatchCuts( vTtMem, pAbc->pGia, nCutSize, nCutNum, fVerbose ); + Vec_MemHashFree( vTtMem ); + Vec_MemFree( vTtMem ); + return 0; + } + if ( strstr(argv[globalUtilOptind], ".aig") ) + { // the entry on the command line is an AIGER file + extern void Gia_ManMatchCones( Gia_Man_t * pBig, Gia_Man_t * pSmall, int nCutSize, int nCutNum, int nNumFuncs, int nNumCones, int fVerbose ); + extern void Gia_ManMatchConesOutput( Gia_Man_t * pBig, Gia_Man_t * pSmall, int nCutNum, int fVerbose ); + pTemp = Gia_AigerRead( argv[globalUtilOptind], 0, 0, 0 ); + if ( pTemp == NULL ) { + Abc_Print( -1, "Abc_CommandAbc9FunTrace(): Cannot read input AIG \"%s\".\n", argv[globalUtilOptind] ); + return 0; + } + if ( fOutputs ) { + if ( Gia_ManCiNum(pTemp) > 16 ) { + Abc_Print( -1, "Abc_CommandAbc9FunTrace(): The AIG \"%s\" has more than 16 primary inputs.\n", argv[globalUtilOptind] ); + Gia_ManStop( pTemp ); + return 0; + } + Gia_ManMatchConesOutput( pAbc->pGia, pTemp, nCutNum, fVerbose ); + } + else { + if ( nCutSize == 0 ) { + Abc_Print( -1, "Abc_CommandAbc9FunTrace(): The LUT size for profiling should be given on the command line.\n" ); + return 0; + } + Gia_ManMatchCones( pAbc->pGia, pTemp, nCutSize, nCutNum, nNumFuncs, nNumCones, fVerbose ); + } + Gia_ManStop( pTemp ); + 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 ); + if ( pFuncFileName ) { + Abc_TtStoreDump( pFuncFileName, vTtMem, 8 * Vec_MemEntrySize(vTtMem) ); + printf( "Dumped %d NPN class member functions into file \"%s\".\n", Vec_MemEntryNum(vTtMem), pFuncFileName ); + } + Vec_MemHashFree( vTtMem ); + Vec_MemFree( vTtMem ); + return 0; + +usage: + Abc_Print( -2, "usage: &funtrace [-CKNM num] [-F file] [-ovh] { or }\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-K num : the LUT size to use when is given [default = %d]\n", nCutSize ); + Abc_Print( -2, "\t-N num : the number of functions to use when or -F are used [default = %d]\n", nNumFuncs ); + Abc_Print( -2, "\t-M num : the number of logic cones to use when is given [default = %d]\n", nNumCones ); + Abc_Print( -2, "\t-F file : the file name to store the NPN member functions [default = %s]\n", pFuncFileName ); + Abc_Print( -2, "\t-o : toggles using AIG output functions instead of frequent cut functions [default = %s]\n", fOutputs ? "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 : truth table in the hexadecimal notation used for tracing\n"); + Abc_Print( -2, "\t : AIG whose K-input functions will be used for tracing\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 [] @@ -52717,7 +54922,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 6615bff0ac..eddb2c1a13 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,154 @@ 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 nLuts, int nRails, int nIters, 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 nLuts, int nRails, int nIters, 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 nLuts, int nRails, int nIters, int fVerbose ); + Gia_Man_t * pGia = Abc_NtkStrashToGia( pNtk ); + Mini_Aig_t * pM = Gia_ManToMiniAig( pGia ); + word * pLuts = Abc_LutCascade( pM, nLutSize, nLuts, nRails, nIters, fVerbose ); + //word * pLuts = Abc_LutCascadeTest( pM, nLutSize, 0 ); + 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/abcDar.c b/src/base/abci/abcDar.c index 76c7cf5473..a209143f35 100644 --- a/src/base/abci/abcDar.c +++ b/src/base/abci/abcDar.c @@ -4682,7 +4682,7 @@ Abc_Ntk_t * Abc_NtkDarUnfold( Abc_Ntk_t * pNtk, int nFrames, int nConfs, int nPr SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkDarFold( Abc_Ntk_t * pNtk, int fCompl, int fVerbose ) +Abc_Ntk_t * Abc_NtkDarFold( Abc_Ntk_t * pNtk, int fCompl, int fVerbose, int fSeqCleanup ) { Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; @@ -4690,7 +4690,7 @@ Abc_Ntk_t * Abc_NtkDarFold( Abc_Ntk_t * pNtk, int fCompl, int fVerbose ) pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; - pMan = Saig_ManDupFoldConstrsFunc( pTemp = pMan, fCompl, fVerbose ); + pMan = Saig_ManDupFoldConstrsFunc( pTemp = pMan, fCompl, fVerbose, fSeqCleanup ); Aig_ManStop( pTemp ); pNtkAig = Abc_NtkFromAigPhase( pMan ); pNtkAig->pName = Extra_UtilStrsav(pMan->pName); diff --git a/src/base/abci/abcDec.c b/src/base/abci/abcDec.c index 7803f539bc..62d58fbcaa 100644 --- a/src/base/abci/abcDec.c +++ b/src/base/abci/abcDec.c @@ -458,6 +458,31 @@ void Abc_TtStoreLoadSave( char * pFileName ) printf( "Input file \"%s\" was copied into output file \"%s\".\n", pFileInput, pFileOutput ); } +/**Function************************************************************* + + Synopsis [Read truth tables from input file and write them into output file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_TtStoreDump( char * pFileName, Vec_Mem_t * vTtMem, int nBytes ) +{ + word * pTruth; int i; + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + return; + } + Vec_MemForEachEntry( vTtMem, pTruth, i ) + fwrite( pTruth, nBytes, 1, pFile ); + fclose( pFile ); +} + /**Function************************************************************* Synopsis [Read truth tables in binary text form and write them into file as binary data.] @@ -709,6 +734,38 @@ void Abc_TruthDecTest( char * pFileName, int DecType, int nVarNum, int fVerbose // printf( "Finished decomposing truth tables from file \"%s\".\n", pFileName ); } +/**Function************************************************************* + + Synopsis [Read truth tables from file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Mem_t * Abc_TruthDecRead( char * pFileName, int nVarNum ) +{ + Abc_TtStore_t * p; int i; + if ( nVarNum < 6 ) + nVarNum = 6; + + // allocate data-structure + p = Abc_TtStoreLoad( pFileName, nVarNum ); + if ( p == NULL ) return NULL; + + // consider functions from the file + Vec_Mem_t * vTtMem = Vec_MemAllocForTTSimple( nVarNum ); + for ( i = 0; i < p->nFuncs; i++ ) + Vec_MemHashInsert( vTtMem, (word *)p->pFuncs[i] ); + + // delete data-structure + Abc_TtStoreFree( p, nVarNum ); +// printf( "Finished decomposing truth tables from file \"%s\".\n", pFileName ); + return vTtMem; +} + /**Function************************************************************* diff --git a/src/base/abci/abcDsd.c b/src/base/abci/abcDsd.c index 27d86ae894..6820f1806c 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/abcFx.c b/src/base/abci/abcFx.c index 487aee3c65..c69d6b887b 100644 --- a/src/base/abci/abcFx.c +++ b/src/base/abci/abcFx.c @@ -287,8 +287,11 @@ int Abc_NtkFxCheck( Abc_Ntk_t * pNtk ) // Abc_NtkForEachObj( pNtk, pNode, i ) // Abc_ObjPrint( stdout, pNode ); Abc_NtkForEachNode( pNtk, pNode, i ) - if ( !Vec_IntCheckUniqueSmall( &pNode->vFanins ) ) + if ( !Vec_IntCheckUniqueSmall( &pNode->vFanins ) ) { + printf( "Fanins of node %d: ", i ); + Vec_IntPrint( &pNode->vFanins ); return 0; + } return 1; } diff --git a/src/base/abci/abcGen.c b/src/base/abci/abcGen.c index 7ffa906254..4441db1667 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 8c4ac1448f..6c71c9ec2d 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 11605eb142..9b5b98881b 100644 --- a/src/base/abci/abcLutmin.c +++ b/src/base/abci/abcLutmin.c @@ -430,10 +430,10 @@ Abc_Obj_t * Abc_NtkBddCurtis( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t int b, c, u, i; assert( nBits + 2 <= nLutSize ); assert( nLutSize < Abc_ObjFaninNum(pNode) ); - // start BDDs for the decompoosed blocks + // start BDDs for the decomposed blocks for ( b = 0; b < nBits; b++ ) bBits[b] = Cudd_ReadLogicZero(ddNew), Cudd_Ref( bBits[b] ); - // add each bound set minterm to one of the blccks + // add each bound set minterm to one of the blocks Vec_PtrForEachEntry( DdNode *, vCofs, bCof, c ) { Vec_PtrForEachEntry( DdNode *, vUniq, bUniq, u ) @@ -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 b429b062e2..07b685eea9 100644 --- a/src/base/abci/abcMap.c +++ b/src/base/abci/abcMap.c @@ -59,7 +59,7 @@ static Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Sup SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, double AreaMulti, double DelayMulti, float LogFan, float Slew, float Gain, int nGatesMin, int fRecovery, int fSwitching, int fSkipFanout, int fUseProfile, int fUseBuffs, int fVerbose ) +Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, Mio_Library_t* userLib, double DelayTarget, double AreaMulti, double DelayMulti, float LogFan, float Slew, float Gain, int nGatesMin, int fRecovery, int fSwitching, int fSkipFanout, int fUseProfile, int fUseBuffs, int fVerbose ) { static int fUseMulti = 0; int fShowSwitching = 1; @@ -88,6 +88,11 @@ Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, double AreaMulti, Map_SuperLibFree( (Map_SuperLib_t *)Abc_FrameReadLibSuper() ); Abc_FrameSetLibSuper( NULL ); } + + if ( userLib != NULL ) { + pLib = userLib; + } + // quit if there is no library if ( pLib == NULL ) { @@ -276,6 +281,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() ) @@ -298,6 +304,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 @@ -328,6 +335,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 ); @@ -420,6 +428,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++ ) @@ -431,6 +440,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; } @@ -462,6 +472,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()); @@ -478,6 +489,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 5ddd25f1c9..f60de56840 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 85f8a4b4c3..cb22e8a60b 100644 --- a/src/base/abci/abcResub.c +++ b/src/base/abci/abcResub.c @@ -170,6 +170,8 @@ int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutMax, int nStepsMax, int nMinS pManRes->nNodesBeg = Abc_NtkNodeNum(pNtk); nNodes = Abc_NtkObjNumMax(pNtk); pProgress = Extra_ProgressBarStart( stdout, nNodes ); + //clear markAB at the beginning + Abc_NtkCleanMarkAB( pNtk ); Abc_NtkForEachNode( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); @@ -558,6 +560,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 +1969,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/abci/abcRunGen.c b/src/base/abci/abcRunGen.c index 9130fdad03..d82ba7fe48 100644 --- a/src/base/abci/abcRunGen.c +++ b/src/base/abci/abcRunGen.c @@ -19,7 +19,16 @@ ***********************************************************************/ #include "base/abc/abc.h" -#include "opt/cut/cut.h" +#include "base/main/main.h" +#include "base/cmd/cmd.h" +#include "misc/util/utilTruth.h" + +#ifdef WIN32 +#include +#define unlink _unlink +#else +#include +#endif ABC_NAMESPACE_IMPL_START @@ -42,8 +51,79 @@ ABC_NAMESPACE_IMPL_START SeeAlso [] ***********************************************************************/ -void Acb_NtkRunGen( char * pFileNames[2], int fVerbose ) +int Abc_NtkRunGenOne( Abc_Ntk_t * p, char * pScript ) +{ + Abc_FrameReplaceCurrentNetwork( Abc_FrameGetGlobalFrame(), p ); + if ( Abc_FrameIsBatchMode() ) + { + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + return 0; + } + } + else + { + Abc_FrameSetBatchMode( 1 ); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + return 0; + } + Abc_FrameSetBatchMode( 0 ); + } + Abc_Ntk_t * pTemp = Abc_FrameReadNtk(Abc_FrameGetGlobalFrame()); + return Abc_NtkNodeNum(pTemp); +} +void Acb_NtkRunGen( int nInputs, int nMints, int nFuncs, int Seed, int fVerbose, char * pScript ) { + abctime clkStart = Abc_Clock(); + Vec_Int_t * vNodes = Vec_IntAlloc( 1000 ); + int i, k, nNodes, nWords = Abc_TtWordNum(nInputs); + word * pFun = ABC_ALLOC( word, nWords ); + Abc_Ntk_t * pNtkNew; char * pTtStr, * pSop; + Abc_Random(1); + for ( i = 0; i < 10+Seed; i++ ) + Abc_Random(0); + printf( "Synthesizing %d random %d-variable functions with %d positive minterms using script \"%s\".\n", nFuncs, nInputs, nMints, pScript ); + for ( i = 0; i < nFuncs; i++ ) + { + if ( nMints == 0 ) + for ( k = 0; k < nWords; k++ ) + pFun[k] = Abc_RandomW(0); + else { + Abc_TtClear( pFun, nWords ); + for ( k = 0; k < nMints; k++ ) { + int iMint = 0; + do iMint = Abc_Random(0) % (1 << nInputs); + while ( Abc_TtGetBit(pFun, iMint) ); + Abc_TtSetBit( pFun, iMint ); + } + } + pTtStr = ABC_CALLOC( char, nInputs > 2 ? (1 << (nInputs-2)) + 1 : 2 ); + Extra_PrintHexadecimalString( pTtStr, (unsigned *)pFun, nInputs ); + pSop = Abc_SopFromTruthHex( pTtStr ); + pNtkNew = Abc_NtkCreateWithNode( pSop ); + nNodes = Abc_NtkRunGenOne( pNtkNew, pScript ); + if ( nNodes >= Vec_IntSize(vNodes) ) + Vec_IntSetEntry( vNodes, nNodes, 0 ); + Vec_IntAddToEntry( vNodes, nNodes, 1 ); + + if ( fVerbose ) { + printf( "Iteration %3d : ", i ); + printf( "Random function has %d positive minterms ", nMints ); + printf( "and maps into %d nodes.\n", nNodes ); + if ( fVerbose ) + printf( "Truth table : %s\n", pTtStr ); + } + ABC_FREE( pTtStr ); + ABC_FREE( pSop ); + } + Vec_IntForEachEntry( vNodes, i, k ) + if ( i ) + printf( "Nodes %3d : Functions %3d Ratio %5.2f %%\n", k, i, 100.0*i/nFuncs ); + ABC_FREE( pFun ); + Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart ); } //////////////////////////////////////////////////////////////////////// diff --git a/src/base/acb/acbFunc.c b/src/base/acb/acbFunc.c index 3c0bb5f065..539b91abf4 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 4a34f9cfd0..20d0f0c38f 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: @@ -2404,7 +2412,11 @@ void Gia_ManGnuplotShow( char * pPlotFileName ) { char Command[1000]; sprintf( Command, "%s %s ", pProgNameGnuplot, pPlotFileName ); +#if defined(__wasm) + if ( 1 ) +#else if ( system( Command ) == -1 ) +#endif { fprintf( stdout, "Cannot execute \"%s\".\n", Command ); return; diff --git a/src/base/cmd/cmdHist.c b/src/base/cmd/cmdHist.c index 0aaf6d5cf0..b0981630ca 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/cmd/cmdUtils.c b/src/base/cmd/cmdUtils.c index a5dc6972b4..e8e28078f8 100644 --- a/src/base/cmd/cmdUtils.c +++ b/src/base/cmd/cmdUtils.c @@ -53,6 +53,9 @@ int cmdCheckShellEscape( Abc_Frame_t * pAbc, int argc, char ** argv) int RetValue; if (argv[0][0] == '!') { +#if defined(__wasm) + RetValue = -1; +#else const int size = 4096; int i; char * buffer = ABC_ALLOC(char, 10000); @@ -71,7 +74,7 @@ int cmdCheckShellEscape( Abc_Frame_t * pAbc, int argc, char ** argv) // the parts, we lose information. So a command like // `!ls "file name"` will be sent to the system as // `ls file name` which is a BUG - +#endif return 1; } else diff --git a/src/base/exor/exor.h b/src/base/exor/exor.h index 5a7275579b..7a25f96b69 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 - -// the maximum number of input variables -#define MAXVARS 1000 - -// the number of cubes that are allocated additionally -#define 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 - -#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 +enum { + // the number of bits per integer + BPI = 32, + BPIMASK = 31, + LOGBPI = 5, + + // the maximum number of input variables + MAXVARS = 1000, + + // the number of cubes that are allocated additionally + ADDITIONAL_CUBES = 33, + + // 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 + + DIFFERENT = 0x55555555, +}; + +extern unsigned char BitCount[]; +static inline int BIT_COUNT(int w) { return BitCount[(w)&0xffff] + BitCount[(w)>>16]; } -#define VarWord(element) ((element)>>LOGBPI) -#define VarBit(element) ((element)&BPIMASK) +static inline int VarWord(int element) { return element>>LOGBPI; } +static inline int VarBit(int element) { return element&BPIMASK; } -#define TICKS_TO_SECONDS(time) ((float)(time)/(float)(CLOCKS_PER_SEC)) +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 41560e6504..e1d8e556eb 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 55a02dee29..3327a9dfd8 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -44,6 +44,7 @@ static int IoCommandReadBblif ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadBlif ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadBlifMv ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadBench ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadCex ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadDsd ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadEdif ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadEqn ( Abc_Frame_t * pAbc, int argc, char **argv ); @@ -58,6 +59,7 @@ static int IoCommandReadStatus ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadGig ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadJson ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadSF ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadRom ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWrite ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteHie ( Abc_Frame_t * pAbc, int argc, char **argv ); @@ -116,6 +118,7 @@ void Io_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "I/O", "read_blif", IoCommandReadBlif, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_blif_mv", IoCommandReadBlifMv, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_bench", IoCommandReadBench, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_cex", IoCommandReadCex, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_dsd", IoCommandReadDsd, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_formula", IoCommandReadDsd, 1 ); // Cmd_CommandAdd( pAbc, "I/O", "read_edif", IoCommandReadEdif, 1 ); @@ -131,6 +134,7 @@ void Io_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "I/O", "&read_gig", IoCommandReadGig, 0 ); Cmd_CommandAdd( pAbc, "I/O", "read_json", IoCommandReadJson, 0 ); Cmd_CommandAdd( pAbc, "I/O", "read_sf", IoCommandReadSF, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "read_rom", IoCommandReadRom, 1 ); Cmd_CommandAdd( pAbc, "I/O", "write", IoCommandWrite, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_hie", IoCommandWriteHie, 0 ); @@ -686,6 +690,331 @@ int IoCommandReadBench( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkReadCexFile( char * pFileName, Abc_Ntk_t * pNtk, Abc_Cex_t ** ppCex, Abc_Cex_t ** ppCexCare, int * pnFrames, int * fOldFormat, int xMode ) +{ + FILE * pFile; + Abc_Cex_t * pCex; + Abc_Cex_t * pCexCare; + Vec_Int_t * vNums; + int c, nRegs = -1, nFrames = -1; + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + printf( "Cannot open log file for reading \"%s\".\n" , pFileName ); + return -1; + } + + vNums = Vec_IntAlloc( 100 ); + int usedX = 0; + *fOldFormat = 0; + + int MaxLine = 1000000; + char *Buffer; + int BufferLen = 0; + int state = 0; + int iPo = 0; + nFrames = -1; + int status = 0; + int i; + int nRegsNtk = 0; + Abc_Obj_t * pObj; + Abc_NtkForEachLatch( pNtk, pObj, i ) nRegsNtk++; + + Buffer = ABC_ALLOC( char, MaxLine ); + while ( fgets( Buffer, MaxLine, pFile ) != NULL ) + { + if ( Buffer[0] == '#' || Buffer[0] == 'c' || Buffer[0] == 'f' || Buffer[0] == 'u' ) + continue; + BufferLen = strlen(Buffer) - 1; + Buffer[BufferLen] = '\0'; + if (state==0 && BufferLen>1) { + // old format detected + *fOldFormat = 1; + state = 2; + iPo = 0; + status = 1; + } + if (state==1 && Buffer[0]!='b' && Buffer[0]!='j') { + // old format detected, first line was actually register + *fOldFormat = 1; + state = 3; + Vec_IntPush( vNums, status ); + status = 1; + } + if (Buffer[0] == '.' ) + break; + switch(state) { + case 0 : + { + char c = Buffer[0]; + if ( c == '0' || c == '1' || c == '2' ) { + status = c - '0' ; + state = 1; + } else if ( c == 'x' ) { + // old format with one x state latch + usedX = 1; + // set to 2 so we can Abc_LatchSetInitNone + // acts like 0 when setting bits + Vec_IntPush( vNums, 2 ); + nRegs = Vec_IntSize(vNums); + state = 3; + } else { + printf( "ERROR: Bad aiger status line.\n" ); + return -1; + } + } + break; + case 1 : + iPo = atoi(Buffer+1); + state = 2; + break; + case 2 : + for (i=0; i nRegsNtk ) + { + printf( "WARNING: Register number is larger than in Ntk. Truncating.\n" ); + Vec_IntShrink( vNums, nRegsNtk ); + nRegs = nRegsNtk; + } + state = 3; + break; + default: + for (i=0; i= Abc_NtkPoNum(pNtk) ) + { + printf( "WARNING: PO that failed verification not coresponding to Ntk, using first PO instead.\n" ); + iPo = 0; + } + Abc_NtkForEachLatch( pNtk, pObj, i ) { + if ( Vec_IntEntry(vNums, i) == 1 ) + Abc_LatchSetInit1(pObj); + else if ( Vec_IntEntry(vNums, i) == 2 && xMode ) + Abc_LatchSetInitNone(pObj); + else + Abc_LatchSetInit0(pObj); + } + + pCex = Abc_CexAlloc( nRegs, nPi, iFrameCex + 1 ); + pCexCare = Abc_CexAlloc( nRegs, nPi, iFrameCex + 1); + // the zero-based number of PO, for which verification failed + // fails in Bmc_CexVerify if not less than actual number of PO + pCex->iPo = iPo; + pCexCare->iPo = iPo; + // the zero-based number of the time-frame, for which verificaiton failed + pCex->iFrame = iFrameCex; + pCexCare->iFrame = iFrameCex; + assert( Vec_IntSize(vNums) == pCex->nBits ); + for ( c = 0; c < pCex->nBits; c++ ) { + if ( Vec_IntEntry(vNums, c) == 1) + { + Abc_InfoSetBit( pCex->pData, c ); + Abc_InfoSetBit( pCexCare->pData, c ); + } + else if ( Vec_IntEntry(vNums, c) == 2 && xMode ) + { + // nothing to set + } + else + Abc_InfoSetBit( pCexCare->pData, c ); + } + + Vec_IntFree( vNums ); + Abc_CexFreeP( ppCex ); + if ( ppCex ) + *ppCex = pCex; + else + Abc_CexFree( pCex ); + Abc_CexFreeP( ppCexCare ); + if ( ppCexCare ) + *ppCexCare = pCexCare; + else + Abc_CexFree( pCexCare ); + + if ( pnFrames ) + *pnFrames = nFrames; + return status; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +int IoCommandReadCex( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + Abc_Cex_t * pCex = NULL; + Abc_Cex_t * pCexCare = NULL; + char * pFileName; + FILE * pFile; + int fCheck = 1; + int fXMode = 0; + int c; + int fOldFormat = 0; + int verified; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "cxh" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'x': + fXMode ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + + // get the input file name + pFileName = argv[globalUtilOptind]; + if ( (pFile = fopen( pFileName, "r" )) == NULL ) + { + fprintf( pAbc->Err, "Cannot open input file \"%s\". \n", pFileName ); + return 1; + } + fclose( pFile ); + + pNtk = pAbc->pNtkCur; + if ( pNtk == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + Abc_FrameClearVerifStatus( pAbc ); + pAbc->Status = Abc_NtkReadCexFile( pFileName, pNtk, &pCex, &pCexCare, &pAbc->nFrames, &fOldFormat, fXMode); + if ( fOldFormat && !fCheck ) + printf( "WARNING: Old witness format detected and checking is disabled. Reading might have failed.\n" ); + + if ( fCheck && pAbc->Status==1) { + extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); + Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 ); + + verified = Bmc_CexCareVerify( pAig, pCex, pCexCare, false ); + if (!verified) + { + printf( "Checking CEX for any PO.\n" ); + int verified = Bmc_CexCareVerifyAnyPo( pAig, pCex, pCexCare, false ); + Aig_ManStop( pAig ); + if (verified < 0) + { + Abc_CexFreeP(&pCex); + Abc_CexFreeP(&pCexCare); + return 1; + } + pAbc->pCex->iPo = verified; + } + + Abc_CexFreeP(&pCexCare); + Abc_FrameReplaceCex( pAbc, &pCex ); + } + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_cex [-ch] \n" ); + fprintf( pAbc->Err, "\t reads the witness cex\n" ); + fprintf( pAbc->Err, "\t-c : toggle check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-x : read x bits for verification [default = %s]\n", fXMode? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} /**Function************************************************************* Synopsis [] @@ -1060,7 +1389,15 @@ int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv ) 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; } @@ -1592,6 +1929,73 @@ int IoCommandReadSF( Abc_Frame_t * pAbc, int argc, char ** argv ) } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadRom( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Io_TransformROM2PLA( char * pNameIn, char * pNameOut ); + + Abc_Ntk_t * pNtk; + FILE * pFile; + char * pFileName, * pFileTemp = "_temp_rom_.pla"; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + pFileName = argv[globalUtilOptind]; + if ( (pFile = fopen( pFileName, "r" )) == NULL ) + { + fprintf( pAbc->Err, "Cannot open input file \"%s\". \n", pFileName ); + return 1; + } + fclose( pFile ); + Io_TransformROM2PLA( pFileName, pFileTemp ); + pNtk = Io_Read( pFileTemp, IO_FILE_PLA, 1, 0 ); + //unlink( pFileTemp ); + if ( pNtk == NULL ) + return 1; + ABC_FREE( pNtk->pName ); + pNtk->pName = Extra_FileNameGeneric( pFileName ); + ABC_FREE( pNtk->pSpec ); + pNtk->pSpec = Abc_UtilStrsav( pFileName ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + Abc_FrameClearVerifStatus( pAbc ); + + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_rom [-h] \n" ); + fprintf( pAbc->Err, "\t reads ROM file\n" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -2541,10 +2945,15 @@ void Abc_NtkDumpOneCexSpecial( FILE * pFile, Abc_Ntk_t * pNtk, Abc_Cex_t * pCex } +extern Abc_Cex_t * Bmc_CexInnerStates( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t ** ppCexImpl, int fVerbose ); +extern Abc_Cex_t * Bmc_CexEssentialBits( Gia_Man_t * p, Abc_Cex_t * pCexState, Abc_Cex_t * pCexCare, int fVerbose ); +extern Abc_Cex_t * Bmc_CexCareBits( Gia_Man_t * p, Abc_Cex_t * pCexState, Abc_Cex_t * pCexImpl, Abc_Cex_t * pCexEss, int fFindAll, int fVerbose ); + void Abc_NtkDumpOneCex( FILE * pFile, Abc_Ntk_t * pNtk, Abc_Cex_t * pCex, - int fPrintFull, int fNames, int fUseFfNames, int fMinimize, int fUseOldMin, - int fCheckCex, int fUseSatBased, int fHighEffort, int fAiger, int fVerbose ) + int fPrintFull, int fNames, int fUseFfNames, int fMinimize, int fUseOldMin, int fCexInfo, + int fCheckCex, int fUseSatBased, int fHighEffort, int fAiger, int fVerbose, int fExtended ) { + Abc_Cex_t * pCare = NULL; Abc_Obj_t * pObj; int i, f; if ( fPrintFull ) @@ -2560,15 +2969,17 @@ void Abc_NtkDumpOneCex( FILE * pFile, Abc_Ntk_t * pNtk, Abc_Cex_t * pCex, fprintf( pFile, "%s@%d=%c ", Abc_ObjName(pObj), f, '0'+Abc_InfoHasBit(pCexFull->pData, Abc_NtkCiNum(pNtk)*f + i) ); Abc_CexFreeP( &pCexFull ); } - else if ( fNames ) + else { - Abc_Cex_t * pCare = NULL; + if ( fNames ) + { + fprintf( pFile, "# FALSIFYING OUTPUTS:"); + fprintf( pFile, " %s", Abc_ObjName(Abc_NtkCo(pNtk, pCex->iPo)) ); + } if ( fMinimize ) { extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 ); - fprintf( pFile, "# FALSIFYING OUTPUTS:"); - fprintf( pFile, " %s", Abc_ObjName(Abc_NtkCo(pNtk, pCex->iPo)) ); if ( fUseOldMin ) { pCare = Saig_ManCbaFindCexCareBits( pAig, pCex, 0, fVerbose ); @@ -2576,21 +2987,47 @@ void Abc_NtkDumpOneCex( FILE * pFile, Abc_Ntk_t * pNtk, Abc_Cex_t * pCex, Bmc_CexCareVerify( pAig, pCex, pCare, fVerbose ); } else if ( fUseSatBased ) - pCare = Bmc_CexCareSatBasedMinimize( pAig, Saig_ManPiNum(pAig), pCex, fHighEffort, fCheckCex, fVerbose ); + { + if ( Abc_NtkPoNum( pNtk ) == 1 ) + pCare = Bmc_CexCareSatBasedMinimize( pAig, Saig_ManPiNum(pAig), pCex, fHighEffort, fCheckCex, fVerbose ); + else + printf( "SAT-based CEX minimization requires having a single PO.\n" ); + } + else if ( fCexInfo ) + { + Gia_Man_t * p = Gia_ManFromAigSimple( pAig ); + Abc_Cex_t * pCexImpl = NULL; + Abc_Cex_t * pCexStates = Bmc_CexInnerStates( p, pCex, &pCexImpl, fVerbose ); + Abc_Cex_t * pCexCare = Bmc_CexCareBits( p, pCexStates, pCexImpl, NULL, 1, fVerbose ); + Abc_Cex_t * pCexEss; + + if ( fCheckCex && !Bmc_CexVerify( p, pCex, pCexCare ) ) + printf( "Counter-example care-set verification has failed.\n" ); + + pCexEss = Bmc_CexEssentialBits( p, pCexStates, pCexCare, fVerbose ); + + // pCare is pCexMin from Bmc_CexTest + pCare = Bmc_CexCareBits( p, pCexStates, pCexImpl, pCexEss, 0, fVerbose ); + + if ( fCheckCex && !Bmc_CexVerify( p, pCex, pCare ) ) + printf( "Counter-example min-set verification has failed.\n" ); + Abc_CexFreeP( &pCexStates ); + Abc_CexFreeP( &pCexImpl ); + Abc_CexFreeP( &pCexCare ); + Abc_CexFreeP( &pCexEss ); + } else pCare = Bmc_CexCareMinimize( pAig, Saig_ManPiNum(pAig), pCex, 4, fCheckCex, fVerbose ); Aig_ManStop( pAig ); - if(pCare == NULL) + if(pCare == NULL) printf( "Counter-example minimization has failed.\n" ); } - else + if (fNames) { - fprintf( pFile, "# FALSIFYING OUTPUTS:"); - fprintf( pFile, " %s", Abc_ObjName(Abc_NtkCo(pNtk, pCex->iPo)) ); + fprintf( pFile, "\n"); + fprintf( pFile, "# COUNTEREXAMPLE LENGTH: %u\n", pCex->iFrame+1); } - fprintf( pFile, "\n"); - fprintf( pFile, "# COUNTEREXAMPLE LENGTH: %u\n", pCex->iFrame+1); - if ( fUseFfNames && Abc_NtkCheckSpecialPi(pNtk) ) + if ( fNames && fUseFfNames && Abc_NtkCheckSpecialPi(pNtk) ) { int * pValues; int nXValues = 0, iFlop = 0, iPivotPi = -1; @@ -2630,29 +3067,36 @@ void Abc_NtkDumpOneCex( FILE * pFile, Abc_Ntk_t * pNtk, Abc_Cex_t * pCex, } else { + if (fExtended && fAiger && !fNames) { + fprintf( pFile, "1\n"); + fprintf( pFile, "b%d\n", pCex->iPo); + } // output flop values (unaffected by the minimization) Abc_NtkForEachLatch( pNtk, pObj, i ) - fprintf( pFile, "%s@0=%c\n", Abc_ObjName(Abc_ObjFanout0(pObj)), '0'+!Abc_LatchIsInit0(pObj) ); + if ( fNames ) + fprintf( pFile, "%s@0=%c\n", Abc_ObjName(Abc_ObjFanout0(pObj)), '0'+!Abc_LatchIsInit0(pObj) ); + else + fprintf( pFile, "%c", '0'+!Abc_LatchIsInit0(pObj) ); + if ( !fNames && fAiger) + fprintf( pFile, "\n"); // output PI values (while skipping the minimized ones) - for ( f = 0; f <= pCex->iFrame; f++ ) + for ( f = 0; f <= pCex->iFrame; f++ ) { Abc_NtkForEachPi( pNtk, pObj, i ) if ( !pCare || Abc_InfoHasBit(pCare->pData, pCare->nRegs+pCare->nPis*f + i) ) - fprintf( pFile, "%s@%d=%c\n", Abc_ObjName(pObj), f, '0'+Abc_InfoHasBit(pCex->pData, pCex->nRegs+pCex->nPis*f + i) ); + if ( fNames ) + fprintf( pFile, "%s@%d=%c\n", Abc_ObjName(pObj), f, '0'+Abc_InfoHasBit(pCex->pData, pCex->nRegs+pCex->nPis*f + i) ); + else + fprintf( pFile, "%c", '0'+Abc_InfoHasBit(pCex->pData, pCex->nRegs+pCex->nPis*f + i) ); + else if ( !fNames ) + fprintf( pFile, "x"); + if ( !fNames && fAiger) + fprintf( pFile, "\n"); + } + if (fExtended && fAiger && !fNames) + fprintf( pFile, ".\n"); } Abc_CexFreeP( &pCare ); } - else - { - Abc_NtkForEachLatch( pNtk, pObj, i ) - fprintf( pFile, "%c", '0'+!Abc_LatchIsInit0(pObj) ); - - for ( i = pCex->nRegs; i < pCex->nBits; i++ ) - { - if ( fAiger && (i-pCex->nRegs)%pCex->nPis == 0) - fprintf( pFile, "\n"); - fprintf( pFile, "%c", '0'+Abc_InfoHasBit(pCex->pData, i) ); - } - } } /**Function************************************************************* @@ -2681,9 +3125,11 @@ int IoCommandWriteCex( Abc_Frame_t * pAbc, int argc, char **argv ) int fPrintFull = 0; int fUseFfNames = 0; int fVerbose = 0; + int fCexInfo = 0; + int fExtended = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "snmueocafzvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "snmueocafzvhxt" ) ) != EOF ) { switch ( c ) { @@ -2720,6 +3166,12 @@ int IoCommandWriteCex( Abc_Frame_t * pAbc, int argc, char **argv ) case 'v': fVerbose ^= 1; break; + case 'x': + fCexInfo ^= 1; + break; + case 't': + fExtended ^= 1; + break; case 'h': goto usage; default: @@ -2768,8 +3220,8 @@ int IoCommandWriteCex( Abc_Frame_t * pAbc, int argc, char **argv ) if ( pAbc->pCex ) { Abc_NtkDumpOneCex( pFile, pNtk, pCex, - fPrintFull, fNames, fUseFfNames, fMinimize, fUseOldMin, - fCheckCex, fUseSatBased, fHighEffort, fAiger, fVerbose ); + fPrintFull, fNames, fUseFfNames, fMinimize, fUseOldMin, fCexInfo, + fCheckCex, fUseSatBased, fHighEffort, fAiger, fVerbose, fExtended ); } else if ( pAbc->vCexVec ) { @@ -2777,10 +3229,10 @@ int IoCommandWriteCex( Abc_Frame_t * pAbc, int argc, char **argv ) { if ( pCex == NULL ) continue; - fprintf( pFile, "#\n#\n# CEX for output %d\n#\n", i ); + fprintf( pFile, "#\n#\n# CEX for output %d\n#\n", i ); Abc_NtkDumpOneCex( pFile, pNtk, pCex, - fPrintFull, fNames, fUseFfNames, fMinimize, fUseOldMin, - fCheckCex, fUseSatBased, fHighEffort, fAiger, fVerbose ); + fPrintFull, fNames, fUseFfNames, fMinimize, fUseOldMin, fCexInfo, + fCheckCex, fUseSatBased, fHighEffort, fAiger, fVerbose, fExtended ); } } fprintf( pFile, "# DONE\n" ); @@ -2824,8 +3276,10 @@ int IoCommandWriteCex( Abc_Frame_t * pAbc, int argc, char **argv ) fprintf( pAbc->Err, "\t-u : use fast SAT-based CEX minimization [default = %s]\n", fUseSatBased? "yes": "no" ); fprintf( pAbc->Err, "\t-e : use high-effort SAT-based CEX minimization [default = %s]\n", fHighEffort? "yes": "no" ); fprintf( pAbc->Err, "\t-o : use old CEX minimization algorithm [default = %s]\n", fUseOldMin? "yes": "no" ); + fprintf( pAbc->Err, "\t-x : minimize using algorithm from cexinfo command [default = %s]\n", fCexInfo? "yes": "no" ); fprintf( pAbc->Err, "\t-c : check generated CEX using ternary simulation [default = %s]\n", fCheckCex? "yes": "no" ); fprintf( pAbc->Err, "\t-a : print cex in AIGER 1.9 format [default = %s]\n", fAiger? "yes": "no" ); + fprintf( pAbc->Err, "\t-t : extended header info when cex in AIGER 1.9 format [default = %s]\n", fAiger? "yes": "no" ); fprintf( pAbc->Err, "\t-f : enable printing flop values in each timeframe [default = %s]\n", fPrintFull? "yes": "no" ); fprintf( pAbc->Err, "\t-z : toggle using saved flop names [default = %s]\n", fUseFfNames? "yes": "no" ); fprintf( pAbc->Err, "\t-v : enable verbose output [default = %s]\n", fVerbose? "yes": "no" ); @@ -3145,13 +3599,13 @@ int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv ) ***********************************************************************/ int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ) { - extern void Io_WriteVerilogLut( Abc_Ntk_t * pNtk, char * pFileName, int nLutSize, int fFixed, int fNoModules ); + extern void Io_WriteVerilogLut( Abc_Ntk_t * pNtk, char * pFileName, int nLutSize, int fFixed, int fNoModules, int fNewInterface ); char * pFileName; - int c, fFixed = 0, fOnlyAnds = 0, fNoModules = 0; + int c, fFixed = 0, fOnlyAnds = 0, fNoModules = 0, fNewInterface = 0; int nLutSize = -1; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Kfamh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Kfamnh" ) ) != EOF ) { switch ( c ) { @@ -3175,6 +3629,9 @@ int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ) case 'm': fNoModules ^= 1; break; + case 'n': + fNewInterface ^= 1; + break; case 'h': goto usage; default: @@ -3193,27 +3650,26 @@ int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ) // get the output file name pFileName = argv[globalUtilOptind]; // call the corresponding file writer - if ( fOnlyAnds ) + if ( nLutSize >= 2 && nLutSize <= 6 ) + Io_WriteVerilogLut( pAbc->pNtkCur, pFileName, nLutSize, fFixed, fNoModules, fNewInterface ); + else { Abc_Ntk_t * pNtkTemp = Abc_NtkToNetlist( pAbc->pNtkCur ); if ( !Abc_NtkHasAig(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) ) Abc_NtkToAig( pNtkTemp ); - Io_WriteVerilog( pNtkTemp, pFileName, 1 ); + Io_WriteVerilog( pNtkTemp, pFileName, fOnlyAnds, fNewInterface ); Abc_NtkDelete( pNtkTemp ); } - else if ( nLutSize >= 2 && nLutSize <= 6 ) - Io_WriteVerilogLut( pAbc->pNtkCur, pFileName, nLutSize, fFixed, fNoModules ); - else - Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_VERILOG ); return 0; usage: - fprintf( pAbc->Err, "usage: write_verilog [-K num] [-famh] \n" ); + fprintf( pAbc->Err, "usage: write_verilog [-K num] [-famnh] \n" ); fprintf( pAbc->Err, "\t writes the current network in Verilog format\n" ); fprintf( pAbc->Err, "\t-K num : write the network using instances of K-LUTs (2 <= K <= 6) [default = not used]\n" ); fprintf( pAbc->Err, "\t-f : toggle using fixed format [default = %s]\n", fFixed? "yes":"no" ); fprintf( pAbc->Err, "\t-a : toggle writing expressions with only ANDs (without XORs and MUXes) [default = %s]\n", fOnlyAnds? "yes":"no" ); fprintf( pAbc->Err, "\t-m : toggle writing additional modules [default = %s]\n", !fNoModules? "yes":"no" ); + fprintf( pAbc->Err, "\t-n : toggle writing generic PO names and assign-statements [default = %s]\n", fNewInterface? "yes":"no" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; diff --git a/src/base/io/ioAbc.h b/src/base/io/ioAbc.h index 9758f19631..cf30196f2c 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 ); @@ -137,7 +137,7 @@ extern int Io_WriteMoPla( Abc_Ntk_t * pNtk, char * FileName ); /*=== abcWriteSmv.c ===========================================================*/ extern int Io_WriteSmv( Abc_Ntk_t * pNtk, char * FileName ); /*=== abcWriteVerilog.c =======================================================*/ -extern void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * FileName, int fOnlyAnds ); +extern void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * FileName, int fOnlyAnds, int fNewInterface ); /*=== abcUtil.c ===============================================================*/ extern Io_FileType_t Io_ReadFileType( char * pFileName ); extern Io_FileType_t Io_ReadLibType( char * pFileName ); diff --git a/src/base/io/ioReadAiger.c b/src/base/io/ioReadAiger.c index 9cf41413d9..200247bbda 100644 --- a/src/base/io/ioReadAiger.c +++ b/src/base/io/ioReadAiger.c @@ -433,14 +433,14 @@ Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck ) else { assert( Init == Abc_Var2Lit(1+Abc_NtkPiNum(pNtkNew)+i, 0) ); - // unitialized value of the latch is the latch literal according to http://fmv.jku.at/hwmcc11/beyond1.pdf + // uninitialized value of the latch is the latch literal according to http://fmv.jku.at/hwmcc11/beyond1.pdf Abc_LatchSetInitDc( Abc_NtkBox(pNtkNew, i) ); } while ( *pCur != ' ' && *pCur != '\n' ) pCur++; } if ( *pCur != '\n' ) { - fprintf( stdout, "The initial value of latch number %d is not recongnized.\n", i ); + fprintf( stdout, "The initial value of latch number %d is not recognized.\n", i ); return NULL; } pCur++; diff --git a/src/base/io/ioReadBlifMv.c b/src/base/io/ioReadBlifMv.c index c8c14581ad..77ae184151 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 0000000000..bd5175fbe4 --- /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/ioUtil.c b/src/base/io/ioUtil.c index eee2dda538..52cadc274f 100644 --- a/src/base/io/ioUtil.c +++ b/src/base/io/ioUtil.c @@ -20,6 +20,7 @@ #include "ioAbc.h" #include "base/main/main.h" +#include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START @@ -464,7 +465,7 @@ void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType ) { if ( !Abc_NtkHasAig(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) ) Abc_NtkToAig( pNtkTemp ); - Io_WriteVerilog( pNtkTemp, pFileName, 0 ); + Io_WriteVerilog( pNtkTemp, pFileName, 0, 0 ); } else fprintf( stderr, "Unknown file format.\n" ); @@ -592,7 +593,7 @@ void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName ) if ( !Abc_NtkHasAig(pNtkResult) && !Abc_NtkHasMapping(pNtkResult) ) Abc_NtkToAig( pNtkResult ); } - Io_WriteVerilog( pNtkResult, pFileName, 0 ); + Io_WriteVerilog( pNtkResult, pFileName, 0, 0 ); } else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV ) { @@ -890,7 +891,7 @@ void Io_TransformSF2PLA( char * pNameIn, char * pNameOut ) if ( pFileOut == NULL ) { if ( pFileIn ) fclose( pFileIn ); - printf( "Cannot open file \"%s\" for reading.\n", pNameOut ); + printf( "Cannot open file \"%s\" for writing.\n", pNameOut ); return; } pBuffer = ABC_ALLOC( char, Size ); @@ -920,6 +921,58 @@ void Io_TransformSF2PLA( char * pNameIn, char * pNameOut ) ABC_FREE( pBuffer ); } +/**Function************************************************************* + + Synopsis [Tranform SF into PLA.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_TransformROM2PLA( char * pNameIn, char * pNameOut ) +{ + FILE * pFileOut = fopen( pNameOut, "wb" ); + if ( pFileOut == NULL ) { + printf( "Cannot open file \"%s\" for writing.\n", pNameOut ); + return; + } + int nWords = -1; + Vec_Wrd_t * vData = Vec_WrdReadHex( pNameIn, &nWords, 0 ); + if ( vData == NULL ) { + fclose( pFileOut ); + return; + } + //Vec_WrdDumpHex( "temp.txt", vData, 1, 1 ); + int v, i, nLines = Vec_WrdSize(vData) / nWords; + int nIns = Abc_Base2Log(nLines), nOuts; + assert( nLines * nWords == Vec_WrdSize(vData) ); + word * pTemp = ABC_CALLOC( word, nWords ); + for ( i = 0; i < nLines; i++ ) + Abc_TtOr( pTemp, pTemp, Vec_WrdEntryP(vData, nWords*i), nWords ); + for ( nOuts = nWords*64; nOuts > 0; nOuts-- ) + if ( Abc_TtGetBit(pTemp, nOuts-1) ) + break; + ABC_FREE( pTemp ); + assert( nOuts > 0 ); + fprintf( pFileOut, ".i %d\n", nIns ); + fprintf( pFileOut, ".o %d\n", nOuts ); + fprintf( pFileOut, ".p %d\n", nLines ); + fprintf( pFileOut, ".type fr\n" ); + for ( i = 0; i < nLines; i++ ) { + word * pData = Vec_WrdEntryP(vData, nWords*i); + for ( v = 0; v < nIns; v++ ) + fprintf( pFileOut, "%d", (i >> v) & 1 ); + fprintf( pFileOut, " " ); + for ( v = 0; v < nOuts; v++ ) + fprintf( pFileOut, "%d", Abc_TtGetBit(pData, v) ); + fprintf( pFileOut, "\n" ); + } + fprintf( pFileOut, ".e\n\n" ); + fclose( pFileOut ); +} /**Function************************************************************* Synopsis [Reads CNF from file.] diff --git a/src/base/io/ioWriteAiger.c b/src/base/io/ioWriteAiger.c index 0a68c7eec9..cad335d4f4 100644 --- a/src/base/io/ioWriteAiger.c +++ b/src/base/io/ioWriteAiger.c @@ -680,7 +680,7 @@ void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols, int f b.f = fopen( pFileName, "wb" ); if ( b.f == NULL ) { - fprintf( stdout, "Ioa_WriteBlif(): Cannot open the output file \"%s\".\n", pFileName ); + fprintf( stdout, "Io_WriteAiger(): Cannot open the output file \"%s\".\n", pFileName ); ABC_FREE(b.buf); return; } @@ -688,7 +688,7 @@ void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols, int f b.b = BZ2_bzWriteOpen( &bzError, b.f, 9, 0, 0 ); if ( bzError != BZ_OK ) { BZ2_bzWriteClose( &bzError, b.b, 0, NULL, NULL ); - fprintf( stdout, "Ioa_WriteBlif(): Cannot start compressed stream.\n" ); + fprintf( stdout, "Io_WriteAiger(): Cannot start compressed stream.\n" ); fclose( b.f ); ABC_FREE(b.buf); return; diff --git a/src/base/io/ioWriteDot.c b/src/base/io/ioWriteDot.c index 0ab3c4d2fd..dc1f976982 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/io/ioWriteVerilog.c b/src/base/io/ioWriteVerilog.c index 5e4438a5dc..acddb75511 100644 --- a/src/base/io/ioWriteVerilog.c +++ b/src/base/io/ioWriteVerilog.c @@ -29,9 +29,10 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk, int fOnlyAnds ); +static void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk, int fOnlyAnds, int fNewInterface ); static void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); -static void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start, int fNewInterface ); +static void Io_WriteVerilogAssigns( FILE * pFile, Abc_Ntk_t * pNtk ); static void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); static void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); static void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk ); @@ -54,11 +55,12 @@ static char * Io_WriteVerilogGetName( char * pName ); SeeAlso [] ***********************************************************************/ -void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * pFileName, int fOnlyAnds ) +void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * pFileName, int fOnlyAnds, int fNewInterface ) { Abc_Ntk_t * pNetlist; FILE * pFile; int i; + // can only write nodes represented using local AIGs if ( !Abc_NtkIsAigNetlist(pNtk) && !Abc_NtkIsMappedNetlist(pNtk) ) { @@ -81,7 +83,7 @@ void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * pFileName, int fOnlyAnds ) if ( pNtk->pDesign ) { // write the network first - Io_WriteVerilogInt( pFile, pNtk, fOnlyAnds ); + Io_WriteVerilogInt( pFile, pNtk, fOnlyAnds, fNewInterface ); // write other things Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pNetlist, i ) { @@ -89,12 +91,12 @@ void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * pFileName, int fOnlyAnds ) if ( pNetlist == pNtk ) continue; fprintf( pFile, "\n" ); - Io_WriteVerilogInt( pFile, pNetlist, fOnlyAnds ); + Io_WriteVerilogInt( pFile, pNetlist, fOnlyAnds, fNewInterface ); } } else { - Io_WriteVerilogInt( pFile, pNtk, fOnlyAnds ); + Io_WriteVerilogInt( pFile, pNtk, fOnlyAnds, fNewInterface ); } fprintf( pFile, "\n" ); @@ -112,7 +114,7 @@ void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * pFileName, int fOnlyAnds ) SeeAlso [] ***********************************************************************/ -void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk, int fOnlyAnds ) +void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk, int fOnlyAnds, int fNewInterface ) { // write inputs and outputs // fprintf( pFile, "module %s ( gclk,\n ", Abc_NtkName(pNtk) ); @@ -128,7 +130,7 @@ void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk, int fOnlyAnds ) fprintf( pFile, ",\n " ); } if ( Abc_NtkPoNum(pNtk) > 0 ) - Io_WriteVerilogPos( pFile, pNtk, 3 ); + Io_WriteVerilogPos( pFile, pNtk, 3, fNewInterface ); fprintf( pFile, " );\n" ); // add the clock signal if it does not exist if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 ) @@ -144,7 +146,7 @@ void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk, int fOnlyAnds ) if ( Abc_NtkPoNum(pNtk) > 0 ) { fprintf( pFile, " output" ); - Io_WriteVerilogPos( pFile, pNtk, 5 ); + Io_WriteVerilogPos( pFile, pNtk, 5, fNewInterface ); fprintf( pFile, ";\n" ); } // if this is not a blackbox, write internal signals @@ -168,6 +170,8 @@ void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk, int fOnlyAnds ) if ( Abc_NtkLatchNum(pNtk) > 0 ) Io_WriteVerilogLatches( pFile, pNtk ); } + if ( fNewInterface ) + Io_WriteVerilogAssigns( pFile, pNtk ); // finalize the file fprintf( pFile, "endmodule\n\n" ); } @@ -222,9 +226,10 @@ void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) SeeAlso [] ***********************************************************************/ -void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start, int fNewInterface ) { Abc_Obj_t * pTerm, * pNet, * pSkip; + char Name[100], * pName = Name; int LineLength; int AddedLength; int NameCounter; @@ -252,7 +257,11 @@ void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) } // get the line length after this name is written - AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( fNewInterface ) + sprintf( Name, "po_username%d", i ); + else + pName = Abc_ObjName(pNet); + AddedLength = strlen(Io_WriteVerilogGetName(pName)) + 2; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, "\n " ); @@ -260,7 +269,7 @@ void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) LineLength = 3; NameCounter = 0; } - fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (i==Abc_NtkPoNum(pNtk)-1)? "" : "," ); + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(pName), (i==Abc_NtkPoNum(pNtk)-1)? "" : "," ); LineLength += AddedLength; NameCounter++; } @@ -274,6 +283,37 @@ void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) } +/**Function************************************************************* + + Synopsis [Writes the primary outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogAssigns( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet, * pSkip; + int i; + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + if ( Abc_ObjIsPi(Abc_ObjFanin0(pNet)) ) + { + // Skip this output since it is a feedthrough -- the same + // name will appear as an input and an output which other + // tools reading verilog do not like. + + pSkip = pNet; // save an example of skipped net + continue; + } + fprintf( pFile, " assign po_username%d = %s;\n", i, Abc_ObjName(pNet) ); + } +} + /**Function************************************************************* Synopsis [Writes the wires.] @@ -816,7 +856,7 @@ void Io_WriteVerilogObjectsLut( FILE * pFile, Abc_Ntk_t * pNtk, int nLutSize, in fprintf( pFile, "}, %*s );\n", Length, Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj))) ); } } -void Io_WriteVerilogLutInt( FILE * pFile, Abc_Ntk_t * pNtk, int nLutSize, int fFixed ) +void Io_WriteVerilogLutInt( FILE * pFile, Abc_Ntk_t * pNtk, int nLutSize, int fFixed, int fNewInterface ) { // write inputs and outputs // fprintf( pFile, "module %s ( gclk,\n ", Abc_NtkName(pNtk) ); @@ -832,7 +872,7 @@ void Io_WriteVerilogLutInt( FILE * pFile, Abc_Ntk_t * pNtk, int nLutSize, int fF fprintf( pFile, ",\n " ); } if ( Abc_NtkPoNum(pNtk) > 0 ) - Io_WriteVerilogPos( pFile, pNtk, 3 ); + Io_WriteVerilogPos( pFile, pNtk, 3, fNewInterface ); fprintf( pFile, " );\n\n" ); // add the clock signal if it does not exist if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 ) @@ -848,7 +888,7 @@ void Io_WriteVerilogLutInt( FILE * pFile, Abc_Ntk_t * pNtk, int nLutSize, int fF if ( Abc_NtkPoNum(pNtk) > 0 ) { fprintf( pFile, " output" ); - Io_WriteVerilogPos( pFile, pNtk, 5 ); + Io_WriteVerilogPos( pFile, pNtk, 5, fNewInterface ); fprintf( pFile, ";\n\n" ); } // if this is not a blackbox, write internal signals @@ -875,10 +915,12 @@ void Io_WriteVerilogLutInt( FILE * pFile, Abc_Ntk_t * pNtk, int nLutSize, int fF Io_WriteVerilogLatches( pFile, pNtk ); } } + if ( fNewInterface ) + Io_WriteVerilogAssigns( pFile, pNtk ); // finalize the file fprintf( pFile, "\nendmodule\n\n" ); } -void Io_WriteVerilogLut( Abc_Ntk_t * pNtk, char * pFileName, int nLutSize, int fFixed, int fNoModules ) +void Io_WriteVerilogLut( Abc_Ntk_t * pNtk, char * pFileName, int nLutSize, int fFixed, int fNoModules, int fNewInterface ) { FILE * pFile; Abc_Ntk_t * pNtkTemp; @@ -917,7 +959,7 @@ void Io_WriteVerilogLut( Abc_Ntk_t * pNtk, char * pFileName, int nLutSize, int f } pNtkTemp = Abc_NtkToNetlist( pNtk ); Abc_NtkToSop( pNtkTemp, -1, ABC_INFINITY ); - Io_WriteVerilogLutInt( pFile, pNtkTemp, nLutSize, fFixed ); + Io_WriteVerilogLutInt( pFile, pNtkTemp, nLutSize, fFixed, fNewInterface ); Abc_NtkDelete( pNtkTemp ); fprintf( pFile, "\n" ); diff --git a/src/base/main/abcapis.h b/src/base/main/abcapis.h index 30494f77c5..d723e3e6f1 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/main/mainReal.c b/src/base/main/mainReal.c index 922e052158..420f2cf101 100644 --- a/src/base/main/mainReal.c +++ b/src/base/main/mainReal.c @@ -49,7 +49,9 @@ SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. #include #include #include +#if !defined(__wasm) #include +#endif #include #endif diff --git a/src/base/wlc/wlc.h b/src/base/wlc/wlc.h index ac47433387..715b3c29f3 100644 --- a/src/base/wlc/wlc.h +++ b/src/base/wlc/wlc.h @@ -223,6 +223,7 @@ struct Wlc_BstPar_t_ int fCreateWordMiter; int fDecMuxes; int fSaveFfNames; + int fBlastNew; int fVerbose; Vec_Int_t * vBoxIds; }; diff --git a/src/base/wlc/wlcAbs.c b/src/base/wlc/wlcAbs.c index c297c54fec..632778fe4d 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 86b18b0542..271b52d99c 100644 --- a/src/base/wlc/wlcBlast.c +++ b/src/base/wlc/wlcBlast.c @@ -20,6 +20,8 @@ #include "wlc.h" #include "misc/tim/tim.h" +#include "base/main/main.h" +#include "base/cmd/cmd.h" ABC_NAMESPACE_IMPL_START @@ -131,6 +133,61 @@ int Wlc_NtkMuxTree2( Gia_Man_t * pNew, int * pCtrl, int nCtrl, Vec_Int_t * vData Vec_IntPush( vTemp, Abc_LitNot( Gia_ManHashAnd(pNew, iLit, Vec_IntEntry(vData, m)) ) ); return Abc_LitNot( Gia_ManHashAndMulti(pNew, vTemp) ); } +int Wlc_NtkMuxTree3( Gia_Man_t * p, Vec_Int_t * vData, char * pNums, Vec_Int_t ** pvDecs ) +{ + int i, iStart = 0, nSize = Vec_IntSize(vData); + for ( i = (int)strlen(pNums)-1; i >= 0; i-- ) + { + int k, b, nBits = (int)(pNums[i] - '0'); + Vec_Int_t * vDec = pvDecs[i]; + 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)) ); + iStart += nBits; + } + assert( nSize == 1 ); + return Vec_IntEntry(vData, 0); +} +Vec_Int_t ** Wlc_NtkMuxTree3DecsDerive( Gia_Man_t * p, int * pIns, int nIns, char * pNums ) +{ + extern Vec_Int_t * Wlc_BlastDecoder2_rec( Gia_Man_t * p, int * pLits, int nLits ); + Vec_Int_t ** pvDecs = ABC_ALLOC( Vec_Int_t *, strlen(pNums) ); int i, iStart = 0; + for ( i = (int)strlen(pNums)-1; i >= 0; i-- ) { + pvDecs[i] = Wlc_BlastDecoder2_rec( p, pIns + iStart, (int)(pNums[i] - '0') ); + iStart += (int)(pNums[i] - '0'); + } + assert( iStart == nIns ); + return pvDecs; +} +void Wlc_NtkMuxTree3DecsFree( Vec_Int_t ** pvDecs, char * pNums ) +{ + int i; + for ( i = (int)strlen(pNums)-1; i >= 0; i-- ) + Vec_IntFree( pvDecs[i] ); + ABC_FREE( pvDecs ); +} +char * Wlc_NtkMuxTreeString( int nIns ) +{ + if ( nIns == 1 ) return (char*)"1"; + if ( nIns == 2 ) return (char*)"11"; + if ( nIns == 3 ) return (char*)"111"; + if ( nIns == 4 ) return (char*)"112"; + if ( nIns == 5 ) return (char*)"1112"; + if ( nIns == 6 ) return (char*)"1113"; + if ( nIns == 7 ) return (char*)"1114"; + if ( nIns == 8 ) return (char*)"1124"; + if ( nIns == 9 ) return (char*)"11124"; + if ( nIns == 10 ) return (char*)"11125"; + if ( nIns == 11 ) return (char*)"11126"; + if ( nIns == 12 ) return (char*)"11136"; + if ( nIns == 13 ) return (char*)"11137"; + if ( nIns == 14 ) return (char*)"11147"; + if ( nIns == 15 ) return (char*)"11148"; + if ( nIns == 16 ) return (char*)"11248"; + return NULL; +} void Wlc_NtkPrintNameArray( Vec_Ptr_t * vNames ) { int i; char * pTemp; @@ -317,6 +374,30 @@ int Wlc_BlastLessSigned( Gia_Man_t * pNew, int * pArg0, int * pArg1, int nBits ) int iDiffSign = Gia_ManHashXor( pNew, pArg0[nBits-1], pArg1[nBits-1] ); return Gia_ManHashMux( pNew, iDiffSign, pArg0[nBits-1], Wlc_BlastLess(pNew, pArg0, pArg1, nBits-1) ); } +int Wlc_BlastLess3( Gia_Man_t * p, int * pArg1, int * pArg0, int nBits ) +{ + int i, iLit = 1; + for ( i = 0; i < nBits; i++ ) { + int iLitA0 = pArg0[i]; + int iLitA1 = i == nBits-1 ? 0 : pArg0[i+1]; + int iLitB0 = pArg1[i]; + int iLitB1 = i == nBits-1 ? 0 : pArg1[i+1]; + int iOrLit0; + if ( i == 0 ) + iOrLit0 = Gia_ManHashOr(p, Abc_LitNotCond(iLitA0, !(i&1)), Abc_LitNotCond(iLitB0, i&1)); + else + iOrLit0 = Gia_ManHashAnd(p, Abc_LitNotCond(iLitA0, !(i&1)), Abc_LitNotCond(iLitB0, i&1)); + int iOrLit1 = Gia_ManHashAnd(p, Abc_LitNotCond(iLitA1, !(i&1)), Abc_LitNotCond(iLitB1, i&1)); + int iOrLit = Gia_ManHashOr(p, iOrLit0, iOrLit1 ); + iLit = Gia_ManHashOr(p, Abc_LitNot(iLit), iOrLit ); + } + return Abc_LitNotCond(iLit, nBits&1); +} +int Wlc_BlastLessSigned3( Gia_Man_t * pNew, int * pArg0, int * pArg1, int nBits ) +{ + int iDiffSign = Gia_ManHashXor( pNew, pArg0[nBits-1], pArg1[nBits-1] ); + return Gia_ManHashMux( pNew, iDiffSign, pArg0[nBits-1], Wlc_BlastLess3(pNew, pArg0, pArg1, nBits-1) ); +} void Wlc_BlastFullAdder( Gia_Man_t * pNew, int a, int b, int c, int * pc, int * ps ) { int fUseXor = 0; @@ -891,7 +972,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 +992,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 +1016,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 +1037,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 ) @@ -1120,6 +1208,37 @@ void Wlc_BlastDecoder( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vTmp, Vec_IntPush( vRes, iMint ); } } +Vec_Int_t * Wlc_BlastDecoder2_rec( 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 = Wlc_BlastDecoder2_rec( p, pLits, nPart1 ); + Vec_Int_t * vRes2 = Wlc_BlastDecoder2_rec( 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; +} +Vec_Int_t * Wlc_BlastDecoder2( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vTmp, Vec_Int_t * vRes ) +{ + Vec_Int_t * vRes2 = Wlc_BlastDecoder2_rec( pNew, pNum, nNum ); + Vec_IntClear( vRes ); + Vec_IntAppend( vRes, vRes2 ); + Vec_IntFree( vRes2 ); + return vRes; +} 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 ) { Vec_Wec_t * vProds = Vec_WecStart( nArgA + nArgB + 3 ); @@ -1155,6 +1274,7 @@ void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int int Prev = i ? pArgA[i-1] : 0; int Part = Gia_ManHashOr( pNew, Gia_ManHashAnd(pNew, One, This), Gia_ManHashAnd(pNew, Two, Prev) ); pp = Gia_ManHashXor( pNew, Part, Neg ); + if ( fVerbose ) printf( "%4d = PP(%5d %5d %5d %5d %5d)\n", pp, Prev, This, Q2jM1, Q2j, Q2jP1 ); if ( pp == 0 || (fSigned && i == nArgA) ) continue; if ( pp ) @@ -1201,6 +1321,8 @@ void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int //Vec_WecShrink( vLevels, nArgA + nArgB ); if ( fVerbose ) Vec_WecPrint( vProds, 0 ); + if ( fVerbose ) + printf( "Total PPs = %d.\n", Vec_WecSizeSize(vProds) ); //Wlc_BlastPrintMatrix( pNew, vProds, 1 ); //printf( "Cutoff ID for partial products = %d.\n", Gia_ManObjNum(pNew) ); if ( pvProds ) @@ -1541,34 +1663,60 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) Wlc_ObjForEachFanin( pObj, iFanin, k ) if ( k > 0 ) fSigned &= Wlc_NtkObj(p, iFanin)->Signed; - Vec_IntClear( vTemp1 ); - if ( pPar->fDecMuxes ) + if ( pParIn->fBlastNew && nRange0 <= 16 ) { - for ( k = 0; k < (1 << nRange0); k++ ) + char * pNums = Wlc_NtkMuxTreeString( nRange0 ); + Vec_Int_t ** pvDecs = Wlc_NtkMuxTree3DecsDerive( pNew, pFans0, nRange0, pNums ); + for ( b = 0; b < nRange; b++ ) { - int iLitAnd = 1; - for ( b = 0; b < nRange0; b++ ) - iLitAnd = Gia_ManHashAnd( pNew, iLitAnd, Abc_LitNotCond(pFans0[b], ((k >> b) & 1) == 0) ); - Vec_IntPush( vTemp1, iLitAnd ); + Vec_IntClear( vTemp0 ); + Wlc_ObjForEachFanin( pObj, iFanin, k ) { + if ( k > 0 ) + { + nRange1 = Wlc_ObjRange( Wlc_NtkObj(p, iFanin) ); + pFans1 = Vec_IntEntryP( vBits, Wlc_ObjCopy(p, iFanin) ); + if ( Wlc_ObjFaninNum(pObj) == 3 ) // Statement 1 + Vec_IntPush( vTemp0, b < nRange1 ? pFans1[b] : (fSigned? pFans1[nRange1-1] : 0) ); + else // Statement 2 + Vec_IntPush( vTemp0, b < nRange1 ? pFans1[b] : (Wlc_NtkObj(p, iFanin)->Signed? pFans1[nRange1-1] : 0) ); + } + } + assert( (1 << nRange0) == Vec_IntSize(vTemp0) ); + Vec_IntPush( vRes, Wlc_NtkMuxTree3(pNew, vTemp0, pNums, pvDecs) ); } + Wlc_NtkMuxTree3DecsFree( pvDecs, pNums ); } - for ( b = 0; b < nRange; b++ ) + else { - Vec_IntClear( vTemp0 ); - Wlc_ObjForEachFanin( pObj, iFanin, k ) - if ( k > 0 ) + Vec_IntClear( vTemp1 ); + if ( pPar->fDecMuxes ) + { + for ( k = 0; k < (1 << nRange0); k++ ) { - nRange1 = Wlc_ObjRange( Wlc_NtkObj(p, iFanin) ); - pFans1 = Vec_IntEntryP( vBits, Wlc_ObjCopy(p, iFanin) ); - if ( Wlc_ObjFaninNum(pObj) == 3 ) // Statement 1 - Vec_IntPush( vTemp0, b < nRange1 ? pFans1[b] : (fSigned? pFans1[nRange1-1] : 0) ); - else // Statement 2 - Vec_IntPush( vTemp0, b < nRange1 ? pFans1[b] : (Wlc_NtkObj(p, iFanin)->Signed? pFans1[nRange1-1] : 0) ); + int iLitAnd = 1; + for ( b = 0; b < nRange0; b++ ) + iLitAnd = Gia_ManHashAnd( pNew, iLitAnd, Abc_LitNotCond(pFans0[b], ((k >> b) & 1) == 0) ); + Vec_IntPush( vTemp1, iLitAnd ); } - if ( pPar->fDecMuxes ) - Vec_IntPush( vRes, Wlc_NtkMuxTree2(pNew, pFans0, nRange0, vTemp0, vTemp1, vTemp2) ); - else - Vec_IntPush( vRes, Wlc_NtkMuxTree_rec(pNew, pFans0, nRange0, vTemp0, 0) ); + } + for ( b = 0; b < nRange; b++ ) + { + Vec_IntClear( vTemp0 ); + Wlc_ObjForEachFanin( pObj, iFanin, k ) + if ( k > 0 ) + { + nRange1 = Wlc_ObjRange( Wlc_NtkObj(p, iFanin) ); + pFans1 = Vec_IntEntryP( vBits, Wlc_ObjCopy(p, iFanin) ); + if ( Wlc_ObjFaninNum(pObj) == 3 ) // Statement 1 + Vec_IntPush( vTemp0, b < nRange1 ? pFans1[b] : (fSigned? pFans1[nRange1-1] : 0) ); + else // Statement 2 + Vec_IntPush( vTemp0, b < nRange1 ? pFans1[b] : (Wlc_NtkObj(p, iFanin)->Signed? pFans1[nRange1-1] : 0) ); + } + if ( pPar->fDecMuxes ) + Vec_IntPush( vRes, Wlc_NtkMuxTree2(pNew, pFans0, nRange0, vTemp0, vTemp1, vTemp2) ); + else + Vec_IntPush( vRes, Wlc_NtkMuxTree_rec(pNew, pFans0, nRange0, vTemp0, 0) ); + } } } else if ( pObj->Type == WLC_OBJ_SEL ) @@ -1772,9 +1920,9 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) int fCompl = (pObj->Type == WLC_OBJ_COMP_MOREEQU || pObj->Type == WLC_OBJ_COMP_LESSEQU); if ( fSwap ) ABC_SWAP( int *, pArg0, pArg1 ); if ( fSigned ) - iLit = Wlc_BlastLessSigned( pNew, pArg0, pArg1, nRangeMax ); + iLit = pParIn->fBlastNew ? Wlc_BlastLessSigned3( pNew, pArg0, pArg1, nRangeMax ) : Wlc_BlastLessSigned( pNew, pArg0, pArg1, nRangeMax ); else - iLit = Wlc_BlastLess( pNew, pArg0, pArg1, nRangeMax ); + iLit = pParIn->fBlastNew ? Wlc_BlastLess3( pNew, pArg0, pArg1, nRangeMax ) : Wlc_BlastLess( pNew, pArg0, pArg1, nRangeMax ); iLit = Abc_LitNotCond( iLit, fCompl ); Vec_IntFill( vRes, 1, iLit ); for ( k = 1; k < nRange; k++ ) @@ -1835,7 +1983,7 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) int nRangeMax = Abc_MaxInt(nRange0, nRange1); int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, fSigned ); int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, fSigned ); - if ( Wlc_NtkCountConstBits(pArg0, nRangeMax) < Wlc_NtkCountConstBits(pArg1, nRangeMax) ) + if ( nRange0 == nRange1 && Wlc_NtkCountConstBits(pArg0, nRangeMax) < Wlc_NtkCountConstBits(pArg1, nRangeMax) ) ABC_SWAP( int *, pArg0, pArg1 ); if ( pPar->fBooth ) Wlc_BlastBooth( pNew, pArg0, pArg1, nRange0, nRange1, vRes, fSigned, pPar->fCla, NULL, pParIn->fVerbose ); @@ -1905,7 +2053,10 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) else if ( pObj->Type == WLC_OBJ_DEC ) { int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRange0, 0 ); - Wlc_BlastDecoder( pNew, pArg0, nRange0, vTemp2, vRes ); + if ( pParIn->fBlastNew ) + Wlc_BlastDecoder2( pNew, pArg0, nRange0, vTemp2, vRes ); + else + Wlc_BlastDecoder( pNew, pArg0, nRange0, vTemp2, vRes ); if ( nRange > Vec_IntSize(vRes) ) Vec_IntFillExtra( vRes, nRange, 0 ); else @@ -2738,6 +2889,47 @@ void Wlc_TransferPioNames( Wlc_Ntk_t * p, Gia_Man_t * pNew ) printf( "Successfully transferred the primary input/output names from the word-level design to the current AIG.\n" ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wlc_MultBlastFileGen( int a, int b, int s ) +{ + FILE * pFile = fopen( "_test13_.v", "wb" ); + fprintf( pFile, "module test ( a, b, z );\n" ); + fprintf( pFile, "input %s [%d:0] a;\n", s ? "signed":"", a-1 ); + fprintf( pFile, "input %s [%d:0] b;\n", s ? "signed":"", b-1 ); + fprintf( pFile, "output %s [%d:0] z;\n", s ? "signed":"", a+b-1 ); + fprintf( pFile, "assign z = a * b;\n" ); + fprintf( pFile, "endmodule\n" ); + fclose( pFile ); +} +void Wlc_MultBlastTest() +{ + char * Command = "%read _test13_.v; %blast; &ps; &w 1.aig; %read _test13_.v; %blast -b; &ps; &w 2.aig; cec -n 1.aig 2.aig"; + int a, b, s, Iters = 0; + for ( a = 1; a < 8; a++ ) + for ( b = 1; b < 8; b++ ) + for ( s = 0; s < 2; s++ ) + { + Wlc_MultBlastFileGen( a, b, s ); + if ( Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ) ) + { + fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); + return; + } + Iters++; + } + printf( "Finished %d iterations.\n", Iters ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/wlc/wlcCom.c b/src/base/wlc/wlcCom.c index d15a7723b7..a3747fcfde 100644 --- a/src/base/wlc/wlcCom.c +++ b/src/base/wlc/wlcCom.c @@ -1046,7 +1046,7 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) Wlc_BstParDefault( pPar ); pPar->nOutputRange = 2; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ORAMcombqaydestrnizvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "ORAMcombqaydestrfnizvh" ) ) != EOF ) { switch ( c ) { @@ -1131,9 +1131,12 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'r': fReorder ^= 1; break; - case 'n': + case 'f': fDumpNames ^= 1; break; + case 'n': + pPar->fBlastNew ^= 1; + break; case 'i': fPrintInputInfo ^= 1; break; @@ -1222,7 +1225,7 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_FrameUpdateGia( pAbc, pNew ); return 0; usage: - Abc_Print( -2, "usage: %%blast [-ORAM num] [-combqaydestrnizvh]\n" ); + Abc_Print( -2, "usage: %%blast [-ORAM num] [-combqaydestrfnizvh]\n" ); Abc_Print( -2, "\t performs bit-blasting of the word-level design\n" ); Abc_Print( -2, "\t-O num : zero-based index of the first word-level PO to bit-blast [default = %d]\n", pPar->iOutput ); Abc_Print( -2, "\t-R num : the total number of word-level POs to bit-blast [default = %d]\n", pPar->nOutputRange ); @@ -1240,7 +1243,8 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-s : toggle creating decoded MUXes [default = %s]\n", pPar->fDecMuxes? "yes": "no" ); Abc_Print( -2, "\t-t : toggle creating regular multi-output miter [default = %s]\n", fMiter? "yes": "no" ); Abc_Print( -2, "\t-r : toggle using interleaved variable ordering [default = %s]\n", fReorder? "yes": "no" ); - Abc_Print( -2, "\t-n : toggle dumping signal names into a text file [default = %s]\n", fDumpNames? "yes": "no" ); + Abc_Print( -2, "\t-f : toggle dumping signal names into a text file [default = %s]\n", fDumpNames? "yes": "no" ); + Abc_Print( -2, "\t-n : toggle using improved bit-blasting procedures [default = %s]\n", pPar->fBlastNew? "yes": "no" ); Abc_Print( -2, "\t-i : toggle to print input names after blasting [default = %s]\n", fPrintInputInfo ? "yes": "no" ); Abc_Print( -2, "\t-z : toggle saving flop names after blasting [default = %s]\n", pPar->fSaveFfNames ? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPar->fVerbose? "yes": "no" ); diff --git a/src/base/wlc/wlcMem.c b/src/base/wlc/wlcMem.c index b2d5c5ee08..1f35f324e2 100644 --- a/src/base/wlc/wlcMem.c +++ b/src/base/wlc/wlcMem.c @@ -1024,7 +1024,7 @@ int Wlc_NtkMemAbstract( Wlc_Ntk_t * p, int nIterMax, int fDumpAbs, int fPdrVerbo pAig = Gia_ManToAigSimple( pAbs ); Gia_ManStop( pAbs ); pAig->nConstrs = 1; - pAig = Saig_ManDupFoldConstrsFunc( pTempAig = pAig, 0, 0 ); + pAig = Saig_ManDupFoldConstrsFunc( pTempAig = pAig, 0, 0, 1 ); Aig_ManStop( pTempAig ); pAbs = Gia_ManFromAigSimple( pAig ); Aig_ManStop( pAig ); diff --git a/src/base/wln/wlnRtl.c b/src/base/wln/wlnRtl.c index 36801c8626..f7364bdedc 100644 --- a/src/base/wln/wlnRtl.c +++ b/src/base/wln/wlnRtl.c @@ -121,6 +121,9 @@ char * Wln_GetYosysName() } int Wln_ConvertToRtl( char * pCommand, char * pFileTemp ) { +#if defined(__wasm) + return 0; +#else FILE * pFile; if ( system( pCommand ) == -1 ) { @@ -134,6 +137,7 @@ int Wln_ConvertToRtl( char * pCommand, char * pFileTemp ) } fclose( pFile ); return 1; +#endif } Rtl_Lib_t * Wln_ReadSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, int fCollapse, int fVerbose ) { diff --git a/src/bdd/cas/casCore.c b/src/bdd/cas/casCore.c index 21c21d2004..23d7be521d 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 4c5cd89155..e8d017fe0d 100644 --- a/src/bdd/dsd/dsd.h +++ b/src/bdd/dsd/dsd.h @@ -115,9 +115,13 @@ 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_TreePrint3( void * pStr, Dsd_Manager_t * pDsdMan, int Output ); +extern void Dsd_TreePrint4( void * pStr, Dsd_Manager_t * pDsdMan, int Output ); extern void Dsd_NodePrint( FILE * pFile, Dsd_Node_t * pNode ); +extern int Dsd_TreeNonDsdMax( Dsd_Manager_t * pDsdMan, int Output ); +extern int Dsd_TreeSuppSize( Dsd_Manager_t * pDsdMan, int Output ); /*=== dsdLocal.c =======================================================*/ extern DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode ); diff --git a/src/bdd/dsd/dsdTree.c b/src/bdd/dsd/dsdTree.c index 9b9dd21210..1873ae0c10 100644 --- a/src/bdd/dsd/dsdTree.c +++ b/src/bdd/dsd/dsdTree.c @@ -627,6 +627,195 @@ void Dsd_TreeCollectNodesDfs_rec( Dsd_Node_t * pNode, Dsd_Node_t * ppNodes[], in ppNodes[ (*pnNodes)++ ] = pNode; } +/**Function************************************************************* + + Synopsis [Returns the size of the largest non-DSD block.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dsd_TreeNonDsdMax_rec( Dsd_Node_t * pNode ) +{ + if ( pNode->Type == DSD_NODE_CONST1 ) + return 0; + if ( pNode->Type == DSD_NODE_BUF ) + return 0; + int MaxBlock = pNode->Type == DSD_NODE_PRIME ? pNode->nDecs : 0; + for ( int i = 0; i < pNode->nDecs; i++ ) + { + int MaxThis = Dsd_TreeNonDsdMax_rec( Dsd_Regular( pNode->pDecs[i] ) ); + MaxBlock = Abc_MaxInt( MaxBlock, MaxThis ); + } + return MaxBlock; +} +int Dsd_TreeNonDsdMax( Dsd_Manager_t * pDsdMan, int Output ) +{ + if ( Output == -1 ) + { + int i, Res = 0; + for ( i = 0; i < pDsdMan->nRoots; i++ ) + Res = Abc_MaxInt( Res, Dsd_TreeNonDsdMax_rec( Dsd_Regular( pDsdMan->pRoots[i] ) ) ); + return Res; + } + else + { + assert( Output >= 0 && Output < pDsdMan->nRoots ); + return Dsd_TreeNonDsdMax_rec( Dsd_Regular( pDsdMan->pRoots[Output] ) ); + } +} + +/**Function************************************************************* + + Synopsis [Returns the support size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dsd_TreeSuppSize_rec( Dsd_Node_t * pNode ) +{ + if ( pNode->Type == DSD_NODE_CONST1 ) + return 0; + if ( pNode->Type == DSD_NODE_BUF ) + return 1; + int nSuppSize = 0; + for ( int i = 0; i < pNode->nDecs; i++ ) + nSuppSize += Dsd_TreeSuppSize_rec( Dsd_Regular( pNode->pDecs[i] ) ); + return nSuppSize; +} +int Dsd_TreeSuppSize( Dsd_Manager_t * pDsdMan, int Output ) +{ + if ( Output == -1 ) + { + int i, Res = 0; + for ( i = 0; i < pDsdMan->nRoots; i++ ) + Res += Dsd_TreeSuppSize_rec( Dsd_Regular( pDsdMan->pRoots[i] ) ); + return Res; + } + else + { + assert( Output >= 0 && Output < pDsdMan->nRoots ); + return Dsd_TreeSuppSize_rec( Dsd_Regular( pDsdMan->pRoots[Output] ) ); + } +} + +/**Function************************************************************* + + Synopsis [Prints the decompostion tree into a string.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dsd_TreePrint3_rec( Vec_Str_t * p, Dsd_Node_t * pNode ) +{ + if ( pNode->Type == DSD_NODE_BUF ) { + Vec_StrPush( p, (int)(pNode->S->index >= 26 ? 'A' - 26 : 'a') + pNode->S->index ); + return; + } + if ( pNode->Type == DSD_NODE_PRIME ) + Vec_StrPush( p, '{' ); + else if ( pNode->Type == DSD_NODE_OR ) + Vec_StrPush( p, '(' ); + else if ( pNode->Type == DSD_NODE_EXOR ) + Vec_StrPush( p, '[' ); + else assert( 0 ); + for ( int i = 0; i < pNode->nDecs; i++ ) + { + Dsd_Node_t * pInput = Dsd_Regular( pNode->pDecs[i] ); + if ( pInput != pNode->pDecs[i] ) + Vec_StrPush( p, '~' ); + Dsd_TreePrint3_rec( p, pInput ); + } + if ( pNode->Type == DSD_NODE_PRIME ) + Vec_StrPush( p, '}' ); + else if ( pNode->Type == DSD_NODE_OR ) + Vec_StrPush( p, ')' ); + else if ( pNode->Type == DSD_NODE_EXOR ) + Vec_StrPush( p, ']' ); + else assert( 0 ); +} +void Dsd_TreePrint3( void * pStr, Dsd_Manager_t * pDsdMan, int Output ) +{ + Vec_Str_t * p = (Vec_Str_t *)pStr; + assert( Output >= 0 && Output < pDsdMan->nRoots ); + Dsd_Node_t * pNode = Dsd_Regular( pDsdMan->pRoots[Output] ); + int fCompl = pNode != pDsdMan->pRoots[Output]; + if ( pNode->Type == DSD_NODE_CONST1 ) + Vec_StrPush( p, fCompl ? '0' : '1' ); + else { + if ( fCompl ) + Vec_StrPush( p, '~' ); + Dsd_TreePrint3_rec( p, pNode ); + } + Vec_StrPush( p, '\0' ); +} + +/**Function************************************************************* + + Synopsis [Prints the decompostion tree into a string.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dsd_TreePrint4_rec( Vec_Str_t * p, Dsd_Node_t * pNode ) +{ + if ( pNode->Type == DSD_NODE_BUF ) { + Vec_StrPush( p, (int)(pNode->S->index >= 26 ? 'A' - 26 : 'a') + pNode->S->index ); + return; + } + if ( pNode->Type == DSD_NODE_PRIME ) + Vec_StrPush( p, '{' ); + else if ( pNode->Type == DSD_NODE_OR ) + Vec_StrPush( p, '(' ); + else if ( pNode->Type == DSD_NODE_EXOR ) + Vec_StrPush( p, '[' ); + else assert( 0 ); + for ( int i = 0; i < pNode->nDecs; i++ ) + { + Dsd_Node_t * pInput = Dsd_Regular( pNode->pDecs[i] ); + if ( (pInput != pNode->pDecs[i]) ^ (pNode->Type == DSD_NODE_OR) ^ (pInput->Type == DSD_NODE_OR) ) + Vec_StrPush( p, '~' ); + Dsd_TreePrint4_rec( p, pInput ); + } + if ( pNode->Type == DSD_NODE_PRIME ) + Vec_StrPush( p, '}' ); + else if ( pNode->Type == DSD_NODE_OR ) + Vec_StrPush( p, ')' ); + else if ( pNode->Type == DSD_NODE_EXOR ) + Vec_StrPush( p, ']' ); + else assert( 0 ); +} +void Dsd_TreePrint4( void * pStr, Dsd_Manager_t * pDsdMan, int Output ) +{ + Vec_Str_t * p = (Vec_Str_t *)pStr; + assert( Output >= 0 && Output < pDsdMan->nRoots ); + Dsd_Node_t * pNode = Dsd_Regular( pDsdMan->pRoots[Output] ); + int fCompl = pNode != pDsdMan->pRoots[Output]; + if ( pNode->Type == DSD_NODE_CONST1 ) + Vec_StrPush( p, fCompl ? '0' : '1' ); + else { + if ( fCompl ^ (pNode->Type == DSD_NODE_OR) ) + Vec_StrPush( p, '~' ); + Dsd_TreePrint4_rec( p, pNode ); + } + Vec_StrPush( p, '\0' ); +} + /**Function************************************************************* Synopsis [Prints the decompostion tree into file.] @@ -638,7 +827,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 +839,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 +875,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 +900,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 +916,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 +940,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 +956,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 +980,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 +996,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 +1168,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 0000000000..38a5dcd264 --- /dev/null +++ b/src/bdd/extrab/extraLutCas.h @@ -0,0 +1,363 @@ +/**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 + +#ifdef _MSC_VER +# include +# define __builtin_popcount __popcnt +#endif + +#include +#include +#include +#include + +#include "aig/miniaig/miniaig.h" +#include "bdd/cudd/cuddInt.h" +#include "bdd/dsd/dsd.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. +*/ + +#define Mini_AigForEachNonPo( p, i ) for (i = 1; i < Mini_AigNodeNum(p); i++) if ( Mini_AigNodeIsPo(p, i) ) {} else + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_LutCasCollapseDeref( DdManager * dd, Vec_Ptr_t * vFuncs ) +{ + DdNode * bFunc; int i; + Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i ) + if ( bFunc ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vFuncs ); +} +Vec_Ptr_t * Abc_LutCasCollapse( Mini_Aig_t * p, DdManager * dd, int nBddLimit, int fVerbose ) +{ + DdNode * bFunc0, * bFunc1, * bFunc; int Id, nOuts = 0; + Vec_Ptr_t * vFuncs = Vec_PtrStart( Mini_AigNodeNum(p) ); + Vec_PtrWriteEntry( vFuncs, 0, Cudd_ReadLogicZero(dd) ), Cudd_Ref(Cudd_ReadLogicZero(dd)); + Mini_AigForEachPi( p, Id ) + Vec_PtrWriteEntry( vFuncs, Id, Cudd_bddIthVar(dd,Id-1) ), Cudd_Ref(Cudd_bddIthVar(dd,Id-1)); + Mini_AigForEachAnd( p, Id ) { + bFunc0 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(vFuncs, Mini_AigLit2Var(Mini_AigNodeFanin0(p, Id))), Mini_AigLitIsCompl(Mini_AigNodeFanin0(p, Id)) ); + bFunc1 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(vFuncs, Mini_AigLit2Var(Mini_AigNodeFanin1(p, Id))), Mini_AigLitIsCompl(Mini_AigNodeFanin1(p, Id)) ); + bFunc = Cudd_bddAndLimit( dd, bFunc0, bFunc1, nBddLimit ); + if ( bFunc == NULL ) + { + Abc_LutCasCollapseDeref( dd, vFuncs ); + return NULL; + } + Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( vFuncs, Id, bFunc ); + } + Mini_AigForEachPo( p, Id ) { + bFunc0 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(vFuncs, Mini_AigLit2Var(Mini_AigNodeFanin0(p, Id))), Mini_AigLitIsCompl(Mini_AigNodeFanin0(p, Id)) ); + Vec_PtrWriteEntry( vFuncs, Id, bFunc0 ); Cudd_Ref( bFunc0 ); + } + Mini_AigForEachNonPo( p, Id ) { + bFunc = (DdNode *)Vec_PtrEntry(vFuncs, Id); + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrWriteEntry( vFuncs, Id, NULL ); + } + Mini_AigForEachPo( p, Id ) + Vec_PtrWriteEntry( vFuncs, nOuts++, Vec_PtrEntry(vFuncs, Id) ); + Vec_PtrShrink( vFuncs, nOuts ); + return vFuncs; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_LutBddScan( DdManager * dd, DdNode * bFunc, int nVars ) +{ + Vec_Ptr_t * vRes = Vec_PtrAlloc( 1 << nVars ); + Vec_Ptr_t * vRes2 = Vec_PtrAlloc( 1 << nVars ); + Vec_PtrPush( vRes, bFunc ); + int v, Level = Cudd_ReadPerm( dd, Cudd_NodeReadIndex(bFunc) ); + for ( v = 0; v < dd->size; v++ ) + printf( "%2d : perm = %d invperm = %d\n", v, dd->perm[v], dd->invperm[v] ); + for ( v = 0; v < nVars; v++ ) + { + int i, LevelCur = Level + v; + Vec_PtrClear( vRes2 ); + DdNode * bTemp; + Vec_PtrForEachEntry( DdNode *, vRes, bTemp, i ) { + int LevelTemp = Cudd_ReadPerm( dd, Cudd_NodeReadIndex(bTemp) ); + if ( LevelTemp == LevelCur ) { + Vec_PtrPush( vRes2, Cudd_NotCond(Cudd_E(bTemp), Cudd_IsComplement(bTemp)) ); + Vec_PtrPush( vRes2, Cudd_NotCond(Cudd_T(bTemp), Cudd_IsComplement(bTemp)) ); + } + else if ( LevelTemp > LevelCur ) { + Vec_PtrPush( vRes2, bTemp ); + Vec_PtrPush( vRes2, bTemp ); + } + else assert( 0 ); + } + ABC_SWAP( Vec_Ptr_t *, vRes, vRes2 ); + //Vec_PtrForEachEntry( DdNode *, vRes, bTemp, i ) + // printf( "%p ", bTemp ); + //printf( "\n" ); + } + Vec_PtrFree( vRes2 ); + assert( Vec_PtrSize(vRes) == (1 << nVars) ); + return vRes; +} +char * Abc_LutBddToTruth( Vec_Ptr_t * vFuncs ) +{ + assert( Vec_PtrSize(vFuncs) <= 256 ); + char * pRes = ABC_CALLOC( char, Vec_PtrSize(vFuncs)+1 ); + void * pTemp, * pStore[256] = {Vec_PtrEntry(vFuncs, 0)}; + int i, k, nStore = 1; pRes[0] = 'a'; + Vec_PtrForEachEntryStart( void *, vFuncs, pTemp, i, 1 ) { + for ( k = 0; k < nStore; k++ ) + if ( pStore[k] == pTemp ) + break; + if ( k == nStore ) + pStore[nStore++] = pTemp; + pRes[i] = 'a' + (char)k; + } + return pRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_NtkPrecomputeData() +{ + char * pRes = ABC_CALLOC( char, 1 << 16 ); + int i, k, b; + for ( i = 0; i < 256; i++ ) { + int nOnes = __builtin_popcount(i); + char * pTemp = pRes + 256*i; + for ( k = 0; k < 256; k++ ) { + int iMask = 0, Counts[2] = {nOnes, 0}; + for ( b = 0; b < 8; Counts[(i >> b++)&1]++ ) + if ( (k >> b) & 1 ) + iMask |= 1 << Counts[(i >> b)&1]; + pTemp[iMask] = (char)k; + assert( Counts[1] == nOnes ); + } + } + for ( i = 0; i < 16; i++, printf("\n") ) + for ( printf("%x : ", i), k = 0; k < 16; k++ ) + printf( "%x=%x ", k, (int)pRes[i*256+k] ); + return pRes; +} + +int Abc_NtkDecPatCount( int iFirst, int nStep, int MyuMax, char * pDecPat, char * pPermInfo ) +{ + int s, k, nPats = 1; + char Pats[256] = { pDecPat[(int)pPermInfo[iFirst]] }; + assert( MyuMax <= 256 ); + for ( s = 1; s < nStep; s++ ) { + char Entry = pDecPat[(int)pPermInfo[iFirst+s]]; + for ( k = 0; k < nPats; k++ ) + if ( Pats[k] == Entry ) + break; + if ( k < nPats ) + continue; + if ( nPats == MyuMax ) + return MyuMax + 1; + assert( nPats < 256 ); + Pats[nPats++] = Entry; + } + return nPats; +} +int Abc_NtkDecPatDecompose_rec( int Mask, int nMaskVars, int iStart, int nVars, int nDiffs, int nRails, char * pDecPat, char * pPermInfo ) +{ + if ( nDiffs == 0 || iStart == nVars ) + return 0; + int v, m, nMints = 1 << nVars; + for ( v = iStart; v < nVars; v++ ) { + int MaskThis = Mask & ~(1 << v); + int nStep = 1 << (nMaskVars - 1); + int MyuMax = 0; + for ( m = 0; m < nMints; m += nStep ) { + int MyuCur = Abc_NtkDecPatCount( m, nStep, 1 << nDiffs, pDecPat, pPermInfo+256*MaskThis ); + MyuMax = Abc_MaxInt( MyuMax, MyuCur ); + } + if ( MyuMax > (1 << nDiffs) ) + continue; + if ( MyuMax <= (1 << nRails) ) + return MaskThis; + MaskThis = Abc_NtkDecPatDecompose_rec( MaskThis, nMaskVars-1, v+1, nVars, nDiffs-1, nRails, pDecPat, pPermInfo ); + if ( MaskThis ) + return MaskThis; + } + return 0; +} +int Abc_NtkDecPatDecompose( int nVars, int nRails, char * pDecPat, char * pPermInfo ) +{ + int BoundSet = ~(~0 << nVars); + int Myu = Abc_NtkDecPatCount( 0, 1 << nVars, 256, pDecPat, pPermInfo + 256*BoundSet ); + int Log2 = Abc_Base2Log( Myu ); + if ( Log2 <= nRails ) + return BoundSet; + return Abc_NtkDecPatDecompose_rec( BoundSet, nVars, 0, nVars, Log2 - nRails, nRails, pDecPat, pPermInfo ); +} + +int Abc_NtkCascadeDecompose( int nVars, int nRails, char * pDecPat, char * pPermInfo ) +{ + return 0; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_LutCasFakeNames( int nNames ) +{ + Vec_Ptr_t * vNames; + char Buffer[5]; + int i; + + vNames = Vec_PtrAlloc( nNames ); + for ( i = 0; i < nNames; i++ ) + { + if ( nNames < 26 ) + { + Buffer[0] = 'a' + i; + Buffer[1] = 0; + } + else + { + Buffer[0] = 'a' + i%26; + Buffer[1] = '0' + i/26; + Buffer[2] = 0; + } + Vec_PtrPush( vNames, Extra_UtilStrsav(Buffer) ); + } + return vNames; +} +void Abc_LutCasPrintDsd( DdManager * dd, DdNode * bFunc, int fVerbose ) +{ + Dsd_Manager_t * pManDsd = Dsd_ManagerStart( dd, dd->size, 0 ); + Dsd_Decompose( pManDsd, &bFunc, 1 ); + if ( fVerbose ) + { + Vec_Ptr_t * vNamesCi = Abc_LutCasFakeNames( dd->size ); + Vec_Ptr_t * vNamesCo = Abc_LutCasFakeNames( 1 ); + char ** ppNamesCi = (char **)Vec_PtrArray( vNamesCi ); + char ** ppNamesCo = (char **)Vec_PtrArray( vNamesCo ); + Dsd_TreePrint( stdout, pManDsd, ppNamesCi, ppNamesCo, 0, -1, 0 ); + Vec_PtrFreeFree( vNamesCi ); + Vec_PtrFreeFree( vNamesCo ); + } + Dsd_ManagerStop( pManDsd ); +} +DdNode * Abc_LutCasBuildBdds( Mini_Aig_t * p, DdManager ** pdd, int fReorder ) +{ + DdManager * dd = Cudd_Init( Mini_AigPiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + if ( fReorder ) Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + Vec_Ptr_t * vFuncs = Abc_LutCasCollapse( p, dd, 10000, 0 ); + if ( fReorder ) Cudd_AutodynDisable( dd ); + if ( vFuncs == NULL ) { + Extra_StopManager( dd ); + return NULL; + } + DdNode * bNode = (DdNode *)Vec_PtrEntry(vFuncs, 0); + Vec_PtrFree(vFuncs); + *pdd = dd; + return bNode; +} +static inline word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ) +{ + DdManager * dd = NULL; + DdNode * bFunc = Abc_LutCasBuildBdds( p, &dd, 0 ); + if ( bFunc == NULL ) return NULL; + char * pPermInfo = Abc_NtkPrecomputeData(); + Abc_LutCasPrintDsd( dd, bFunc, 1 ); + + Vec_Ptr_t * vTemp = Abc_LutBddScan( dd, bFunc, nLutSize ); + char * pTruth = Abc_LutBddToTruth( vTemp ); + + int BoundSet = Abc_NtkDecPatDecompose( nLutSize, nRails, pTruth, pPermInfo ); + printf( "Pattern %s : Bound set = %d\n", pTruth, BoundSet ); + + ABC_FREE( pTruth ); + Vec_PtrFree( vTemp ); + + Cudd_RecursiveDeref( dd, bFunc ); + Extra_StopManager( dd ); + ABC_FREE( pPermInfo ); + + printf( "\n" ); + word * pLuts = NULL; + return pLuts; +} + +ABC_NAMESPACE_HEADER_END + +#endif /* ABC__misc__extra__extra_lutcas_h */ diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp index d8a44b1d54..55097a4539 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 @@ -289,6 +294,7 @@ class ac_decomposition_impl pst->num_luts = best_multiplicity <= 2 ? 2 : best_multiplicity <= 4 ? 3 : best_multiplicity <= 8 ? 4 : 5; + pst->num_edges = ( pst->num_luts - 1 ) * ( num_vars - best_free_set ) + ( pst->num_luts - 1 ) + best_free_set; } return true; @@ -459,7 +465,7 @@ class ac_decomposition_impl 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 */ @@ -506,7 +512,7 @@ class ac_decomposition_impl } while ( combinations_offset_next( free_set_size, offset, pComb, pInvPerm, tt ) ); std::array res_perm; - + if ( best_cost > ( 1 << ( ps.lut_size - free_set_size ) ) ) { return std::make_tuple( local_best_tt, res_perm, UINT32_MAX ); @@ -798,31 +804,43 @@ class ac_decomposition_impl } } support_minimization_encodings = std::vector>( num_combs ); - generate_support_minimization_encodings_rec( 0, 0, 0, count ); + generate_support_minimization_encodings_rec( 0, 0, 0, count, best_multiplicity >> 1, true ); + assert( count == num_combs ); + return; } - else if ( best_multiplicity > 8 ) + + /* constraint the number of offset classes for a strict encoding */ + int32_t min_set_size = 1; + if ( best_multiplicity <= 4 ) + min_set_size = 2; + else if ( best_multiplicity <= 8 ) + min_set_size = 4; + else + min_set_size = 8; + min_set_size = best_multiplicity - min_set_size; + + if ( best_multiplicity > 8 ) { - /* combinations are 2^(mu - 1) */ - num_combs = 1u << ( best_multiplicity - 1 ); + /* distinct elements in 2 indistinct bins with at least `min_set_size` elements in the indistinct bins */ + uint32_t class_sizes[13] = { 3, 3, 15, 25, 35, 35, 255, 501, 957, 1749, 3003, 4719, 6435 }; + num_combs = class_sizes[best_multiplicity - 3]; support_minimization_encodings = std::vector>( num_combs ); - generate_support_minimization_encodings_rec( 0, 0, 0, count ); + generate_support_minimization_encodings_rec( 0, 0, 0, count, min_set_size, true ); } else { - /* combinations are 2*3^(mu - 1) */ - for ( uint32_t i = 1; i < best_multiplicity; ++i ) - { - num_combs = ( num_combs << 1 ) + num_combs; - } + /* distinct elements in 3 bins, of which 2 are indistinct, and with at least `min_set_size` elements in the indistinct bins */ + uint32_t class_sizes[13] = { 6, 3, 90, 130, 105, 35, 9330, 23436, 48708, 78474, 91377, 70785, 32175 }; + num_combs = class_sizes[best_multiplicity - 3]; support_minimization_encodings = std::vector>( num_combs ); - generate_support_minimization_encodings_rec( 0, 0, 0, count ); + generate_support_minimization_encodings_rec( 0, 0, 0, count, min_set_size, true ); } assert( count == num_combs ); } template - void generate_support_minimization_encodings_rec( uint32_t onset, uint32_t offset, uint32_t var, uint32_t& count ) + void generate_support_minimization_encodings_rec( uint32_t onset, uint32_t offset, uint32_t var, uint32_t& count, int32_t min_set_size, bool first ) { if ( var == best_multiplicity ) { @@ -834,6 +852,11 @@ class ac_decomposition_impl return; } } + else if ( __builtin_popcount( onset ) < min_set_size || __builtin_popcount( offset ) < min_set_size ) + { + /* ON-set and OFF-set must be populated with at least min_set_size elements */ + return; + } support_minimization_encodings[count][0] = onset; support_minimization_encodings[count][1] = offset; @@ -844,23 +867,23 @@ class ac_decomposition_impl /* var in DCSET */ if ( enable_dcset ) { - generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); + generate_support_minimization_encodings_rec( onset, offset, var + 1, count, min_set_size, first ); } /* move var in ONSET */ onset |= 1 << var; - generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); + generate_support_minimization_encodings_rec( onset, offset, var + 1, count, min_set_size, false ); onset &= ~( 1 << var ); /* remove symmetries */ - if ( var == 0 ) + if ( first ) { return; } /* move var in OFFSET */ offset |= 1 << var; - generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); + generate_support_minimization_encodings_rec( onset, offset, var + 1, count, min_set_size, false ); offset &= ~( 1 << var ); } @@ -1011,15 +1034,6 @@ class ac_decomposition_impl uint32_t const onset = support_minimization_encodings[i][0]; uint32_t const offset = support_minimization_encodings[i][1]; - uint32_t ones_onset = __builtin_popcount( onset ); - uint32_t ones_offset = __builtin_popcount( offset ); - - /* filter columns that do not distinguish pairs */ - if ( ones_onset == 0 || ones_offset == 0 || ones_onset == best_multiplicity || ones_offset == best_multiplicity ) - { - continue; - } - /* compute function and distinguishable seed dichotomies */ uint64_t column[2] = { 0, 0 }; STT tt; @@ -1498,4 +1512,4 @@ class ac_decomposition_impl ABC_NAMESPACE_CXX_HEADER_END -#endif // _ACD_H_ \ No newline at end of file +#endif // _ACD_H_ diff --git a/src/map/if/acd/ac_wrapper.cpp b/src/map/if/acd/ac_wrapper.cpp index ad923edd22..ed512961fb 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 edb45ca7f2..47c9afe459 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 1095129867..607eee197c 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 e43404ea91..cf9bd6a277 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 }; }; @@ -602,7 +610,7 @@ class acdXX_impl : cost <= 32 ? 4 : 5; - if ( ss_vars_needed + free_set_size < 6 ) + if ( ss_vars_needed + free_set_size < ps.lut_size ) { /* look for a shared variable */ best_multiplicity = cost; @@ -657,7 +665,7 @@ class acdXX_impl : cost <= 32 ? 4 : 5; - if ( ss_vars_needed + free_set_size < 6 ) + if ( ss_vars_needed + free_set_size < ps.lut_size ) { /* look for a shared variable */ best_multiplicity = cost; @@ -795,7 +803,7 @@ class acdXX_impl 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 e0292bc053..f1893144ce 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 7ccab7ca10..ded73b0025 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 723fda7802..136e615733 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 b8851e5007..6311df6d1e 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 00904a182f..73717180b4 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 9c486685cd..7ded4ad189 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<Delay = If_CutDelay( p, pObj, pCut ); if ( pCut->Delay == -1 ) continue; - if ( Mode && pCut->Delay > pObj->Required + p->fEpsilon ) + if ( Mode && pCut->Delay > pObj->Required + p->fEpsilon && pCutSet->nCuts > 0 ) continue; // compute area of the cut (this area may depend on the application specific cost) pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut ) : If_CutAreaFlow( p, pCut ); @@ -558,7 +558,7 @@ void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fP continue; // check if the cut satisfies the required times // assert( pCut->Delay == If_CutDelay( p, pTemp, pCut ) ); - if ( Mode && pCut->Delay > pObj->Required + p->fEpsilon ) + if ( Mode && pCut->Delay > pObj->Required + p->fEpsilon && pCutSet->nCuts > 0 ) continue; // set the phase attribute pCut->fCompl = pObj->fPhase ^ pTemp->fPhase; diff --git a/src/map/mapper/mapper.h b/src/map/mapper/mapper.h index f0fcea8396..97115f666c 100644 --- a/src/map/mapper/mapper.h +++ b/src/map/mapper/mapper.h @@ -110,11 +110,13 @@ extern void Map_ManSetVerbose( Map_Man_t * p, int fVerbose ); extern void Map_ManSetSwitching( Map_Man_t * p, int fSwitching ); extern void Map_ManSetSkipFanout( Map_Man_t * p, int fSkipFanout ); extern void Map_ManSetUseProfile( Map_Man_t * p ); +extern void Map_ManCreateAigIds( Map_Man_t * p, int nObjs ); extern Map_Man_t * Map_NodeReadMan( Map_Node_t * p ); extern char * Map_NodeReadData( Map_Node_t * p, int fPhase ); extern int Map_NodeReadNum( Map_Node_t * p ); extern int Map_NodeReadLevel( Map_Node_t * p ); +extern int Map_NodeReadAigId( Map_Node_t * p ); extern Map_Cut_t * Map_NodeReadCuts( Map_Node_t * p ); extern Map_Cut_t * Map_NodeReadCutBest( Map_Node_t * p, int fPhase ); extern Map_Node_t * Map_NodeReadOne( Map_Node_t * p ); @@ -123,6 +125,7 @@ extern void Map_NodeSetData( Map_Node_t * p, int fPhase, char * pData extern void Map_NodeSetNextE( Map_Node_t * p, Map_Node_t * pNextE ); extern void Map_NodeSetRepr( Map_Node_t * p, Map_Node_t * pRepr ); extern void Map_NodeSetSwitching( Map_Node_t * p, float Switching ); +extern void Map_NodeSetAigId( Map_Node_t * p, int Id ); extern int Map_NodeIsConst( Map_Node_t * p ); extern int Map_NodeIsVar( Map_Node_t * p ); @@ -167,6 +170,7 @@ extern Map_Cut_t * Map_CutAlloc( Map_Man_t * p ); /*=== mapperCutUtils.c =============================================================*/ extern void Map_CutCreateFromNode( Map_Man_t * p, Map_Super_t * pSuper, int iRoot, unsigned uPhaseRoot, int * pLeaves, int nLeaves, unsigned uPhaseLeaves ); +extern Vec_Ptr_t * Map_CutInternalNodes( Map_Node_t * pObj, Map_Cut_t * pCut ); /*=== mapperCore.c =============================================================*/ extern int Map_Mapping( Map_Man_t * p ); /*=== mapperLib.c =============================================================*/ diff --git a/src/map/mapper/mapperCreate.c b/src/map/mapper/mapperCreate.c index d3e574f34e..4a651991d5 100644 --- a/src/map/mapper/mapperCreate.c +++ b/src/map/mapper/mapperCreate.c @@ -75,6 +75,7 @@ void Map_ManSetVerbose( Map_Man_t * p, int fVerbose ) { p-> 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 aa307368b3..18e5a009ae 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 79c8d61ad0..768255a8af 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 0c33d5800b..049c7cc52d 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 9ca6767db4..cfe5d3e8ce 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 1a072a5028..ce6f0aa9b6 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 ); diff --git a/src/map/mio/mioRead.c b/src/map/mio/mioRead.c index c19c07d4d0..79d5dc4efa 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/scl.c b/src/map/scl/scl.c index 6ddd60944a..9112bcecae 100644 --- a/src/map/scl/scl.c +++ b/src/map/scl/scl.c @@ -185,13 +185,14 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) int fVeryVerbose = 0; int fMerge = 0; int fUsePrefix = 0; + int fUseAll = 0; SC_DontUse dont_use = {0}; dont_use.dont_use_list = ABC_ALLOC(char *, argc); dont_use.size = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "SGMXdnuvwmph" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "SGMXdnuvwmpah" ) ) != EOF ) { switch ( c ) { @@ -259,6 +260,9 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'p': fUsePrefix ^= 1; break; + case 'a': + fUseAll ^= 1; + break; case 'h': goto usage; default: @@ -318,13 +322,13 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) // extract genlib library if ( pAbc->pLibScl ) { - Abc_SclInstallGenlib( pAbc->pLibScl, Slew, Gain, nGatesMin ); + Abc_SclInstallGenlib( pAbc->pLibScl, Slew, Gain, fUseAll, nGatesMin ); Mio_LibraryTransferCellIds(); } return 0; usage: - fprintf( pAbc->Err, "usage: read_lib [-SG float] [-M num] [-dnuvwmph] [-X cell_name] \n" ); + fprintf( pAbc->Err, "usage: read_lib [-SG float] [-M num] [-dnuvwmpah] [-X cell_name] \n" ); fprintf( pAbc->Err, "\t reads Liberty library from file\n" ); fprintf( pAbc->Err, "\t-S float : the slew parameter used to generate the library [default = %.2f]\n", Slew ); fprintf( pAbc->Err, "\t-G float : the gain parameter used to generate the library [default = %.2f]\n", Gain ); @@ -336,6 +340,7 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pAbc->Err, "\t-v : toggle writing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-w : toggle writing information about skipped gates [default = %s]\n", fVeryVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-m : toggle merging library with exisiting library [default = %s]\n", fMerge? "yes": "no" ); + fprintf( pAbc->Err, "\t-a : toggle using prefix for the cell names [default = %s]\n", fUseAll? "yes": "no" ); fprintf( pAbc->Err, "\t-p : toggle using prefix for the cell names [default = %s]\n", fUsePrefix? "yes": "no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\t : the name of a file to read\n" ); @@ -606,7 +611,7 @@ int Scl_CommandReadScl( Abc_Frame_t * pAbc, int argc, char ** argv ) // extract genlib library if ( pAbc->pLibScl ) { - Abc_SclInstallGenlib( pAbc->pLibScl, 0, 0, 0 ); + Abc_SclInstallGenlib( pAbc->pLibScl, 0, 0, 0, 0 ); Mio_LibraryTransferCellIds(); } return 0; diff --git a/src/map/scl/sclBufSize.c b/src/map/scl/sclBufSize.c index 4d438af094..9f4e078853 100644 --- a/src/map/scl/sclBufSize.c +++ b/src/map/scl/sclBufSize.c @@ -345,7 +345,7 @@ Abc_Obj_t * Abc_SclAddOneInv( Bus_Man_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vFano SC_Cell * pCellNew; Abc_Obj_t * pFanout, * pInv; float Target = SC_CellPinCap(p->pInv, 0) * Gain; - float LoadWirePrev, LoadWireThis, LoadNew, Load = 0; + float LoadWirePrev, LoadWireThis, Load = 0; int Limit = Abc_MinInt( p->pPars->nDegree, Vec_PtrSize(vFanouts) ); int i, iStop; Bus_SclCheckSortedFanout( vFanouts ); @@ -384,8 +384,7 @@ Abc_Obj_t * Abc_SclAddOneInv( Bus_Man_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vFano Vec_IntSetEntry( p->pNtk->vGates, Abc_ObjId(pInv), pCellNew->Id ); // set departure and load Abc_NtkComputeNodeDeparture( pInv, p->pPars->Slew ); - LoadNew = Abc_NtkComputeNodeLoad( p, pInv ); - assert( LoadNew - Load < 1 && Load - LoadNew < 1 ); + Abc_NtkComputeNodeLoad( p, pInv ); // set fanout info for the inverter Bus_SclObjSetCin( pInv, SC_CellPinCap(pCellNew, 0) ); Bus_SclObjSetETime( pInv, Abc_NtkComputeEdgeDept(pInv, 0, p->pPars->Slew) ); @@ -400,7 +399,7 @@ void Abc_SclBufSize( Bus_Man_t * p, float Gain ) Abc_Obj_t * pObj, * pFanout; abctime clk = Abc_Clock(); int i, k, nObjsOld = Abc_NtkObjNumMax(p->pNtk); - float GainGate, GainInv, Load, LoadNew, Cin, DeptMax = 0; + float GainGate, GainInv, Load, Cin, DeptMax = 0; GainGate = p->pPars->fAddBufs ? (float)pow( (double)Gain, (double)2.0 ) : Gain; GainInv = p->pPars->fAddBufs ? (float)pow( (double)Gain, (double)2.0 ) : Gain; Abc_NtkForEachObjReverse( p->pNtk, pObj, i ) @@ -453,8 +452,7 @@ void Abc_SclBufSize( Bus_Man_t * p, float Gain ) if ( Abc_ObjFaninNum(pFanout) == 0 ) Abc_ObjAddFanin( pFanout, pObj ); Bus_SclObjSetLoad( pObj, 0 ); - LoadNew = Abc_NtkComputeNodeLoad( p, pObj ); - assert( LoadNew - Load < 1 && Load - LoadNew < 1 ); + Abc_NtkComputeNodeLoad( p, pObj ); } if ( Abc_ObjIsCi(pObj) ) continue; diff --git a/src/map/scl/sclLib.h b/src/map/scl/sclLib.h index c08f30c09c..2b616a20d2 100644 --- a/src/map/scl/sclLib.h +++ b/src/map/scl/sclLib.h @@ -766,7 +766,7 @@ extern SC_WireLoad * Abc_SclFetchWireLoadModel( SC_Lib * p, char * pName ); extern int Abc_SclHasDelayInfo( void * pScl ); extern float Abc_SclComputeAverageSlew( SC_Lib * p ); extern void Abc_SclDumpGenlib( char * pFileName, SC_Lib * p, float Slew, float Gain, int nGatesMin ); -extern void Abc_SclInstallGenlib( void * pScl, float Slew, float Gain, int nGatesMin ); +extern void Abc_SclInstallGenlib( void * pScl, float Slew, float Gain, int fUseAll, int nGatesMin ); ABC_NAMESPACE_HEADER_END diff --git a/src/map/scl/sclLibUtil.c b/src/map/scl/sclLibUtil.c index 9624be93e5..88e8e514ee 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) ); @@ -867,13 +867,13 @@ Mio_Library_t * Abc_SclDeriveGenlibSimple( void * pScl ) SeeAlso [] ***********************************************************************/ -Vec_Str_t * Abc_SclProduceGenlibStr( SC_Lib * p, float Slew, float Gain, int nGatesMin, int * pnCellCount ) +Vec_Str_t * Abc_SclProduceGenlibStr( SC_Lib * p, float Slew, float Gain, int nGatesMin, int fUseAll, int * pnCellCount ) { char Buffer[200]; Vec_Str_t * vStr; SC_Cell * pRepr; - SC_Pin * pPin; - int i, k, Count = 2, nClassMax = 0; + SC_Pin * pPin, * pPinOut; + int i, j, k, Count = 2, nClassMax = 0; // find the largest number of cells in a class SC_LibForEachCellClass( p, pRepr, i ) if ( pRepr->n_outputs == 1 ) @@ -886,38 +886,80 @@ Vec_Str_t * Abc_SclProduceGenlibStr( SC_Lib * p, float Slew, float Gain, int nGa vStr = Vec_StrAlloc( 1000 ); Vec_StrPrintStr( vStr, "GATE _const0_ 0.00 z=CONST0;\n" ); Vec_StrPrintStr( vStr, "GATE _const1_ 0.00 z=CONST1;\n" ); - SC_LibForEachCellClass( p, pRepr, i ) + if ( fUseAll ) { - if ( pRepr->n_inputs == 0 ) - continue; - if ( pRepr->n_outputs > 1 ) - continue; - if ( nGatesMin && pRepr->n_inputs > 2 && Abc_SclClassCellNum(pRepr) < nGatesMin ) - continue; - assert( strlen(pRepr->pName) < 200 ); - Vec_StrPrintStr( vStr, "GATE " ); - sprintf( Buffer, "%-16s", pRepr->pName ); - Vec_StrPrintStr( vStr, Buffer ); - Vec_StrPrintStr( vStr, " " ); -// sprintf( Buffer, "%7.2f", Abc_SclComputeAreaClass(pRepr) ); - sprintf( Buffer, "%7.2f", pRepr->area ); - Vec_StrPrintStr( vStr, Buffer ); - Vec_StrPrintStr( vStr, " " ); - Vec_StrPrintStr( vStr, SC_CellPinName(pRepr, pRepr->n_inputs) ); - Vec_StrPrintStr( vStr, "=" ); - Vec_StrPrintStr( vStr, SC_CellPinOutFunc(pRepr, 0) ? SC_CellPinOutFunc(pRepr, 0) : "?" ); - Vec_StrPrintStr( vStr, ";\n" ); - SC_CellForEachPinIn( pRepr, pPin, k ) + SC_LibForEachCell( p, pRepr, i ) { - float Delay = Abc_SclComputeDelayClassPin( p, pRepr, k, Slew, Gain ); - assert( Delay > 0 ); - Vec_StrPrintStr( vStr, " PIN " ); - sprintf( Buffer, "%-4s", pPin->pName ); + if ( pRepr->n_inputs == 0 ) + continue; + //if ( pRepr->n_outputs > 1 ) + // continue; + if ( nGatesMin && pRepr->n_inputs > 2 && Abc_SclClassCellNum(pRepr) < nGatesMin ) + continue; + SC_CellForEachPinOut( pRepr, pPinOut, j ) + { + assert( strlen(pRepr->pName) < 200 ); + Vec_StrPrintStr( vStr, "GATE " ); + sprintf( Buffer, "%-16s", pRepr->pName ); + Vec_StrPrintStr( vStr, Buffer ); + Vec_StrPrintStr( vStr, " " ); + // sprintf( Buffer, "%7.2f", Abc_SclComputeAreaClass(pRepr) ); + sprintf( Buffer, "%7.2f", pRepr->area ); + Vec_StrPrintStr( vStr, Buffer ); + Vec_StrPrintStr( vStr, " " ); + Vec_StrPrintStr( vStr, SC_CellPinName(pRepr, j) ); + Vec_StrPrintStr( vStr, "=" ); + Vec_StrPrintStr( vStr, SC_CellPinOutFunc(pRepr, j-pRepr->n_inputs) ? SC_CellPinOutFunc(pRepr, j-pRepr->n_inputs) : "?" ); + Vec_StrPrintStr( vStr, ";\n" ); + SC_CellForEachPinIn( pRepr, pPin, k ) + { + float Delay = Abc_SclComputeDelayClassPin( p, pRepr, k, Slew, Gain ); + assert( Delay > 0 ); + Vec_StrPrintStr( vStr, " PIN " ); + sprintf( Buffer, "%-4s", pPin->pName ); + Vec_StrPrintStr( vStr, Buffer ); + sprintf( Buffer, " UNKNOWN 1 999 %7.2f 0.00 %7.2f 0.00\n", Delay, Delay ); + Vec_StrPrintStr( vStr, Buffer ); + } + Count++; + } + } + } + else + { + SC_LibForEachCellClass( p, pRepr, i ) + { + if ( pRepr->n_inputs == 0 ) + continue; + if ( pRepr->n_outputs > 1 ) + continue; + if ( nGatesMin && pRepr->n_inputs > 2 && Abc_SclClassCellNum(pRepr) < nGatesMin ) + continue; + assert( strlen(pRepr->pName) < 200 ); + Vec_StrPrintStr( vStr, "GATE " ); + sprintf( Buffer, "%-16s", pRepr->pName ); Vec_StrPrintStr( vStr, Buffer ); - sprintf( Buffer, " UNKNOWN 1 999 %7.2f 0.00 %7.2f 0.00\n", Delay, Delay ); + Vec_StrPrintStr( vStr, " " ); + // sprintf( Buffer, "%7.2f", Abc_SclComputeAreaClass(pRepr) ); + sprintf( Buffer, "%7.2f", pRepr->area ); Vec_StrPrintStr( vStr, Buffer ); + Vec_StrPrintStr( vStr, " " ); + Vec_StrPrintStr( vStr, SC_CellPinName(pRepr, pRepr->n_inputs) ); + Vec_StrPrintStr( vStr, "=" ); + Vec_StrPrintStr( vStr, SC_CellPinOutFunc(pRepr, 0) ? SC_CellPinOutFunc(pRepr, 0) : "?" ); + Vec_StrPrintStr( vStr, ";\n" ); + SC_CellForEachPinIn( pRepr, pPin, k ) + { + float Delay = Abc_SclComputeDelayClassPin( p, pRepr, k, Slew, Gain ); + assert( Delay > 0 ); + Vec_StrPrintStr( vStr, " PIN " ); + sprintf( Buffer, "%-4s", pPin->pName ); + Vec_StrPrintStr( vStr, Buffer ); + sprintf( Buffer, " UNKNOWN 1 999 %7.2f 0.00 %7.2f 0.00\n", Delay, Delay ); + Vec_StrPrintStr( vStr, Buffer ); + } + Count++; } - Count++; } Vec_StrPrintStr( vStr, "\n.end\n" ); Vec_StrPush( vStr, '\0' ); @@ -1012,7 +1054,7 @@ void Abc_SclDumpGenlib( char * pFileName, SC_Lib * p, float SlewInit, float Gain printf( "Cannot open file \"%s\" for writing.\n", FileName ); return; } - vStr = Abc_SclProduceGenlibStr( p, Slew, Gain, nGatesMin, &nCellCount ); + vStr = Abc_SclProduceGenlibStr( p, Slew, Gain, nGatesMin, 0, &nCellCount ); fprintf( pFile, "%s", Vec_StrArray(vStr) ); Vec_StrFree( vStr ); fclose( pFile ); @@ -1026,10 +1068,10 @@ Mio_Library_t * Abc_SclDeriveGenlib( void * pScl, void * pMio, float SlewInit, f Vec_Str_t * vStr; Mio_Library_t * pLib; if ( pMio == NULL ) - vStr = Abc_SclProduceGenlibStr( p, Slew, Gain, nGatesMin, &nCellCount ); + vStr = Abc_SclProduceGenlibStr( p, Slew, Gain, nGatesMin, 0, &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" ); @@ -1049,7 +1091,7 @@ Mio_Library_t * Abc_SclDeriveGenlib( void * pScl, void * pMio, float SlewInit, f SeeAlso [] ***********************************************************************/ -void Abc_SclInstallGenlib( void * pScl, float SlewInit, float Gain, int nGatesMin ) +void Abc_SclInstallGenlib( void * pScl, float SlewInit, float Gain, int fUseAll, int nGatesMin ) { SC_Lib * p = (SC_Lib *)pScl; Vec_Str_t * vStr, * vStr2; @@ -1058,7 +1100,7 @@ void Abc_SclInstallGenlib( void * pScl, float SlewInit, float Gain, int nGatesMi if ( Gain == 0 ) vStr = Abc_SclProduceGenlibStrSimple(p); else - vStr = Abc_SclProduceGenlibStr( p, Slew, Gain, nGatesMin, &nGateCount ); + vStr = Abc_SclProduceGenlibStr( p, Slew, Gain, nGatesMin, fUseAll, &nGateCount ); vStr2 = Vec_StrDup( vStr ); RetValue = Mio_UpdateGenlib2( vStr, vStr2, p->pName, 0 ); Vec_StrFree( vStr ); diff --git a/src/map/scl/sclLiberty.c b/src/map/scl/sclLiberty.c index d853f557bf..707a8c5851 100644 --- a/src/map/scl/sclLiberty.c +++ b/src/map/scl/sclLiberty.c @@ -49,20 +49,20 @@ typedef enum { typedef struct Scl_Pair_t_ Scl_Pair_t; struct Scl_Pair_t_ { - int Beg; // item beginning - int End; // item end + long Beg; // item beginning + long End; // item end }; typedef struct Scl_Item_t_ Scl_Item_t; struct Scl_Item_t_ { int Type; // Scl_LibertyType_t - int iLine; // file line where the item's spec begins + long iLine; // file line where the item's spec begins Scl_Pair_t Key; // key part Scl_Pair_t Head; // head part Scl_Pair_t Body; // body part - int Next; // next item in the list - int Child; // first child item + long Next; // next item in the list + long Child; // first child item }; typedef struct Scl_Tree_t_ Scl_Tree_t; @@ -71,9 +71,9 @@ struct Scl_Tree_t_ char * pFileName; // input Liberty file name char * pContents; // file contents long nContents; // file size - int nLines; // line counter - int nItems; // number of items - int nItermAlloc; // number of items allocated + long nLines; // line counter + long nItems; // number of items + long nItermAlloc; // number of items allocated Scl_Item_t * pItems; // the items char * pError; // the error string abctime clkStart; // beginning time @@ -89,11 +89,11 @@ static inline int Scl_LibertyGlobMatch(const char * pattern, const char #endif } static inline Scl_Item_t * Scl_LibertyRoot( Scl_Tree_t * p ) { return p->pItems; } -static inline Scl_Item_t * Scl_LibertyItem( Scl_Tree_t * p, int v ) { assert( v < p->nItems ); return v < 0 ? NULL : p->pItems + v; } -static inline int Scl_LibertyCompare( Scl_Tree_t * p, Scl_Pair_t Pair, char * pStr ) { return strncmp( p->pContents+Pair.Beg, pStr, Pair.End-Pair.Beg ) || ((int)strlen(pStr) != Pair.End-Pair.Beg); } +static inline Scl_Item_t * Scl_LibertyItem( Scl_Tree_t * p, long v ) { assert( v < p->nItems ); return v < 0 ? NULL : p->pItems + v; } +static inline long Scl_LibertyCompare( Scl_Tree_t * p, Scl_Pair_t Pair, char * pStr ) { return strncmp( p->pContents+Pair.Beg, pStr, Pair.End-Pair.Beg ) || ((long)strlen(pStr) != Pair.End-Pair.Beg); } static inline void Scl_PrintWord( FILE * pFile, Scl_Tree_t * p, Scl_Pair_t Pair ) { char * pBeg = p->pContents+Pair.Beg, * pEnd = p->pContents+Pair.End; while ( pBeg < pEnd ) fputc( *pBeg++, pFile ); } -static inline void Scl_PrintSpace( FILE * pFile, int nOffset ) { int i; for ( i = 0; i < nOffset; i++ ) fputc(' ', pFile); } -static inline int Scl_LibertyItemId( Scl_Tree_t * p, Scl_Item_t * pItem ) { return pItem - p->pItems; } +static inline void Scl_PrintSpace( FILE * pFile, long nOffset ) { long i; for ( i = 0; i < nOffset; i++ ) fputc(' ', pFile); } +static inline long Scl_LibertyItemId( Scl_Tree_t * p, Scl_Item_t * pItem ) { return pItem - p->pItems; } #define Scl_ItemForEachChild( p, pItem, pChild ) \ for ( pChild = Scl_LibertyItem(p, pItem->Child); pChild; pChild = Scl_LibertyItem(p, pChild->Next) ) @@ -181,9 +181,9 @@ int Scl_LibertyParseDump( Scl_Tree_t * p, char * pFileName ) SeeAlso [] ***********************************************************************/ -int Scl_LibertyCountItems( char * pBeg, char * pEnd ) +long Scl_LibertyCountItems( char * pBeg, char * pEnd ) { - int Counter = 0; + long Counter = 0; for ( ; pBeg < pEnd; pBeg++ ) Counter += (*pBeg == '(' || *pBeg == ':'); return Counter; @@ -228,11 +228,11 @@ void Scl_LibertyWipeOutComments( char * pBeg, char * pEnd ) } } } -static inline int Scl_LibertyCharIsSpace( char c ) +static inline long Scl_LibertyCharIsSpace( char c ) { return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\\'; } -static inline int Scl_LibertySkipSpaces( Scl_Tree_t * p, char ** ppPos, char * pEnd, int fStopAtNewLine ) +static inline long Scl_LibertySkipSpaces( Scl_Tree_t * p, char ** ppPos, char * pEnd, int fStopAtNewLine ) { char * pPos = *ppPos; for ( ; pPos < pEnd; pPos++ ) @@ -250,7 +250,7 @@ static inline int Scl_LibertySkipSpaces( Scl_Tree_t * p, char ** ppPos, char * p return pPos == pEnd; } // skips entry delimited by " :;(){}" and returns 1 if reached the end -static inline int Scl_LibertySkipEntry( char ** ppPos, char * pEnd ) +static inline long Scl_LibertySkipEntry( char ** ppPos, char * pEnd ) { char * pPos = *ppPos; if ( *pPos == '\"' ) @@ -277,7 +277,7 @@ static inline int Scl_LibertySkipEntry( char ** ppPos, char * pEnd ) // finds the matching closing symbol static inline char * Scl_LibertyFindMatch( char * pPos, char * pEnd ) { - int Counter = 0; + long Counter = 0; assert( *pPos == '(' || *pPos == '{' ); if ( *pPos == '(' ) { @@ -387,10 +387,10 @@ char * Scl_LibertyReadString( Scl_Tree_t * p, Scl_Pair_t Pair ) Buffer[Pair.End-Pair.Beg] = 0; return Buffer; } -int Scl_LibertyItemNum( Scl_Tree_t * p, Scl_Item_t * pRoot, char * pName ) +long Scl_LibertyItemNum( Scl_Tree_t * p, Scl_Item_t * pRoot, char * pName ) { Scl_Item_t * pItem; - int Counter = 0; + long Counter = 0; Scl_ItemForEachChildName( p, pRoot, pItem, pName ) Counter++; return Counter; @@ -407,7 +407,7 @@ int Scl_LibertyItemNum( Scl_Tree_t * p, Scl_Item_t * pRoot, char * pName ) SeeAlso [] ***********************************************************************/ -int Scl_LibertyBuildItem( Scl_Tree_t * p, char ** ppPos, char * pEnd ) +long Scl_LibertyBuildItem( Scl_Tree_t * p, char ** ppPos, char * pEnd ) { Scl_Item_t * pItem; Scl_Pair_t Key, Head, Body; @@ -513,7 +513,7 @@ int Scl_LibertyBuildItem( Scl_Tree_t * p, char ** ppPos, char * pEnd ) if ( p->pError == NULL ) { p->pError = ABC_ALLOC( char, 1000 ); - sprintf( p->pError, "File \"%s\". Line %6d. Failed to parse entry \"%s\".\n", + sprintf( p->pError, "File \"%s\". Line %6ld. Failed to parse entry \"%s\".\n", p->pFileName, p->nLines, Scl_LibertyReadString(p, Key) ); } return -1; @@ -556,7 +556,7 @@ char * Scl_LibertyFileContents( char * pFileName, long nContents ) { FILE * pFile = fopen( pFileName, "rb" ); char * pContents = ABC_ALLOC( char, nContents+1 ); - int RetValue = 0; + long RetValue = 0; RetValue = fread( pContents, nContents, 1, pFile ); fclose( pFile ); pContents[nContents] = 0; @@ -565,7 +565,7 @@ char * Scl_LibertyFileContents( char * pFileName, long nContents ) void Scl_LibertyStringDump( char * pFileName, Vec_Str_t * vStr ) { FILE * pFile = fopen( pFileName, "wb" ); - int RetValue = 0; + long RetValue = 0; if ( pFile == NULL ) { printf( "Scl_LibertyStringDump(): The output file is unavailable.\n" ); @@ -721,10 +721,10 @@ int Scl_LibertyReadCellIsThreeState( Scl_Tree_t * p, Scl_Item_t * pCell ) return 1; return 0; } -int Scl_LibertyReadCellOutputNum( Scl_Tree_t * p, Scl_Item_t * pCell ) +long Scl_LibertyReadCellOutputNum( Scl_Tree_t * p, Scl_Item_t * pCell ) { Scl_Item_t * pPin; - int Counter = 0; + long Counter = 0; Scl_ItemForEachChildName( p, pCell, pPin, "pin" ) if ( Scl_LibertyReadPinFormula(p, pPin) ) Counter++; diff --git a/src/map/super/super.c b/src/map/super/super.c index 7868ba78e6..21b1938451 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/bbl/bblif.h b/src/misc/bbl/bblif.h index b485937017..af6025da3b 100644 --- a/src/misc/bbl/bblif.h +++ b/src/misc/bbl/bblif.h @@ -237,7 +237,7 @@ extern void Bbl_ManDumpBinaryBlif( Bbl_Man_t * p, char * pFileName ); // (3) reading the data manager from file extern Bbl_Man_t * Bbl_ManReadBinaryBlif( char * pFileName ); -// (4) returning the mapped network after reading the data manaager from file +// (4) returning the mapped network after reading the data manager from file extern char * Bbl_ManName( Bbl_Man_t * p ); extern int Bbl_ObjIsInput( Bbl_Obj_t * p ); extern int Bbl_ObjIsOutput( Bbl_Obj_t * p ); diff --git a/src/misc/extra/extraUtilFile.c b/src/misc/extra/extraUtilFile.c index 54e6efc259..6585b7a729 100644 --- a/src/misc/extra/extraUtilFile.c +++ b/src/misc/extra/extraUtilFile.c @@ -18,6 +18,13 @@ ***********************************************************************/ +#ifdef WIN32 +#include +#define PATH_MAX MAX_PATH +#else +#include +#endif + #include "extra.h" ABC_NAMESPACE_IMPL_START @@ -184,9 +191,9 @@ char * Extra_FileNameGeneric( char * FileName ) ***********************************************************************/ char * Extra_FileNameGenericAppend( char * pBase, char * pSuffix ) { - static char Buffer[1000]; + static char Buffer[PATH_MAX]; char * pDot; - assert( strlen(pBase) + strlen(pSuffix) < 1000 ); + assert( strlen(pBase) + strlen(pSuffix) < PATH_MAX ); strcpy( Buffer, pBase ); if ( (pDot = strrchr( Buffer, '.' )) ) *pDot = 0; diff --git a/src/misc/util/abc_global.h b/src/misc/util/abc_global.h index fefbd67c7e..4354984004 100644 --- a/src/misc/util/abc_global.h +++ b/src/misc/util/abc_global.h @@ -287,6 +287,9 @@ static inline double Abc_Word2Dbl( word Num ) { union { word x; static inline int Abc_Base2Log( unsigned n ) { int r; if ( n < 2 ) return (int)n; for ( r = 0, n--; n; n >>= 1, r++ ) {}; return r; } static inline int Abc_Base10Log( unsigned n ) { int r; if ( n < 2 ) return (int)n; for ( r = 0, n--; n; n /= 10, r++ ) {}; return r; } static inline int Abc_Base16Log( unsigned n ) { int r; if ( n < 2 ) return (int)n; for ( r = 0, n--; n; n /= 16, r++ ) {}; return r; } +static inline int Abc_Base2LogW( word n ) { int r; if ( n < 2 ) return (int)n; for ( r = 0, n--; n; n >>= 1, r++ ) {}; return r; } +static inline int Abc_Base10LogW( word n ) { int r; if ( n < 2 ) return (int)n; for ( r = 0, n--; n; n /= 10, r++ ) {}; return r; } +static inline int Abc_Base16LogW( word n ) { int r; if ( n < 2 ) return (int)n; for ( r = 0, n--; n; n /= 16, r++ ) {}; return r; } static inline char * Abc_UtilStrsav( char * s ) { return s ? strcpy(ABC_ALLOC(char, strlen(s)+1), s) : NULL; } static inline char * Abc_UtilStrsavTwo( char * s, char * a ){ char * r; if (!a) return Abc_UtilStrsav(s); r = ABC_ALLOC(char, strlen(s)+strlen(a)+1); sprintf(r, "%s%s", s, a ); return r; } static inline char * Abc_UtilStrsavNum( char * s, int n ) { char * r; if (!s) return NULL; r = ABC_ALLOC(char, strlen(s)+12+1); sprintf(r, "%s%d", s, n ); return r; } @@ -334,7 +337,7 @@ static inline abctime Abc_Clock() #else #define APPLE_MACH 0 #endif -#if (defined(LIN) || defined(LIN64)) && !APPLE_MACH && !defined(__MINGW32__) +#if (defined(LIN) || defined(LIN64)) && !APPLE_MACH && !defined(__MINGW32__) && !defined(__wasm) struct timespec ts; if ( clock_gettime(CLOCK_MONOTONIC, &ts) < 0 ) return (abctime)-1; @@ -353,7 +356,7 @@ static inline abctime Abc_ThreadClock() #else #define APPLE_MACH 0 #endif -#if (defined(LIN) || defined(LIN64)) && !APPLE_MACH && !defined(__MINGW32__) +#if (defined(LIN) || defined(LIN64)) && !APPLE_MACH && !defined(__MINGW32__) && !defined(__wasm) struct timespec ts; if ( clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) < 0 ) return (abctime)-1; @@ -548,6 +551,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 5b3601bbb6..66e87653fb 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/utilFile.c b/src/misc/util/utilFile.c index 4bb2f4c68a..f64d71c24a 100644 --- a/src/misc/util/utilFile.c +++ b/src/misc/util/utilFile.c @@ -25,6 +25,23 @@ #include #include +// Handle legacy macros +#if !defined(S_IREAD) +#if defined(S_IRUSR) +#define S_IREAD S_IRUSR +#else +#error S_IREAD is undefined +#endif +#endif + +#if !defined(S_IWRITE) +#if defined(S_IWUSR) +#define S_IWRITE S_IWUSR +#else +#error S_IWRITE is undefined +#endif +#endif + #if defined(_MSC_VER) || defined(__MINGW32__) #include #include @@ -102,6 +119,17 @@ int tmpFile(const char* prefix, const char* suffix, char** out_name) } assert(0); // -- could not open temporary file return 0; +#elif defined(__wasm) + static int seq = 0; // no risk of collision since we're in a sandbox + int fd; + *out_name = (char*)malloc(strlen(prefix) + strlen(suffix) + 9); + sprintf(*out_name, "%s%08d%s", prefix, seq++, suffix); + fd = open(*out_name, O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE); + if (fd == -1){ + free(*out_name); + *out_name = NULL; + } + return fd; #else int fd; *out_name = (char*)malloc(strlen(prefix) + strlen(suffix) + 7); diff --git a/src/misc/util/utilPth.c b/src/misc/util/utilPth.c new file mode 100644 index 0000000000..aeb9125971 --- /dev/null +++ b/src/misc/util/utilPth.c @@ -0,0 +1,192 @@ +/**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 +#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, false, 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, false, 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, true, 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, true, 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/utilSignal.c b/src/misc/util/utilSignal.c index 03af81d13d..137ff54b81 100644 --- a/src/misc/util/utilSignal.c +++ b/src/misc/util/utilSignal.c @@ -43,7 +43,11 @@ ABC_NAMESPACE_IMPL_START int Util_SignalSystem(const char* cmd) { +#if defined(__wasm) + return -1; +#else return system(cmd); +#endif } int tmpFile(const char* prefix, const char* suffix, char** out_name); diff --git a/src/misc/util/utilSort.c b/src/misc/util/utilSort.c index a748caf95a..0bbd7d2896 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 2624f94639..323c96467a 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 /// @@ -231,6 +225,33 @@ static inline void Abc_TtMask( word * pTruth, int nWords, int nBits ) pTruth[w] = 0; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline word Abc_TtWordReverseBits( word w ) +{ + int Rev[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15}; + word r = 0; int i; + for ( i = 0; i < 16; i++ ) + r |= (word)Rev[(w >> (i<<2))&15] << ((15-i)<<2); + return r; +} +static inline word Abc_TtWordReverseHexDigits( word w ) +{ + word r = 0; int i; + for ( i = 0; i < 16; i++ ) + r |= ((w >> (i<<2))&15) << ((15-i)<<2); + return r; +} + /**Function************************************************************* Synopsis [] diff --git a/src/misc/vec/vecInt.h b/src/misc/vec/vecInt.h index e4ea6cfe33..0b1ae6d300 100644 --- a/src/misc/vec/vecInt.h +++ b/src/misc/vec/vecInt.h @@ -65,6 +65,8 @@ struct Vec_Int_t_ for ( i = Start; (i >= 0) && (((pEntry) = Vec_IntEntry(vVec, i)), 1); i-- ) #define Vec_IntForEachEntryTwo( vVec1, vVec2, Entry1, Entry2, i ) \ for ( i = 0; (i < Vec_IntSize(vVec1)) && (((Entry1) = Vec_IntEntry(vVec1, i)), 1) && (((Entry2) = Vec_IntEntry(vVec2, i)), 1); i++ ) +#define Vec_IntForEachEntryThree( vVec1, vVec2, vVec3, Entry1, Entry2, Entry3, i ) \ + for ( i = 0; (i < Vec_IntSize(vVec1)) && (((Entry1) = Vec_IntEntry(vVec1, i)), 1) && (((Entry2) = Vec_IntEntry(vVec2, i)), 1) && (((Entry3) = Vec_IntEntry(vVec3, i)), 1); i++ ) #define Vec_IntForEachEntryTwoStart( vVec1, vVec2, Entry1, Entry2, i, Start ) \ for ( i = Start; (i < Vec_IntSize(vVec1)) && (((Entry1) = Vec_IntEntry(vVec1, i)), 1) && (((Entry2) = Vec_IntEntry(vVec2, i)), 1); i++ ) #define Vec_IntForEachEntryDouble( vVec, Entry1, Entry2, i ) \ diff --git a/src/misc/vec/vecWrd.h b/src/misc/vec/vecWrd.h index b0d16efe67..5bfee43fb7 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 dd954d9a7b..bd97c280c0 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 2b9e1915d0..a654695c59 100644 --- a/src/opt/dau/dauNpn.c +++ b/src/opt/dau/dauNpn.c @@ -800,6 +800,187 @@ 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; +} + +/**Function************************************************************* + + Synopsis [Compute NPN class members.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Mem_t * Dau_CollectNpnFunctionsArray( Vec_Wrd_t * vFuncs, int nVars, Vec_Int_t ** pvMap, int fVerbose ) +{ + assert( nVars <= 10 ); + abctime clkStart = Abc_Clock(); + Vec_Int_t * vMap = Vec_IntAlloc( 100 ); + Vec_Int_t * vCnts = Vec_IntAlloc( Vec_WrdSize(vFuncs) ); + Vec_Mem_t * vTtMem = Vec_MemAllocForTTSimple( nVars ); + int nWords = Abc_Truth6WordNum(nVars); + int nPerms = Extra_Factorial( nVars ); + int nMints = 1 << nVars; + int * pPerm = Extra_PermSchedule( nVars ); + int * pComp = Extra_GreyCodeSchedule( nVars ); + int m, i, k, t, Entry; + word * pCopy = ABC_ALLOC( word, nWords ); + int nClasses = Vec_WrdSize(vFuncs) / nWords; + assert( nClasses * nWords == Vec_WrdSize(vFuncs) ); + for ( t = 0; t < nClasses; t++ ) + { + word * pTruth = Vec_WrdEntryP( vFuncs, nWords * t ); + int nFuncs = Vec_MemEntryNum(vTtMem); + Abc_TtCopy( pCopy, pTruth, nWords, pTruth[0] & 1 ); + Vec_MemHashInsert( vTtMem, pCopy ); + 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 ); + } + if ( pTruth[0] & 1 ) + assert( Abc_TtOpposite(pCopy, pTruth, nWords) ); + else + assert( Abc_TtEqual(pCopy, pTruth, nWords) ); + int nFuncs2 = Vec_MemEntryNum(vTtMem); + for ( i = nFuncs; i < nFuncs2; 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) ); + } + for ( i = nFuncs; i < Vec_MemEntryNum(vTtMem); i++ ) + Vec_IntPush( vMap, t ); + Vec_IntPush( vCnts, Vec_MemEntryNum(vTtMem) - nFuncs ); + } + ABC_FREE( pCopy ); + ABC_FREE( pPerm ); + ABC_FREE( pComp ); + if ( fVerbose ) { + int Lim = Abc_MinInt( Vec_IntSize(vCnts), 7 ); + printf( "Collected %d", Vec_MemEntryNum(vTtMem) ); + Vec_IntForEachEntryStop( vCnts, Entry, i, Lim ) + printf( " %c %d", i ? '+' : '=', Entry ); + if ( Vec_IntSize(vCnts) > Lim ) + printf( " + ..." ); + printf( " NPN class members. " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + fflush(stdout); + } + Vec_IntFree( vCnts ); + if ( pvMap ) + *pvMap = vMap; + else + Vec_IntFree( vMap ); + return vTtMem; +} + +/**Function************************************************************* + + Synopsis [Canonicize a set of functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dau_CanonicizeArray( Vec_Wrd_t * vFuncs, int nVars, int fVerbose ) +{ + abctime clkStart = Abc_Clock(); + extern unsigned Abc_TtCanonicizeCA(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int iThres); + if ( fVerbose ) printf( "Functions: %d (original) ", Vec_WrdSize(vFuncs) ); + unsigned uCanonPhase; char pCanonPerm[16]; word Func; int i; + Vec_WrdUniqify( vFuncs ); + + if ( fVerbose ) printf( "-> %d (unique) ", Vec_WrdSize(vFuncs) ); + Vec_WrdForEachEntry( vFuncs, Func, i ) { + uCanonPhase = Abc_TtCanonicize( &Func, nVars, pCanonPerm ); + Vec_WrdWriteEntry( vFuncs, i, Func ); + } + Vec_WrdUniqify( vFuncs ); + if ( fVerbose ) printf( "-> %d (approx NPN) ", Vec_WrdSize(vFuncs) ); + Abc_TtHieMan_t * pMan = Abc_TtHieManStart(nVars, 5); + Vec_WrdForEachEntry( vFuncs, Func, i ) { + uCanonPhase = Abc_TtCanonicizeWrap(Abc_TtCanonicizeCA, pMan, &Func, nVars, pCanonPerm, 1); + Vec_WrdWriteEntry( vFuncs, i, Func ); + } + Vec_WrdUniqify( vFuncs ); + if ( fVerbose ) printf( "-> %d (exact NPN). ", Vec_WrdSize(vFuncs) ); + Abc_TtHieManStop(pMan); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + fflush( stdout ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/opt/fxu/fxuReduce.c b/src/opt/fxu/fxuReduce.c index 84e2bf87a1..6e5dd0fed4 100644 --- a/src/opt/fxu/fxuReduce.c +++ b/src/opt/fxu/fxuReduce.c @@ -84,6 +84,8 @@ int Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTota nBitsMax = nFanins; } assert( iPair == nPairsTotal ); + if ( nBitsMax == -1 ) + nBitsMax = 0; // allocate storage for counters of cube pairs by difference pnPairCounters = ABC_CALLOC( int, 2 * nBitsMax ); diff --git a/src/opt/lpk/lpkCore.c b/src/opt/lpk/lpkCore.c index cc6087e89b..58de15e887 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/cecCorr.c b/src/proof/cec/cecCorr.c index d1d8958fc7..8d4c730a18 100644 --- a/src/proof/cec/cecCorr.c +++ b/src/proof/cec/cecCorr.c @@ -1269,6 +1269,179 @@ 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 ) { + Gia_ManIncrementTravId( p ); + for ( k = 0, Temp = Spot; Vec_IntEntry(vNexts, Temp) >= 0; k++, Temp = Vec_IntEntry(vNexts, Temp) ) { + if ( Gia_ObjUpdateTravIdCurrentId(p, Temp) ) + break; + Vec_IntWriteEntry( vAvail, Temp, 1 ); + } + if ( k > 100 ) + { + nItems++; + if ( vRes == NULL ) + vRes = Vec_IntAlloc( 100 ); + Gia_ManIncrementTravId( p ); + for ( k = 0, Temp = Spot; Vec_IntEntry(vNexts, Temp) >= 0; k++, Temp = Vec_IntEntry(vNexts, Temp) ) { + if ( Gia_ObjUpdateTravIdCurrentId(p, Temp) ) + break; + 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/pdr/pdrCore.c b/src/proof/pdr/pdrCore.c index b98a4bbe37..34a3270347 100644 --- a/src/proof/pdr/pdrCore.c +++ b/src/proof/pdr/pdrCore.c @@ -697,7 +697,7 @@ int Pdr_ManGeneralize( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppP return -1; if ( RetValue == 0 ) { - p->tGeneral += clock() - clk; + p->tGeneral += Abc_Clock() - clk; return 0; } diff --git a/src/proof/ssw/ssw.h b/src/proof/ssw/ssw.h index 7299e37d1f..608b709e5a 100644 --- a/src/proof/ssw/ssw.h +++ b/src/proof/ssw/ssw.h @@ -74,6 +74,7 @@ struct Ssw_Pars_t_ int fEquivDump; // enables dumping equivalences int fEquivDump2; // enables dumping equivalences int fStopWhenGone; // stop when PO output is not a candidate constant + int nSkip; // optimized latch correspondence int fLatchCorrOpt; // perform register correspondence (optimized) int nSatVarMax; // max number of SAT vars before recycling SAT solver (optimized latch corr only) diff --git a/src/proof/ssw/sswAig.c b/src/proof/ssw/sswAig.c index acd8f919fe..ec744dc4b7 100644 --- a/src/proof/ssw/sswAig.c +++ b/src/proof/ssw/sswAig.c @@ -120,8 +120,10 @@ static inline void Ssw_FramesConstrainNode( Ssw_Man_t * p, Aig_Man_t * pFrames, // add the constraint if ( fTwoPos ) { - Aig_ObjCreateCo( pFrames, pObjNew2 ); - Aig_ObjCreateCo( pFrames, pObjNew ); + if ( p->pPars->nSkip == 0 ||rand() % p->pPars->nSkip == 0 ) { + Aig_ObjCreateCo( pFrames, pObjNew2 ); + Aig_ObjCreateCo( pFrames, pObjNew ); + } } else { @@ -158,6 +160,8 @@ Aig_Man_t * Ssw_FramesWithClasses( Ssw_Man_t * p ) Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreateCi(pFrames) ); // add timeframes iLits = 0; + if ( p->pPars->nSkip ) + srand(1); for ( f = 0; f < p->pPars->nFramesK; f++ ) { // map constants and PIs diff --git a/src/proof/ssw/sswPart.c b/src/proof/ssw/sswPart.c index 0c6e54cefe..89b6806848 100644 --- a/src/proof/ssw/sswPart.c +++ b/src/proof/ssw/sswPart.c @@ -32,6 +32,14 @@ #include #endif +#ifdef __cplusplus +#include +using namespace std; +#else +#include +#include +#endif + #endif @@ -98,17 +106,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 +127,7 @@ void * Ssw_GiaWorkerThread( void * pArg ) return NULL; } Cec_ManLSCorrespondenceClasses( pThData->p, &pThData->CorPars ); - pThData->fWorking = 0; + atomic_store_explicit(&pThData->fWorking, false, memory_order_release); } assert( 0 ); return NULL; @@ -144,37 +155,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, false, 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, true, 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, true, 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/bmc.h b/src/sat/bmc/bmc.h index 844497ad03..92fbb74225 100644 --- a/src/sat/bmc/bmc.h +++ b/src/sat/bmc/bmc.h @@ -62,9 +62,13 @@ struct Bmc_EsPar_t_ int fFewerVars; int fQuadrEnc; int fUniqFans; + int fLutCascade; int RuntimeLim; + int nRandFuncs; + int nMintNum; int fVerbose; char * pTtStr; + char * pSymStr; }; static inline void Bmc_EsParSetDefault( Bmc_EsPar_t * pPars ) @@ -84,9 +88,10 @@ static inline void Bmc_EsParSetDefault( Bmc_EsPar_t * pPars ) pPars->fEnumSols = 0; pPars->fFewerVars = 0; pPars->fQuadrEnc = 0; - pPars->fUniqFans = 0; + pPars->fUniqFans = 0; + pPars->fLutCascade = 0; pPars->RuntimeLim = 0; - pPars->fVerbose = 1; + pPars->fVerbose = 0; } @@ -227,7 +232,8 @@ extern int Gia_ManBmcPerform( Gia_Man_t * p, Bmc_AndPar_t * pPars extern Abc_Cex_t * Bmc_CexCareExtendToObjects( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare ); extern Abc_Cex_t * Bmc_CexCareMinimize( Aig_Man_t * p, int nRealPis, Abc_Cex_t * pCex, int nTryCexes, int fCheck, int fVerbose ); extern Abc_Cex_t * Bmc_CexCareMinimizeAig( Gia_Man_t * p, int nRealPis, Abc_Cex_t * pCex, int nTryCexes, int fCheck, int fVerbose ); -extern void Bmc_CexCareVerify( Aig_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexMin, int fVerbose ); +extern int Bmc_CexCareVerify( Aig_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexMin, int fVerbose ); +extern int Bmc_CexCareVerifyAnyPo( Aig_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexMin, int fVerbose ); extern Abc_Cex_t * Bmc_CexCareSatBasedMinimize( Aig_Man_t * p, int nRealPis, Abc_Cex_t * pCex, int fHighEffort, int fCheck, int fVerbose ); extern Abc_Cex_t * Bmc_CexCareSatBasedMinimizeAig( Gia_Man_t * p, Abc_Cex_t * pCex, int fHighEffort, int fVerbose ); /*=== bmcCexCut.c ==========================================================*/ @@ -238,6 +244,7 @@ extern Abc_Cex_t * Saig_ManCexMinPerform( Aig_Man_t * pAig, Abc_Cex_t * pC /*=== bmcCexTool.c ==========================================================*/ extern void Bmc_CexPrint( Abc_Cex_t * pCex, int nRealPis, int fVerbose ); extern int Bmc_CexVerify( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare ); +extern int Bmc_CexVerifyAnyPo( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare ); /*=== bmcICheck.c ==========================================================*/ extern void Bmc_PerformICheck( Gia_Man_t * p, int nFramesMax, int nTimeOut, int fEmpty, int fVerbose ); extern Vec_Int_t * Bmc_PerformISearch( Gia_Man_t * p, int nFramesMax, int nTimeOut, int fReverse, int fBackTopo, int fDump, int fVerbose ); diff --git a/src/sat/bmc/bmcCexCare.c b/src/sat/bmc/bmcCexCare.c index c274b04cbf..d9a677c356 100644 --- a/src/sat/bmc/bmcCexCare.c +++ b/src/sat/bmc/bmcCexCare.c @@ -455,8 +455,9 @@ Abc_Cex_t * Bmc_CexCareSatBasedMinimize( Aig_Man_t * p, int nRealPis, Abc_Cex_t SeeAlso [] ***********************************************************************/ -void Bmc_CexCareVerify( Aig_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexMin, int fVerbose ) +int Bmc_CexCareVerify( Aig_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexMin, int fVerbose ) { + int result; Gia_Man_t * pGia = Gia_ManFromAigSimple( p ); if ( fVerbose ) { @@ -465,11 +466,13 @@ void Bmc_CexCareVerify( Aig_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexMin, in printf( "Minimized: " ); Bmc_CexPrint( pCexMin, Gia_ManPiNum(pGia), 0 ); } - if ( !Bmc_CexVerify( pGia, pCex, pCexMin ) ) + result = Bmc_CexVerify( pGia, pCex, pCexMin ); + if ( !result ) printf( "Counter-example verification has failed.\n" ); else printf( "Counter-example verification succeeded.\n" ); Gia_ManStop( pGia ); + return result; } /* { @@ -480,6 +483,37 @@ void Bmc_CexCareVerify( Aig_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexMin, in } */ +/**Function************************************************************* + + Synopsis [Verifies the care set of the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bmc_CexCareVerifyAnyPo( Aig_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexMin, int fVerbose ) +{ + int iPo; + Gia_Man_t * pGia = Gia_ManFromAigSimple( p ); + if ( fVerbose ) + { + printf( "Original : " ); + Bmc_CexPrint( pCex, Gia_ManPiNum(pGia), 0 ); + printf( "Minimized: " ); + Bmc_CexPrint( pCexMin, Gia_ManPiNum(pGia), 0 ); + } + iPo = Bmc_CexVerifyAnyPo( pGia, pCex, pCexMin ); + if ( iPo < 0 ) + printf( "Counter-example verification has failed.\n" ); + else + printf( "Counter-example verification succeeded.\n" ); + Gia_ManStop( pGia ); + return iPo; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/sat/bmc/bmcCexTools.c b/src/sat/bmc/bmcCexTools.c index 6cc298577a..6bea6fc5f9 100644 --- a/src/sat/bmc/bmcCexTools.c +++ b/src/sat/bmc/bmcCexTools.c @@ -374,6 +374,53 @@ int Bmc_CexVerify( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare ) return Gia_ObjTerSimGet1(pObj); } +/**Function************************************************************* + + Synopsis [Verifies the care set of the counter-example for an arbitrary PO.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bmc_CexVerifyAnyPo( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare ) +{ + Gia_Obj_t * pObj; + int i, k; +// assert( pCex->nRegs > 0 ); +// assert( pCexCare->nRegs == 0 ); + Gia_ObjTerSimSet0( Gia_ManConst0(p) ); + Gia_ManForEachRi( p, pObj, k ) + Gia_ObjTerSimSet0( pObj ); + for ( i = 0; i <= pCex->iFrame; i++ ) + { + Gia_ManForEachPi( p, pObj, k ) + { + if ( !Abc_InfoHasBit( pCexCare->pData, pCexCare->nRegs + i * pCexCare->nPis + k ) ) + Gia_ObjTerSimSetX( pObj ); + else if ( Abc_InfoHasBit( pCex->pData, pCex->nRegs + i * pCex->nPis + k ) ) + Gia_ObjTerSimSet1( pObj ); + else + Gia_ObjTerSimSet0( pObj ); + } + Gia_ManForEachRo( p, pObj, k ) + Gia_ObjTerSimRo( p, pObj ); + Gia_ManForEachAnd( p, pObj, k ) + Gia_ObjTerSimAnd( pObj ); + Gia_ManForEachCo( p, pObj, k ) + Gia_ObjTerSimCo( pObj ); + } + for (i = 0; i < Gia_ManPoNum(p) - Gia_ManConstrNum(p); i++) + { + pObj = Gia_ManPo( p, i ); + if (Gia_ObjTerSimGet1(pObj)) + return i; + } + return -1; +} + /**Function************************************************************* Synopsis [Computes internal states of the CEX.] diff --git a/src/sat/bmc/bmcMaj.c b/src/sat/bmc/bmcMaj.c index 40ecd4a5e5..68601338ec 100644 --- a/src/sat/bmc/bmcMaj.c +++ b/src/sat/bmc/bmcMaj.c @@ -23,6 +23,9 @@ #include "misc/util/utilTruth.h" #include "sat/glucose/AbcGlucose.h" #include "aig/miniaig/miniaig.h" +#include "base/io/ioResub.h" +#include "base/main/main.h" +#include "base/cmd/cmd.h" ABC_NAMESPACE_IMPL_START @@ -950,7 +953,7 @@ void Exa_ManExactSynthesis( Bmc_EsPar_t * pPars ) } if ( status == GLUCOSE_UNDEC ) { - printf( "The problem timed out after %d sec.\n", pPars->RuntimeLim ); + printf( "The solver timed out after %d sec.\n", pPars->RuntimeLim ); break; } iMint = Exa_ManEval( p ); @@ -1044,6 +1047,23 @@ static int Exa3_ManMarkup( Exa3_Man_t * p ) // assign connectivity variables for ( i = p->nVars; i < p->nObjs; i++ ) { + if ( p->pPars->fLutCascade ) + { + if ( i > p->nVars ) + { + Vec_WecPush( p->vOutLits, i-1, Abc_Var2Lit(p->iVar, 0) ); + p->VarMarks[i][0][i-1] = p->iVar++; + } + for ( k = (int)(i > p->nVars); k < p->nLutSize; k++ ) + { + for ( j = 0; j < p->nVars - k + (int)(i > p->nVars); j++ ) + { + Vec_WecPush( p->vOutLits, j, Abc_Var2Lit(p->iVar, 0) ); + p->VarMarks[i][k][j] = p->iVar++; + } + } + continue; + } for ( k = 0; k < p->nLutSize; k++ ) { if ( p->pPars->fFewerVars && i == p->nObjs - 1 && k == 0 ) @@ -1208,6 +1228,61 @@ static void Exa3_ManPrintSolution( Exa3_Man_t * p, int fCompl ) } } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Exa3_ManDumpBlif( Exa3_Man_t * p, int fCompl ) +{ + int i, k, b, iVar; + char pFileName[1000]; + sprintf( pFileName, "%s.blif", p->pPars->pTtStr ); + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) return; + fprintf( pFile, "# Realization of given %d-input function using %d %d-input LUTs synthesized by ABC on %s\n", p->nVars, p->nNodes, p->nLutSize, Extra_TimeStamp() ); + fprintf( pFile, ".model %s\n", p->pPars->pTtStr ); + fprintf( pFile, ".inputs" ); + for ( k = 0; k < p->nVars; k++ ) + fprintf( pFile, " %c", 'a'+k ); + fprintf( pFile, "\n.outputs F\n" ); + for ( i = p->nObjs - 1; i >= p->nVars; i-- ) + { + fprintf( pFile, ".names" ); + for ( k = 0; k < p->nLutSize; k++ ) + { + iVar = Exa3_ManFindFanin( p, i, k ); + if ( iVar >= 0 && iVar < p->nVars ) + fprintf( pFile, " %c", 'a'+iVar ); + else + fprintf( pFile, " %02d", iVar ); + } + if ( i == p->nObjs - 1 ) + fprintf( pFile, " F\n" ); + else + fprintf( pFile, " %02d\n", i ); + int iVarStart = 1 + p->LutMask*(i - p->nVars); + for ( k = 0; k < p->LutMask; k++ ) + { + int Val = bmcg_sat_solver_read_cex_varvalue(p->pSat, iVarStart+k); + if ( Val == 0 ) + continue; + for ( b = 0; b < p->nLutSize; b++ ) + fprintf( pFile, "%d", ((k+1) >> b) & 1 ); + fprintf( pFile, " %d\n", i != p->nObjs - 1 || !fCompl ); + } + } + fprintf( pFile, ".end\n\n" ); + fclose( pFile ); + printf( "Finished dumping the resulting LUT network into file \"%s\".\n", pFileName ); +} + /**Function************************************************************* @@ -1424,12 +1499,22 @@ void Exa3_ManPrint( Exa3_Man_t * p, int i, int iMint, abctime clk ) printf( "Conf =%9d ", bmcg_sat_solver_conflictnum(p->pSat) ); Abc_PrintTime( 1, "Time", clk ); } -void Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ) +int Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ) { - int i, status, iMint = 1; + int i, status, Res = 0, iMint = 1; abctime clkTotal = Abc_Clock(); Exa3_Man_t * p; int fCompl = 0; - word pTruth[16]; Abc_TtReadHex( pTruth, pPars->pTtStr ); + word pTruth[16]; + if ( pPars->pSymStr ) { + word * pFun = Abc_TtSymFunGenerate( pPars->pSymStr, pPars->nVars ); + pPars->pTtStr = ABC_CALLOC( char, pPars->nVars > 2 ? (1 << (pPars->nVars-2)) + 1 : 2 ); + Extra_PrintHexadecimalString( pPars->pTtStr, (unsigned *)pFun, pPars->nVars ); + printf( "Generated symmetric function: %s\n", pPars->pTtStr ); + ABC_FREE( pFun ); + } + if ( pPars->pTtStr ) + Abc_TtReadHex( pTruth, pPars->pTtStr ); + else assert( 0 ); assert( pPars->nVars <= 10 ); assert( pPars->nLutSize <= 6 ); p = Exa3_ManAlloc( pPars, pTruth ); @@ -1457,15 +1542,54 @@ void Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ) if ( pPars->fVerbose && status != GLUCOSE_UNDEC ) Exa3_ManPrint( p, i, iMint, Abc_Clock() - clkTotal ); if ( iMint == -1 ) - Exa3_ManPrintSolution( p, fCompl ); + Exa3_ManPrintSolution( p, fCompl ), Res = 1; else if ( status == GLUCOSE_UNDEC ) - printf( "The problem timed out after %d sec.\n", pPars->RuntimeLim ); + printf( "The solver timed out after %d sec.\n", pPars->RuntimeLim ); else printf( "The problem has no solution.\n" ); printf( "Added = %d. Tried = %d. ", p->nUsed[1], p->nUsed[0] ); - Exa3_ManFree( p ); Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); + if ( iMint == -1 ) + Exa3_ManDumpBlif( p, fCompl ); + if ( pPars->pSymStr ) + ABC_FREE( pPars->pTtStr ); + Exa3_ManFree( p ); + return Res; } +void Exa3_ManExactSynthesisRand( Bmc_EsPar_t * pPars ) +{ + int i, k, nDecs = 0, nWords = Abc_TtWordNum(pPars->nVars); + word * pFun = ABC_ALLOC( word, nWords ); + Abc_Random(1); + printf( "\n" ); + for ( i = 0; i < pPars->nRandFuncs; i++ ) { + if ( pPars->nMintNum == 0 ) + for ( k = 0; k < nWords; k++ ) + pFun[k] = Abc_RandomW(0); + else { + Abc_TtClear( pFun, nWords ); + for ( k = 0; k < pPars->nMintNum; k++ ) { + int iMint = 0; + do iMint = Abc_Random(0) % (1 << pPars->nVars); + while ( Abc_TtGetBit(pFun, iMint) ); + Abc_TtSetBit( pFun, iMint ); + } + } + pPars->pTtStr = ABC_CALLOC( char, pPars->nVars > 2 ? (1 << (pPars->nVars-2)) + 1 : 2 ); + Extra_PrintHexadecimalString( pPars->pTtStr, (unsigned *)pFun, pPars->nVars ); + printf( "\nIteration %d : ", i ); + if ( pPars->nMintNum ) + printf( "Random function has %d positive minterms.", pPars->nMintNum ); + printf( "\n" ); + if ( pPars->fVerbose ) + printf( "Truth table : %s\n", pPars->pTtStr ); + nDecs += Exa3_ManExactSynthesis( pPars ); + ABC_FREE( pPars->pTtStr ); + } + printf( "Decomposable are %d (out of %d) functions (%.2f %%).\n", nDecs, pPars->nRandFuncs, 100.0*nDecs/pPars->nRandFuncs ); + ABC_FREE( pFun ); +} + /**Function************************************************************* @@ -1641,7 +1765,11 @@ Vec_Int_t * Exa4_ManSolve( char * pFileNameIn, char * pFileNameOut, int TimeOut, sprintf( pCommand, "%s --time=%d %s %s > %s", pKissat, TimeOut, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut ); else sprintf( pCommand, "%s %s %s > %s", pKissat, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut ); +#ifdef __wasm + if ( 1 ) +#else if ( system( pCommand ) == -1 ) +#endif { fprintf( stdout, "Command \"%s\" did not succeed.\n", pCommand ); return 0; @@ -3419,7 +3547,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; @@ -3663,7 +3791,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; @@ -3678,7 +3806,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; @@ -3700,10 +3828,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 ); @@ -3714,11 +3842,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 ); @@ -3885,6 +4039,62 @@ void Exa_ManExactSynthesis7( Bmc_EsPar_t * pPars, int GateSize ) Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Exa_NpnCascadeTest() +{ + char Buffer[100]; + char Command[1000]; int i; + FILE * pFile = fopen( "npn3.txt", "r" ); + for ( i = 0; i < 14; i++ ) +// FILE * pFile = fopen( "npn4.txt", "r" ); +// for ( i = 0; i < 222; i++ ) +// FILE * pFile = fopen( "npn5.txt", "r" ); +// for ( i = 0; i < 616126; i++ ) + { + int Value = fscanf( pFile, "%s", Buffer ); + assert( Value == 1 ); + if ( i == 0 ) continue; + if ( Buffer[strlen(Buffer)-1] == '\n' ) + Buffer[strlen(Buffer)-1] = '\0'; + if ( Buffer[strlen(Buffer)-1] == '\r' ) + Buffer[strlen(Buffer)-1] = '\0'; + sprintf( Command, "lutexact -I 3 -N 2 -K 2 -gvc %s", Buffer+2 ); + printf( "\nNPN class %6d : Command \"%s\":\n", i, Command ); + if ( Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ) ) + { + fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); + return; + } + } + fclose( pFile ); +} +void Exa_NpnCascadeTest6() +{ + char Command[1000]; int i; + Abc_Random(1); + for ( i = 0; i < 10000; i++ ) + { + word Truth = Abc_RandomW(0); + sprintf( Command, "lutexact -I 6 -N 2 -K 5 -gvc %016lx", Truth ); + printf( "\nIter %4d : Command \"%s\":\n", i, Command ); + if ( Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ) ) + { + fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); + return; + } + } +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/sat/bmc/bmcMaj2.c b/src/sat/bmc/bmcMaj2.c index 32bbc102f4..665b61611a 100644 --- a/src/sat/bmc/bmcMaj2.c +++ b/src/sat/bmc/bmcMaj2.c @@ -944,6 +944,23 @@ static int Exa3_ManMarkup( Exa3_Man_t * p ) // assign connectivity variables for ( i = p->nVars; i < p->nObjs; i++ ) { + if ( p->pPars->fLutCascade ) + { + if ( i > p->nVars ) + { + Vec_WecPush( p->vOutLits, i-1, Abc_Var2Lit(p->iVar, 0) ); + p->VarMarks[i][0][i-1] = p->iVar++; + } + for ( k = (int)(i > p->nVars); k < p->nLutSize; k++ ) + { + for ( j = 0; j < p->nVars - k + (int)(i > p->nVars); j++ ) + { + Vec_WecPush( p->vOutLits, j, Abc_Var2Lit(p->iVar, 0) ); + p->VarMarks[i][k][j] = p->iVar++; + } + } + continue; + } for ( k = 0; k < p->nLutSize; k++ ) { if ( p->pPars->fFewerVars && i == p->nObjs - 1 && k == 0 ) @@ -1159,6 +1176,61 @@ static void Exa3_ManPrintSolution( Exa3_Man_t * p, int fCompl ) } } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Exa3_ManDumpBlif( Exa3_Man_t * p, int fCompl ) +{ + int i, k, b, iVar; + char pFileName[1000]; + sprintf( pFileName, "%s.blif", p->pPars->pTtStr ); + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) return; + fprintf( pFile, "# Realization of given %d-input function using %d %d-input LUTs synthesized by ABC on %s\n", p->nVars, p->nNodes, p->nLutSize, Extra_TimeStamp() ); + fprintf( pFile, ".model %s\n", p->pPars->pTtStr ); + fprintf( pFile, ".inputs" ); + for ( k = 0; k < p->nVars; k++ ) + fprintf( pFile, " %c", 'a'+k ); + fprintf( pFile, "\n.outputs F\n" ); + for ( i = p->nObjs - 1; i >= p->nVars; i-- ) + { + fprintf( pFile, ".names" ); + for ( k = 0; k < p->nLutSize; k++ ) + { + iVar = Exa3_ManFindFanin( p, i, k ); + if ( iVar >= 0 && iVar < p->nVars ) + fprintf( pFile, " %c", 'a'+iVar ); + else + fprintf( pFile, " %02d", iVar ); + } + if ( i == p->nObjs - 1 ) + fprintf( pFile, " F\n" ); + else + fprintf( pFile, " %02d\n", i ); + int iVarStart = 1 + p->LutMask*(i - p->nVars); + for ( k = 0; k < p->LutMask; k++ ) + { + int Val = sat_solver_var_value(p->pSat, iVarStart+k); + if ( Val == 0 ) + continue; + for ( b = 0; b < p->nLutSize; b++ ) + fprintf( pFile, "%d", ((k+1) >> b) & 1 ); + fprintf( pFile, " %d\n", i != p->nObjs - 1 || !fCompl ); + } + } + fprintf( pFile, ".end\n\n" ); + fclose( pFile ); + printf( "Finished dumping the resulting LUT network into file \"%s\".\n", pFileName ); +} + /**Function************************************************************* @@ -1315,7 +1387,17 @@ void Exa3_ManExactSynthesis2( Bmc_EsPar_t * pPars ) int i, status, iMint = 1; abctime clkTotal = Abc_Clock(); Exa3_Man_t * p; int fCompl = 0; - word pTruth[16]; Abc_TtReadHex( pTruth, pPars->pTtStr ); + word pTruth[16]; + if ( pPars->pSymStr ) { + word * pFun = Abc_TtSymFunGenerate( pPars->pSymStr, pPars->nVars ); + pPars->pTtStr = ABC_CALLOC( char, pPars->nVars > 2 ? (1 << (pPars->nVars-2)) + 1 : 2 ); + Extra_PrintHexadecimalString( pPars->pTtStr, (unsigned *)pFun, pPars->nVars ); + printf( "Generated symmetric function: %s\n", pPars->pTtStr ); + ABC_FREE( pFun ); + } + if ( pPars->pTtStr ) + Abc_TtReadHex( pTruth, pPars->pTtStr ); + else assert( 0 ); assert( pPars->nVars <= 10 ); assert( pPars->nLutSize <= 6 ); p = Exa3_ManAlloc( pPars, pTruth ); @@ -1347,8 +1429,12 @@ void Exa3_ManExactSynthesis2( Bmc_EsPar_t * pPars ) } if ( iMint == -1 ) Exa3_ManPrintSolution( p, fCompl ); - Exa3_ManFree( p ); Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); + if ( iMint == -1 ) + Exa3_ManDumpBlif( p, fCompl ); + if ( pPars->pSymStr ) + ABC_FREE( pPars->pTtStr ); + Exa3_ManFree( p ); } diff --git a/src/sat/bsat/satSolver.c b/src/sat/bsat/satSolver.c index eea280293d..6b246a2e60 100644 --- a/src/sat/bsat/satSolver.c +++ b/src/sat/bsat/satSolver.c @@ -60,9 +60,10 @@ static void printlits(lit* begin, lit* end) static inline double drand(double* seed) { int q; *seed *= 1389796; - q = (int)(*seed / 2147483647); + q = (int)(*seed * 4.6566128752457969e-10); // 1.0/2147483647.0; *seed -= (double)q * 2147483647; - return *seed / 2147483647; } + return *seed * 4.6566128752457969e-10; // 1.0/2147483647.0 +} // Returns a random integer 0 <= x < size. Seed must never be 0. @@ -1954,12 +1955,12 @@ int sat_solver_solve_internal(sat_solver* s) while (status == l_Undef){ ABC_INT64_T nof_conflicts; - double Ratio = (s->stats.learnts == 0)? 0.0 : - s->stats.learnts_literals / (double)s->stats.learnts; if ( s->nRuntimeLimit && Abc_Clock() > s->nRuntimeLimit ) break; if (s->verbosity >= 1) { + double Ratio = (s->stats.learnts == 0)? 0.0 : + s->stats.learnts_literals / (double)s->stats.learnts; printf("| %9.0f | %7.0f %8.0f | %7.0f %7.0f %8.0f %7.1f | %6.3f %% |\n", (double)s->stats.conflicts, (double)s->stats.clauses, diff --git a/src/sat/bsat/satVec.h b/src/sat/bsat/satVec.h index 8cc8ba4eb5..305df9160c 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/bsat2/Alloc.h b/src/sat/bsat2/Alloc.h index a9786a9a88..1bf5784fcc 100644 --- a/src/sat/bsat2/Alloc.h +++ b/src/sat/bsat2/Alloc.h @@ -99,7 +99,11 @@ void RegionAllocator::capacity(uint32_t min_cap) cap += delta; if (cap <= prev_cap) +#ifdef __wasm + abort(); +#else throw OutOfMemoryException(); +#endif } // printf(" .. (%p) cap = %u\n", this, cap); @@ -121,7 +125,11 @@ RegionAllocator::alloc(int size) // Handle overflow: if (sz < prev_sz) +#ifdef __wasm + abort(); +#else throw OutOfMemoryException(); +#endif return prev_sz; } diff --git a/src/sat/bsat2/Vec.h b/src/sat/bsat2/Vec.h index f5f5499eaf..6937d7256d 100644 --- a/src/sat/bsat2/Vec.h +++ b/src/sat/bsat2/Vec.h @@ -98,7 +98,11 @@ 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(data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM)) +#ifdef __wasm + abort(); +#else throw OutOfMemoryException(); +#endif } diff --git a/src/sat/bsat2/XAlloc.h b/src/sat/bsat2/XAlloc.h index fdebe502ad..3e9e39674c 100644 --- a/src/sat/bsat2/XAlloc.h +++ b/src/sat/bsat2/XAlloc.h @@ -38,7 +38,11 @@ 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 }else return mem; } diff --git a/src/sat/cnf/cnfUtil.c b/src/sat/cnf/cnfUtil.c index e67328171e..3a47ae796f 100644 --- a/src/sat/cnf/cnfUtil.c +++ b/src/sat/cnf/cnfUtil.c @@ -82,7 +82,11 @@ Vec_Int_t *Cnf_RunSolverOnce(int Id, int Rand, int TimeOut, int fVerbose) FILE * pFile = fopen(FileNameIn, "rb"); if ( pFile != NULL ) { fclose( pFile ); +#if defined(__wasm) + if ( 1 ) { +#else if (system(pCommand) == -1) { +#endif fprintf(stdout, "Command \"%s\" did not succeed.\n", pCommand); return 0; } @@ -764,7 +768,11 @@ void Cnf_SplitCnfFile(char * pFileName, int nParts, int iVarBeg, int iVarEnd, in char Command[1000]; sprintf(Command, "satelite --verbosity=0 -pre temp.cnf %s", FileName); Cnf_DataWriteIntoFile(pCnf, "temp.cnf", 0, NULL, NULL); +#if defined(__wasm) + if ( 1 ) { +#else if (system(Command) == -1) { +#endif fprintf(stdout, "Command \"%s\" did not succeed. Preprocessing skipped.\n", Command); Cnf_DataWriteIntoFile(pCnf, FileName, 0, NULL, NULL); } diff --git a/src/sat/glucose/Alloc.h b/src/sat/glucose/Alloc.h index e56b54414d..9ceb5dcd00 100644 --- a/src/sat/glucose/Alloc.h +++ b/src/sat/glucose/Alloc.h @@ -100,7 +100,7 @@ void RegionAllocator::capacity(uint32_t min_cap) cap += delta; if (cap <= prev_cap) - throw OutOfMemoryException(); + fatal_out_of_memory(); } //printf(" .. (%p) cap = %u\n", this, cap); @@ -122,7 +122,7 @@ RegionAllocator::alloc(int size) // Handle overflow: if (sz < prev_sz) - throw OutOfMemoryException(); + fatal_out_of_memory(); return prev_sz; } diff --git a/src/sat/glucose/IntTypes.h b/src/sat/glucose/IntTypes.h index 3f75862b1b..5c4176b292 100644 --- a/src/sat/glucose/IntTypes.h +++ b/src/sat/glucose/IntTypes.h @@ -28,20 +28,18 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA # include # include -#else +#elif _WIN32 -#define __STDC_LIMIT_MACROS # include "pstdint.h" -//# include -#endif +#else -#include +# define __STDC_LIMIT_MACROS +# include +# include -#ifndef PRIu64 -#define PRIu64 "lu" -#define PRIi64 "ld" #endif + //================================================================================================= #include diff --git a/src/sat/glucose/Vec.h b/src/sat/glucose/Vec.h index da815e3013..a985a11144 100644 --- a/src/sat/glucose/Vec.h +++ b/src/sat/glucose/Vec.h @@ -100,7 +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)) - throw OutOfMemoryException(); + fatal_out_of_memory(); } diff --git a/src/sat/glucose/XAlloc.h b/src/sat/glucose/XAlloc.h index 233f834e02..e08584e4c2 100644 --- a/src/sat/glucose/XAlloc.h +++ b/src/sat/glucose/XAlloc.h @@ -34,12 +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){ - throw OutOfMemoryException(); + fatal_out_of_memory(); + return NULL; }else { return mem; } diff --git a/src/sat/glucose2/Alloc.h b/src/sat/glucose2/Alloc.h index b7bebacac1..6575020c7c 100644 --- a/src/sat/glucose2/Alloc.h +++ b/src/sat/glucose2/Alloc.h @@ -100,7 +100,7 @@ void RegionAllocator::capacity(uint32_t min_cap) cap += delta; if (cap <= prev_cap) - throw OutOfMemoryException(); + fatal_out_of_memory(); } //printf(" .. (%p) cap = %u\n", this, cap); @@ -122,7 +122,7 @@ RegionAllocator::alloc(int size) // Handle overflow: if (sz < prev_sz) - throw OutOfMemoryException(); + fatal_out_of_memory(); return prev_sz; } diff --git a/src/sat/glucose2/IntTypes.h b/src/sat/glucose2/IntTypes.h index 3f75862b1b..5c4176b292 100644 --- a/src/sat/glucose2/IntTypes.h +++ b/src/sat/glucose2/IntTypes.h @@ -28,20 +28,18 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA # include # include -#else +#elif _WIN32 -#define __STDC_LIMIT_MACROS # include "pstdint.h" -//# include -#endif +#else -#include +# define __STDC_LIMIT_MACROS +# include +# include -#ifndef PRIu64 -#define PRIu64 "lu" -#define PRIi64 "ld" #endif + //================================================================================================= #include diff --git a/src/sat/glucose2/Vec.h b/src/sat/glucose2/Vec.h index a087f29b35..1483ac798b 100644 --- a/src/sat/glucose2/Vec.h +++ b/src/sat/glucose2/Vec.h @@ -102,14 +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)) - throw OutOfMemoryException(); + 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)) - throw OutOfMemoryException(); + fatal_out_of_memory();; cap = ext_cap; } diff --git a/src/sat/glucose2/XAlloc.h b/src/sat/glucose2/XAlloc.h index 716643ef86..45a802ce56 100644 --- a/src/sat/glucose2/XAlloc.h +++ b/src/sat/glucose2/XAlloc.h @@ -34,12 +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){ - throw OutOfMemoryException(); + fatal_out_of_memory(); + return NULL; }else { return mem; } diff --git a/test.ps b/test.ps new file mode 100644 index 0000000000..7634275b22 Binary files /dev/null and b/test.ps differ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000000..5a187fcac7 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(gia) \ No newline at end of file diff --git a/test/gia/CMakeLists.txt b/test/gia/CMakeLists.txt new file mode 100644 index 0000000000..c9022dc8c0 --- /dev/null +++ b/test/gia/CMakeLists.txt @@ -0,0 +1,11 @@ +add_executable(gia_test gia_test.cc) + +target_link_libraries(gia_test + gtest + gtest_main + libabc +) + +gtest_discover_tests(gia_test + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) \ No newline at end of file diff --git a/test/gia/gia_test.cc b/test/gia/gia_test.cc new file mode 100644 index 0000000000..a6b288f791 --- /dev/null +++ b/test/gia/gia_test.cc @@ -0,0 +1,54 @@ +#include "gtest/gtest.h" + +#include "aig/gia/gia.h" + +ABC_NAMESPACE_IMPL_START + +TEST(GiaTest, CanAllocateGiaManager) { + Gia_Man_t* aig_manager = Gia_ManStart(100); + + EXPECT_TRUE(aig_manager != nullptr); + Gia_ManStop(aig_manager); +} + +TEST(GiaTest, CanAddACi) { + Gia_Man_t* aig_manager = Gia_ManStart(100); + Gia_ManAppendCi(aig_manager); + + EXPECT_EQ(Gia_ManCiNum(aig_manager), 1); + Gia_ManStop(aig_manager); +} + +TEST(GiaTest, CanAddACo) { + Gia_Man_t* aig_manager = Gia_ManStart(100); + int input1 = Gia_ManAppendCi(aig_manager); + Gia_ManAppendCo(aig_manager, input1); + + EXPECT_EQ(Gia_ManCiNum(aig_manager), 1); + EXPECT_EQ(Gia_ManCoNum(aig_manager), 1); + Gia_ManStop(aig_manager); +} + +TEST(GiaTest, CanAddAnAndGate) { + Gia_Man_t* aig_manager = Gia_ManStart(100); + + int input1 = Gia_ManAppendCi(aig_manager); + int input2 = Gia_ManAppendCi(aig_manager); + + int and_output = Gia_ManAppendAnd(aig_manager, input1, input2); + Gia_ManAppendCo(aig_manager, and_output); + + Vec_Wrd_t* stimulus = Vec_WrdAlloc(2); + Vec_WrdPush(stimulus, /*A*/1); + Vec_WrdPush(stimulus, /*B*/1); + Vec_Wrd_t* output = Gia_ManSimPatSimOut(aig_manager, stimulus, /*fouts*/1); + + EXPECT_EQ(Gia_ManCiNum(aig_manager), 2); + EXPECT_EQ(Gia_ManCoNum(aig_manager), 1); + // A = 1, B = 1 -> A & B == 1 + EXPECT_EQ(Vec_WrdGetEntry(output, 0), 1); + Vec_WrdFree(output); + Gia_ManStop(aig_manager); +} + +ABC_NAMESPACE_IMPL_END